-
Notifications
You must be signed in to change notification settings - Fork 0
feat: /create-repository #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
23a6ab6
5c956c7
3036ea6
f818fae
89370c5
cac353e
8141854
d395a5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <!-- What problem does it solve or what feature does it add? --> | ||
| ## Overview | ||
|
|
||
| <!-- Summarize the key changes in the Pull Request. --> | ||
| ## Key Changes | ||
| - TBD: 1st key change of the PR | ||
| - TBD: 2nd key change of the PR | ||
|
|
||
| <!-- Add attached issue that this PR solves. --> | ||
| ## Related | ||
| Closes #issue_number |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,271 @@ | ||
| --- | ||
| name: create-repository | ||
| description: > | ||
| Creates and configures a brand-new GitHub repository under the Absa organizations: AbsaOSS (open source) | ||
| or absa-group (internal). Runs a short interactive interview, then an annotated gh command plan that | ||
| creates the repo from the shared cps-repository-template (copies file structure) and, as part of that setup, | ||
| adds theApache-2.0 license and populated CODEOWNERS file (open source repos), the standard Absa | ||
| label taxonomy (cloned from the template), the ruleset, and auto-delete-branches, plus project | ||
| links for internal repos. Use this whenever someone wants to create, spin up, scaffold, or | ||
| set up a new repository, project, codebase, or service repo under AbsaOSS or absa-group. Even if they don't | ||
| say "repository" explicitly. Do NOT use for modifying an existing repo (adding a single label, granting | ||
| access on a repo that already exists, creating branches, pull requests, issues, or workflow files, or | ||
| cloning). Use only for creating a new repository from scratch. | ||
| --- | ||
|
|
||
| # Create Repository | ||
|
|
||
| Interactive: **interview** → **plan** → **confirm once** → **execute** → **report**. | ||
| The skill is done once the repository exists and is configured. | ||
|
|
||
| Keep every prompt short. Move fast: when the user says yes or accepts a suggested default, take it and go | ||
| straight to the next step — no extra deliberation or re-confirmation. Ask follow-ups only when an answer is | ||
| genuinely unclear; the interview is designed so that shouldn't be necessary. | ||
|
|
||
| Wherever a step accepts multiple values (admins, code owners, projects), let the user separate them however | ||
| is natural — commas or spaces — and figure out the split yourself. Don't burden the prompt with formatting rules. | ||
|
|
||
| Keep the whole skill simple and explicit so it runs reliably even on smaller models: plain sequential `gh` | ||
| commands, no clever scripts, no helper languages, no temp files. | ||
|
|
||
| The repo is created **from the shared template** `absa-group/cps-repository-template`. Templating copies only | ||
| the files on the template's default branch — README, CONTRIBUTING, `appid.json`, and the `.github/` folder | ||
| (GitHub workflows, dependabot, issue/PR templates, and an **empty** CODEOWNERS). It does **not** copy labels, | ||
| rulesets, repository settings, collaborators, or a license — those remain explicit steps. | ||
|
|
||
| ## Step 0 — Preflight (before any questions) | ||
|
|
||
| Run `gh auth status`. If it exits non-zero, **stop immediately** and tell the user: | ||
|
|
||
| > This skill needs an authenticated GitHub CLI, logged in as a member of AbsaOSS / absa-group with | ||
| > permission to create repositories in that organization. | ||
| > Set a `GITHUB_TOKEN` (or run `gh auth login`) with the right scopes, then re-run. | ||
|
|
||
| Do not probe individual scopes — permission problems surface on the specific call at execution time. | ||
|
|
||
| ## The interview | ||
|
|
||
| Ask **exactly** these questions, in this order — the interview must be identical every time so the | ||
| experience is predictable. Items 1–4 are required; 5–6 are recommended (accepting the suggested option is | ||
| the fast path); 4 (code owners) is asked only for OSS repos; 7 (project link) is asked only for internal repos. | ||
|
|
||
| **Copy, don't compose.** Each step below gives the exact text after `Ask:` and, where present, an exact | ||
| `Options:` list. Use that text **verbatim, character for character** — don't rephrase the question, don't | ||
| add your own parenthetical hints, don't invent a Yes/No framing that isn't already in the text below. | ||
| If a step has no `Options:` list, it's freeform — just ask the question and take the raw answer. | ||
|
|
||
| **Always included at creation (no questions asked):** | ||
|
|
||
| - The repo is created **from the `absa-group/cps-repository-template`**, which brings a **README** and the | ||
| rest of the standard scaffolding — our repos must have at least README-level documentation. | ||
| - The **Apache-2.0** license on **OSS (`AbsaOSS`) repos only** — we always use it for open source. It's added | ||
| as a `LICENSE` file right after creation (the `--template` flag can't also apply a license). Internal | ||
| (`absa-group`) repos get no license (they're proprietary). | ||
| - The **Core Branches ruleset** on every repo — PR review with code-owner approval, the required "PR | ||
| Requirements" check, signed commits, and no force-push/deletion on the default branch. Applied from the | ||
| bundled `assets/rulesets.json`; not something the interview asks about. | ||
|
|
||
| The template auto-initializes the repo, so the default branch (`master`) exists before any configuration runs. | ||
|
|
||
| ### 1. Visibility (required) → derives the org | ||
|
|
||
| Ask: "Is this repository open source or internal?" Options: | ||
|
|
||
| - `Open source — AbsaOSS (public)` | ||
| - `Internal — absa-group (private)` | ||
|
|
||
| Strict 1:1 mapping, no separate org question, no cross-combinations: | ||
|
|
||
| - open source → org `AbsaOSS`, `--public` | ||
| - internal → org `absa-group`, `--private` | ||
|
|
||
| ### 2. Name (required) | ||
|
|
||
| Ask: "What should the repository be called? (e.g. aquasec-scan-results)" | ||
|
|
||
| Validate, in this order: | ||
|
|
||
| 1. **kebab-case** is the one mechanical rule (`^[a-z0-9]+(-[a-z0-9]+)*$`). If it doesn't match, offer a | ||
| friendly active fix using the normalized form (lowercase, `.`/spaces/camelCase boundaries → `-`): | ||
| "Use of the kebab-case style is highly recommended, would you like `event-gate` instead?" | ||
| 2. **Purpose & no people names** are advisory. A good name makes the repo's purpose clear to a first-time | ||
| reader, pattern `<system>-<purpose>` (e.g. `aquasec-scan-results`), and contains no personal names. If | ||
| the name looks non-descriptive or person-named, warn once, but accept it if the | ||
| user insists. Only kebab-case gets the active fix; these are overridable nudges. | ||
|
|
||
| **Assist fallback (opt-in, never first):** only if the user is unsure, ask them to describe the repo's | ||
| purpose and propose 1–3 kebab-case `<system>-<purpose>` candidates. | ||
|
|
||
| Don't check name availability — a collision surfaces when `gh repo create` runs. | ||
|
|
||
| ### 3. Admins (required, ≥1) | ||
|
|
||
| Ask: "Who should be repository admin? Enter one or more GitHub usernames." | ||
| Each becomes a repository admin. | ||
|
|
||
| ### 4. Code owners (OSS repos only, ≥1 user) | ||
|
|
||
| **Only ask this for open source (`AbsaOSS`) repos.** Internal (`absa-group`) repos keep the template's | ||
| empty `CODEOWNERS`. An always-on org-level ruleset **prohibits committing straight to the default branch** | ||
| on internal repos. | ||
|
|
||
| Ask: "Who should be the code owners?" Options: | ||
|
|
||
| - `Same people as the admins (@admin1, @admin2)` | ||
| - `Write a different set of code owners` | ||
|
|
||
| If the `Write a different set of code owners` option is chosen, ask: "Enter the GitHub usernames and/or | ||
| teams for the code owners." Individual users are written as `@username`; teams are written as | ||
| `@absa-group/team-slug`. | ||
|
|
||
| A single global `CODEOWNERS` rule covers all files, listing every entry the user provided. | ||
|
|
||
| ### 5. Labels (recommended) | ||
|
|
||
| The full Absa label taxonomy lives on the template. Ask: | ||
| "Do you want to clone the standard Absa label set (can be found at | ||
| https://github.com/absa-group/cps-repository-template/labels)?" Options: | ||
|
|
||
| - `Yes, add proposed label set (recommended)` | ||
| - `No, keep the GitHub default label set` | ||
|
|
||
| All-or-nothing: yes clones the taxonomy with a single `gh label clone` from | ||
| `absa-group/cps-repository-template`; no keeps only GitHub's built-in defaults. | ||
|
|
||
| ### 6. Auto-delete branches (recommended on) | ||
|
|
||
| Ask: "Auto-delete branches after merge?" Options: | ||
|
|
||
| - `Yes, auto-delete branches after merge (recommended)` | ||
| - `No, keep merged branches` | ||
|
|
||
| If yes, one PATCH sets `delete_branch_on_merge=true` on the repository. | ||
|
|
||
| ### 7. Project link(s) — internal repos only (recommended, 0:n) | ||
|
|
||
| **Only ask this for internal (`absa-group`) repos.** GitHub forbids linking a repository to a project | ||
| owned by a different org, and all Absa projects live under `absa-group`. | ||
| So an OSS (`AbsaOSS`) repo can never link to them — **skip this step entirely for OSS repos**, don't even ask. | ||
|
|
||
| For internal repos, ask: "Which absa-group project(s) should this be linked to? Enter project number(s), | ||
| or press Enter to skip." Empty → skip. | ||
|
|
||
| ## Build and confirm the plan | ||
|
|
||
| Present the plan **only for the steps that will actually run** — never list or mention steps that are | ||
| skipped (e.g. no project link on OSS repos; no license on internal repos). Don't explain what's being skipped or why. | ||
|
|
||
| Format the plan like this: a title line, then each step as a numbered plain-language sentence with its | ||
| command(s) in a fenced code block underneath. **Do not** write the descriptions as `#` comments inside the | ||
| code — the sentence goes above the block, the command goes in the block. Keep each description to one short | ||
| sentence; the user will ask if something is unclear. | ||
|
|
||
| ``` | ||
| Plan for repository `{owner}/{name}` creation ({OSS|internal}) | ||
|
|
||
| The repository will be created based on the CPS repo template (https://github.com/absa-group/cps-repository-template), | ||
| which also brings the standard scaffolding: README, CONTRIBUTING, the GitHub workflows, the PR and issue | ||
| templates, the dependabot config, and appid.json (update appid.json with its repo's own Support | ||
| contact and AppIds before deploying). | ||
|
|
||
| 1. Create the {public|private} repo from the template. | ||
| ``` | ||
| gh repo create {owner}/{name} --{public|private} --template absa-group/cps-repository-template | ||
| ``` | ||
|
|
||
| 2. Add the Apache-2.0 LICENSE. ← OSS repos only; omit the whole step otherwise | ||
| ``` | ||
| gh api -X PUT repos/{owner}/{name}/contents/LICENSE \ | ||
| -f message="Add Apache-2.0 license" \ | ||
| -f content="$(gh api /licenses/apache-2.0 --jq .body | base64)" | ||
| ``` | ||
|
|
||
| 3. Grant @{admin} admin access. ← one line per admin | ||
| ``` | ||
| gh api -X PUT repos/{owner}/{name}/collaborators/{admin} -f permission=admin | ||
| ``` | ||
|
|
||
| 4. Set .github/CODEOWNERS to "* @{owner1} @{owner2}". ← OSS repos only; omit the whole step otherwise | ||
| ``` | ||
| CO_SHA=$(gh api repos/{owner}/{name}/contents/.github/CODEOWNERS --jq .sha) | ||
| gh api -X PUT repos/{owner}/{name}/contents/.github/CODEOWNERS \ | ||
| -f message="Set CODEOWNERS" -f content="$(printf '* @{owner1} @{owner2}\n' | base64)" -f sha="$CO_SHA" | ||
| ``` | ||
|
|
||
| 5. Clone the full Absa label taxonomy from the template. | ||
| ``` | ||
| gh label clone absa-group/cps-repository-template --repo {owner}/{name} | ||
| ``` | ||
|
|
||
| 6. Apply the Core Branches ruleset. | ||
| ``` | ||
| gh api -X POST repos/{owner}/{name}/rulesets --input {skill-dir}/assets/rulesets.json | ||
| ``` | ||
|
|
||
| 7. Auto-delete head branches after merge. | ||
| ``` | ||
| gh api -X PATCH repos/{owner}/{name} -F delete_branch_on_merge=true | ||
| ``` | ||
|
|
||
| 8. Link the repository to project number {number} (https://github.com/orgs/absa-group/projects/{number}). ← private repos only (one block per project); omit otherwise | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should automatically ask for adding the scope if the user token doesn't have it:
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, this skill should do only repository creation scoped commands. If person does not have permission to add it to the absa-group project, then someone with correct permission should do it instead. This command is refreshing existing login token and requesting extra permission, which can be overlooked by skill user and cause not wanted outcomes. |
||
| ``` | ||
| REPO_ID=$(gh api repos/absa-group/{name} --jq .node_id) | ||
| PROJ_ID=$(gh api graphql -f query='query{organization(login:"absa-group"){projectV2(number:{number}){id}}}' --jq '.data.organization.projectV2.id') | ||
| gh api graphql -f query='mutation($p:ID!,$r:ID!){linkProjectV2ToRepository(input:{projectId:$p,repositoryId:$r}){repository{name}}}' -f p="$PROJ_ID" -f r="$REPO_ID" | ||
| ``` | ||
|
|
||
| Then ask one confirmation with these options: `Execute the plan` and there is by default Others. | ||
| Renumber the steps so they are sequential for whatever set actually applies (e.g. an internal repo has no | ||
| license step, so its steps still run 1, 2, 3, …). | ||
|
|
||
| ## Execute | ||
|
|
||
| On confirmation, run **exactly the commands shown in the approved plan, verbatim** — the plan is the | ||
| contract. The user only agreed to what they saw, so don't run anything extra or surprising: | ||
|
|
||
| - **No helper languages or scripts** — no `python`/`python3 -c`, no `node`, no bash loops, no reading assets | ||
| at runtime beyond the `--input {skill-dir}/assets/rulesets.json` already in the plan. Don't use `/tmp`. | ||
| - **No added output filters or parsing** — don't tack on `--jq`, `| grep`, `| head`, or similar that weren't | ||
| in the planned command. Run each `gh` line as-is. | ||
| - **No extra read-back / verification calls** — don't call `.../collaborators/{u}/permission`, re-`GET` the | ||
| repo, etc. Judge each step's success from its own exit status. | ||
| - **No proactive `sleep`s or waits, no pre-emptive conditional wrapping.** Run the CODEOWNERS `GET` exactly | ||
| as planned, as its own plain command — don't wrap it in an `if`/retry script "just in case". Only if that | ||
| call actually comes back 404 (template files still copying) do you react: run a plain `sleep 3`, then | ||
| re-run the exact same `GET` command once, plain, before treating it as a failure. This reactive retry is | ||
| the only deviation from "run the plan verbatim" that's ever allowed, and only fires after a real 404, not | ||
| before. | ||
|
|
||
| The only runtime-dynamic pieces are the `$(...)` captures already shown in the plan (CODEOWNERS `CO_SHA`, | ||
| the LICENSE `content=` base64, and the project-link `REPO_ID`/`PROJ_ID`); everything else is a literal `gh` command. | ||
|
|
||
| - If `gh repo create` (step 1) fails, abort — there's nothing to configure. Report the error (often a name | ||
| collision or a permissions problem). | ||
| - Everything after creation is independent. Use **best-effort**: if a call fails, keep going and collect the | ||
| failure. `gh label clone` already skips labels that exist; a ruleset that already exists (HTTP 422) is fine. | ||
|
|
||
| End with **exactly** the block below and nothing else — no leading line like "All steps succeeded", no | ||
| trailing commentary, no summary sentence before or after it. Output only the title line, a blank line, the | ||
| results table listing **only the steps that ran** (no skipped rows), a blank line, then the template link, in | ||
| that literal order, every time. For example (an OSS repo — no project-link row): | ||
|
|
||
| ``` | ||
| Repository `cps-test-repo` successfully created via /create-repository skill | ||
|
|
||
| | Step | Result | | ||
| | ----------------------------- | --------------------------------------------- | | ||
| | Create repo | ✓ https://github.com/AbsaOSS/cps-test-repo | | ||
| | Apache-2.0 license | ✓ | | ||
| | Admin | ✓ @admin-dev | | ||
| | CODEOWNERS | ✓ * @admin-dev | | ||
| | Labels | ✓ Cloned from template | | ||
| | Core Branches ruleset | ✓ | | ||
| | Auto-delete branches on merge | ✓ | | ||
|
|
||
| Template: https://github.com/absa-group/cps-repository-template | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am missing the information in this summary about which files are copied from the template repository. I think it can be useful for the user to know exactly what he created.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I added under Template another row called: Files copied from the template. See commit: d395a5d |
||
| Files copied from the template: README, CONTRIBUTING, appid.json, .github/ (workflows, dependabot, issue/PR templates, CODEOWNERS) | ||
| ``` | ||
|
|
||
| For internal repos, there is no CODEOWNERS row (that step is OSS-only); instead add a Link to project row | ||
| e.g. `| Linked project | ✓ project 203 |`. If a | ||
| step failed, show ✗ with a short reason on that row so the user can fix it manually. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| { | ||
| "name": "Core Branches Rules", | ||
| "target": "branch", | ||
| "enforcement": "active", | ||
| "conditions": { | ||
| "ref_name": { | ||
| "exclude": [], | ||
| "include": [ | ||
| "~DEFAULT_BRANCH" | ||
| ] | ||
| } | ||
| }, | ||
| "rules": [ | ||
| { | ||
| "type": "deletion" | ||
| }, | ||
| { | ||
| "type": "non_fast_forward" | ||
| }, | ||
| { | ||
| "type": "pull_request", | ||
| "parameters": { | ||
| "required_approving_review_count": 1, | ||
| "dismiss_stale_reviews_on_push": true, | ||
| "required_reviewers": [], | ||
| "require_code_owner_review": true, | ||
| "dismissal_restriction": { | ||
| "enabled": false, | ||
| "allowed_actors": [] | ||
| }, | ||
| "require_last_push_approval": true, | ||
| "required_review_thread_resolution": false, | ||
| "allowed_merge_methods": [ | ||
| "squash" | ||
| ] | ||
| } | ||
| }, | ||
| { | ||
| "type": "required_status_checks", | ||
| "parameters": { | ||
| "strict_required_status_checks_policy": true, | ||
| "do_not_enforce_on_create": false, | ||
| "required_status_checks": [ | ||
| { | ||
| "context": "PR Requirements" | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| { | ||
| "type": "required_signatures" | ||
| } | ||
| ], | ||
| "bypass_actors": [ | ||
| { | ||
| "actor_id": 5, | ||
| "actor_type": "RepositoryRole", | ||
| "bypass_mode": "always" | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "skill_name": "create-repository", | ||
| "evals": [ | ||
| { | ||
| "id": 1, | ||
| "prompt": "I need to create a new open-source repo under AbsaOSS for storing Aqua security scan results. Call it aquasec-scan-results. It's mainly a Python project. I should be the admin (my GitHub handle is jdoe) and also the code owner. Link it to absa-group project 17.", | ||
| "expected_output": "An annotated gh command plan that creates AbsaOSS/aquasec-scan-results as public from the cps-repository-template, adds the Apache-2.0 LICENSE, grants jdoe admin, sets CODEOWNERS with jdoe, clones the ABSA label taxonomy from the template, applies the Core Branches ruleset, sets auto-delete branches, and shows that the absa-group project link cannot be applied to an OSS repo (cross-org) — shown for confirmation before execution.", | ||
| "files": [] | ||
| }, | ||
| { | ||
| "id": 2, | ||
| "prompt": "Make me a new internal repository called EventGate. Admins should be asmith and bnguyen.", | ||
| "expected_output": "The skill flags EventGate as not kebab-case and offers event-gate, targets absa-group as private, creates it from the cps-repository-template, collects asmith and bnguyen as admins, offers to reuse them as code owners, and walks through labels/settings/project steps before showing an annotated plan.", | ||
| "files": [] | ||
| }, | ||
| { | ||
| "id": 3, | ||
| "prompt": "Set up a private repo under absa-group named schema-standards. Admin and code owner is myteammate1. No project link needed. Just the standard labels and auto-delete branches. No particular technology.", | ||
| "expected_output": "An annotated plan creating absa-group/schema-standards as private from the cps-repository-template with no license (internal), granting myteammate1 admin, CODEOWNERS with myteammate1, the ABSA label taxonomy cloned from the template, the Core Branches ruleset, auto-delete branches, and no project link call.", | ||
| "files": [] | ||
| } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the CODEOWNERS file for internal repositories empty in this step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is because CSO team added to every internal repository a mandatory
Check appid.json fileworkflow, that is added automatically. But they did not think about option to merge a commit straight without PR. So when we try to modify CODEOWNERS directly, the appid.json check is pending and the change is not possible without PR.