From 23a6ab606c14d327a5f79a33e1f3ed03691db595 Mon Sep 17 00:00:00 2001 From: "Tobias.Mikula" Date: Thu, 23 Jul 2026 11:53:42 +0200 Subject: [PATCH 1/5] feat: Repository creation skill. --- README.md | 1 + skills/create-repository/SKILL.md | 262 ++++++++++++++++++ skills/create-repository/assets/rulesets.json | 61 ++++ skills/create-repository/evals/evals.json | 23 ++ 4 files changed, 347 insertions(+) create mode 100644 skills/create-repository/SKILL.md create mode 100644 skills/create-repository/assets/rulesets.json create mode 100644 skills/create-repository/evals/evals.json diff --git a/README.md b/README.md index 6b1f500..da21bde 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ its purpose, trigger phrases, and full instructions. | Skill | Description | |------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| **[create-repository](./skills/create-repository/)** | Creates and configures a GitHub repository under AbsaOSS (open source) or absa-group (internal). Runs a short interview, then shows an annotated `gh` command plan and executes it on confirmation — visibility, naming, admins, CODEOWNERS, labels, merge settings, and project links. | | **[pr-review](./skills/pr-review/)** | Pull request code review — reviews diffs for risk, security issues, API contract changes, dependency bumps, CI/CD and infrastructure changes. Produces concise Blocker / Important / Nit comments. | | **[token-saving](./skills/token-saving/)** | Always-active response discipline — enforces brevity, no filler openers or closers, structured output, and a What/Why/How footer on code responses. Suspends on explicit "full detail" requests. | diff --git a/skills/create-repository/SKILL.md b/skills/create-repository/SKILL.md new file mode 100644 index 0000000..61ab1a1 --- /dev/null +++ b/skills/create-repository/SKILL.md @@ -0,0 +1,262 @@ +--- +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 (open source repos), admins, a populated CODEOWNERS file, 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 with org-admin permissions for AbsaOSS / absa-group. +> 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); 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 `-` (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 `-` 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 (required, ≥1 user) + +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 for +the code owners." + +A single global `CODEOWNERS` rule covers all files. Individuals only — no teams. + +### 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}". +``` +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}. ← private repos only (one line per project); omit otherwise +``` +gh project link {number} --owner absa-group --repo absa-group/{name} +``` + +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 ones already visible in the plan — the `CO_SHA=$(...)` capture for +CODEOWNERS and the `content="$(gh api /licenses/apache-2.0 --jq .body | base64)"` substitution in the LICENSE +step. 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 +``` + +For internal repos, add a Link to project row e.g. `| Linked project | ✓ #203 |`. If a +step failed, show ✗ with a short reason on that row so the user can fix it manually. diff --git a/skills/create-repository/assets/rulesets.json b/skills/create-repository/assets/rulesets.json new file mode 100644 index 0000000..2a7322c --- /dev/null +++ b/skills/create-repository/assets/rulesets.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/skills/create-repository/evals/evals.json b/skills/create-repository/evals/evals.json new file mode 100644 index 0000000..cee27c5 --- /dev/null +++ b/skills/create-repository/evals/evals.json @@ -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": [] + } + ] +} From 5c956c78c005cba02b1e74f5719a2ad453e9d28a Mon Sep 17 00:00:00 2001 From: "Tobias.Mikula" Date: Thu, 23 Jul 2026 11:53:42 +0200 Subject: [PATCH 2/5] feat: Repository creation skill. --- README.md | 1 + skills/create-repository/SKILL.md | 268 ++++++++++++++++++ skills/create-repository/assets/rulesets.json | 61 ++++ skills/create-repository/evals/evals.json | 23 ++ 4 files changed, 353 insertions(+) create mode 100644 skills/create-repository/SKILL.md create mode 100644 skills/create-repository/assets/rulesets.json create mode 100644 skills/create-repository/evals/evals.json diff --git a/README.md b/README.md index 6b1f500..da21bde 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ its purpose, trigger phrases, and full instructions. | Skill | Description | |------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| **[create-repository](./skills/create-repository/)** | Creates and configures a GitHub repository under AbsaOSS (open source) or absa-group (internal). Runs a short interview, then shows an annotated `gh` command plan and executes it on confirmation — visibility, naming, admins, CODEOWNERS, labels, merge settings, and project links. | | **[pr-review](./skills/pr-review/)** | Pull request code review — reviews diffs for risk, security issues, API contract changes, dependency bumps, CI/CD and infrastructure changes. Produces concise Blocker / Important / Nit comments. | | **[token-saving](./skills/token-saving/)** | Always-active response discipline — enforces brevity, no filler openers or closers, structured output, and a What/Why/How footer on code responses. Suspends on explicit "full detail" requests. | diff --git a/skills/create-repository/SKILL.md b/skills/create-repository/SKILL.md new file mode 100644 index 0000000..4a0b3e8 --- /dev/null +++ b/skills/create-repository/SKILL.md @@ -0,0 +1,268 @@ +--- +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 with org-admin permissions for AbsaOSS / absa-group. +> 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 `-` (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 `-` 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 for +the code owners." + +A single global `CODEOWNERS` rule covers all files. Individuals only — no teams. + +### 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 +``` +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 +``` + +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. diff --git a/skills/create-repository/assets/rulesets.json b/skills/create-repository/assets/rulesets.json new file mode 100644 index 0000000..2a7322c --- /dev/null +++ b/skills/create-repository/assets/rulesets.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/skills/create-repository/evals/evals.json b/skills/create-repository/evals/evals.json new file mode 100644 index 0000000..cee27c5 --- /dev/null +++ b/skills/create-repository/evals/evals.json @@ -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": [] + } + ] +} From f818fae38a8c4999b83cefc1582d2059107e2947 Mon Sep 17 00:00:00 2001 From: "Tobias.Mikula" Date: Thu, 23 Jul 2026 15:39:17 +0200 Subject: [PATCH 3/5] feat: Adding the PR template. --- .github/pull_request_template.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..a256715 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ + +## Overview + + +## Key Changes +- TBD: 1st key change of the PR +- TBD: 2nd key change of the PR From cac353e8f3e0a69e2e7e433276af777e8f3f1835 Mon Sep 17 00:00:00 2001 From: "Tobias.Mikula" Date: Thu, 23 Jul 2026 15:44:14 +0200 Subject: [PATCH 4/5] Updating the PR template. --- .github/pull_request_template.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a256715..713fbe8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,3 +5,7 @@ ## Key Changes - TBD: 1st key change of the PR - TBD: 2nd key change of the PR + + +## Related +Closes #issue_number From d395a5d331f6fa60f64d96e9ea7e9dec35e3c648 Mon Sep 17 00:00:00 2001 From: "Tobias.Mikula" Date: Fri, 24 Jul 2026 12:06:10 +0200 Subject: [PATCH 5/5] Reaction to the review comments. --- skills/create-repository/SKILL.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/skills/create-repository/SKILL.md b/skills/create-repository/SKILL.md index 4a0b3e8..4a5c3c1 100644 --- a/skills/create-repository/SKILL.md +++ b/skills/create-repository/SKILL.md @@ -37,7 +37,8 @@ rulesets, repository settings, collaborators, or a license — those remain expl Run `gh auth status`. If it exits non-zero, **stop immediately** and tell the user: -> This skill needs an authenticated GitHub CLI with org-admin permissions for AbsaOSS / absa-group. +> 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. @@ -113,10 +114,11 @@ 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 for -the 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. Individuals only — no teams. +A single global `CODEOWNERS` rule covers all files, listing every entry the user provided. ### 5. Labels (recommended) @@ -261,6 +263,7 @@ Repository `cps-test-repo` successfully created via /create-repository skill | Auto-delete branches on merge | ✓ | Template: https://github.com/absa-group/cps-repository-template +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