diff --git a/claude-skills/publish-release/SKILL.md b/claude-skills/publish-release/SKILL.md index 314d8f6..354a1ee 100644 --- a/claude-skills/publish-release/SKILL.md +++ b/claude-skills/publish-release/SKILL.md @@ -1,6 +1,6 @@ --- name: publish-release -description: Publish a new versioned release. Opens a version bump PR to develop, merges it, promotes develop to main via PR, tags main, and triggers the release pipeline. +description: Publish a new versioned release. Opens a version bump PR to develop, merges it, promotes develop to main via CLI --no-ff merge (never a GitHub PR), tags main, and triggers the release pipeline. --- Publish a new release based on the user's request: $ARGUMENTS @@ -41,35 +41,43 @@ gh pr create \ --base develop \ --head chore/release-v \ --title "chore: release v" \ - --body "Version bump to v. Merge to proceed with the develop→main release PR." + --body "Version bump to v. Merge to proceed with the develop→main CLI release merge." ``` Show the user the PR URL. Wait for CI to pass, then ask them to approve and merge it. -## Step 2 — Promote develop → main +## Step 2 — Promote develop → main via CLI merge -After the version bump PR is merged, open the develop→main release PR: +After the version bump PR is merged, promote develop to main with a non-fast-forward merge from the command line. -```bash -git checkout develop && git pull - -gh pr create \ - --base main \ - --head develop \ - --title "chore: release v" \ - --body "Promotes develop to main for release v. +> **Do NOT use a GitHub PR for this step.** GitHub's merge button squash-merges by default, which flattens every commit on develop into a single new commit on main with no ancestry relationship. On the next release, main and develop have diverged at every commit and every subsequent release hits merge conflicts. A `--no-ff` CLI merge preserves the commit graph so main remains a strict ancestor of develop. -After merging, the tag will be pushed to trigger the release pipeline." +```bash +git fetch origin +git checkout main && git pull +git merge --no-ff origin/develop -m "chore: release v" +git push origin main ``` -Show the user the PR URL and ask them to approve and merge it. +Confirm the push succeeded before moving to Step 3. -## Step 3 — Tag main after merge +> **Branch protection note:** if `main` has `enforce_admins: true` and required-PR review, the CLI push will be rejected. Toggle protection around the push: +> +> ```bash +> # Disable bypass-prevention temporarily +> gh api -X DELETE repos//branches/main/protection/enforce_admins +> +> # ...do the merge and push above... +> +> # Re-enable +> gh api -X POST repos//branches/main/protection/enforce_admins +> ``` +> +> The `amcheste-ai-agent` GitHub App needs `Administration: Read & Write` permission on the install for these toggles. The same dance applies to the `v*` tag ruleset in Step 3 if tag creation is restricted — toggle the ruleset's enforcement to `disabled` around the tag push, then back to `active`. -After the user confirms the develop→main PR is merged: +## Step 3 — Tag main ```bash -git checkout main && git pull git tag -a "v" -m "Release v" git push origin "v" ``` @@ -89,5 +97,5 @@ Show the user the release pipeline URL and confirm the tag was pushed. Let them Tell the user: - What version was tagged on `main` - That the pipeline is running: validate → VM acceptance → publish -- Where to watch it: `https://github.com/amcheste/mac-dev-setup/actions` +- Where to watch it: `https://github.com/amcheste//actions` - That `main` now equals the new release and `develop` is ready for the next cycle diff --git a/claude-skills/setup-repo/SKILL.md b/claude-skills/setup-repo/SKILL.md index 4f42ece..463bfe2 100644 --- a/claude-skills/setup-repo/SKILL.md +++ b/claude-skills/setup-repo/SKILL.md @@ -1,6 +1,6 @@ --- name: setup-repo -description: Apply standard branch model, protection rules, and settings to a GitHub repository. Creates develop branch, sets it as default, protects develop and main, and adds tag protection. +description: Apply standard branch model, protection rules, and settings to a GitHub repository. Creates develop branch, sets it as default, protects develop and main, adds tag protection, and verifies CODEOWNERS routing. --- Configure a GitHub repository with the standard branch model and protection rules: $ARGUMENTS @@ -13,7 +13,17 @@ Extract from the user's message: ## Pre-flight 1. Verify the repo exists: `gh repo view ` -2. Show the user what you're about to do and confirm before making any changes +2. **Refuse forks.** `setup-repo` configures the conventions of the *owner* of the repo. A fork is owned by upstream's conventions, not yours — applying your branching model, protections, and CODEOWNERS to it is wrong: + + ```bash + if [ "$(gh repo view --json isFork --jq .isFork)" = "true" ]; then + echo "ERROR: is a fork. setup-repo follows your conventions; forks follow upstream's. Aborting." + exit 1 + fi + ``` + + This also applies to audit scripts that survey "all my repos" — use `gh repo list --source` (filters out forks) instead of plain `gh repo list` so forks don't surface in the report. +3. Show the user what you're about to do and confirm before making any changes ## Step 1 — Ensure develop branch exists @@ -126,9 +136,35 @@ gh api repos//rulesets \ EOF ``` +## Step 6 — Verify CODEOWNERS routing + +Bot-authored PRs (via the `amcheste-ai-agent` GitHub App) need +`.github/CODEOWNERS` to auto-route review requests to a human reviewer. +Without this file, App-authored PRs don't appear in any reviewer's +queue (Graphite, GitHub's review-requested filter, etc.) and get lost. + +```bash +gh api repos//contents/.github/CODEOWNERS >/dev/null 2>&1 \ + && echo "✓ CODEOWNERS exists" \ + || echo "⚠ CODEOWNERS missing" +``` + +If the file is missing, **do not write it directly** — `setup-repo` only +configures settings/rulesets, never commits to the repo. Instead, surface +the gap in the summary so the user can add it via a PR. The canonical +default content is: + +``` +# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +* @amcheste +``` + +This pairs with the bot-account model documented in the +[engineering handbook](https://github.com/amcheste/engineering-handbook/blob/main/docs/design/claude-bot-account.md). + ## Summary -Report what was configured: +Report what was configured (and any gaps that need a follow-up PR): ``` ✓ develop branch created (or already existed) @@ -136,9 +172,11 @@ Report what was configured: ✓ develop protected — require PR + [checks] ✓ main protected — require PR + [checks] ✓ Tag ruleset active — v* tags protected +✓/⚠ CODEOWNERS verified (or: CODEOWNERS missing — see follow-ups) Next steps: - If using repo-template: copy .github/ files into this repo - Add project-specific lint/test steps to .github/workflows/validate.yml - Update required status check names to match your workflow job names +- If CODEOWNERS was missing, open a PR adding `.github/CODEOWNERS` with `* @amcheste` ```