diff --git a/.atuin/skills/release/SKILL.md b/.atuin/skills/release/SKILL.md index a3c8f30e..c84fe511 100644 --- a/.atuin/skills/release/SKILL.md +++ b/.atuin/skills/release/SKILL.md @@ -48,6 +48,60 @@ After determining the version: --- +## Step 2.5 — Survey Release-Labeled PRs + +Two labels mark PRs whose merge has to be timed around the release. They are +typically PRs touching `docs/` or `install.sh` — changes that deploy on merge to +`main` rather than shipping inside the release artifact. + +| Label | Merged at | In the tag & artifact? | +|-------|-----------|------------------------| +| `merge-immediately-before-release` | Step 7.5 — after the prep PR merges, before the tag | Yes | +| `merge-immediately-after-release` | Step 8.5 — after the release workflow uploads assets | No | + +Check both: + +```bash +gh pr list --repo atuinsh/atuin --state open \ + --label merge-immediately-before-release \ + --json number,title,url +gh pr list --repo atuinsh/atuin --state open \ + --label merge-immediately-after-release \ + --json number,title,url +``` + +If both come back empty, say so and continue to Step 3. No checkpoint needed. + +The two labels are mutually exclusive: they name opposite sides of the tag. If a +PR number comes back in **both** lists, that is a labelling mistake — the two +queries are independent, so it would otherwise be approved twice, merged at Step +7.5, then merged again at Step 8.5 against an already-closed PR. **Stop** and ask +the user which single timing applies, then treat it as carrying only that label +for the rest of the release. Do not guess, and do not carry it into both steps. + +If either is non-empty: + +1. Show the user every PR found, grouped by label, with its number, title, and + the merge point from the table above. +2. **Checkpoint:** Use AskUserQuestion (multiSelect) to ask which of these PRs + should in fact be merged at their labeled time. +3. Record the approved set — it carries to Step 7.5 and Step 8.5. A PR the user + declines is left alone for the remainder of the release: don't merge it, + don't raise it again. + +Take each label at face value. It records the PR author's decision about timing; +it is not a suggestion for you to re-evaluate: + +- An `after-release` PR is **not** in the tag and **not** in the release + artifact. That is the intended outcome, not a problem to solve. The label is + for changes that deploy the moment they merge, so artifact inclusion is + irrelevant to them. An author who needed the change in the artifact would have + labeled it `merge-immediately-before-release`. +- Never merge an `after-release` PR early to get it into the release, and never + reclassify a PR from one label to the other. + +--- + ## Step 3 — Set Up Working Directory Clone a fresh copy into a temp directory: @@ -149,7 +203,7 @@ Create the PR: gh pr create \ --title "chore(release): prepare for release " \ --body "" \ - --repo atuinsh/atuin + --repo atuinsh/atuin \ --draft ``` @@ -159,6 +213,37 @@ When the user reports the PR is merged, proceed to the next step. --- +## Step 7.5 — Merge `merge-immediately-before-release` PRs + +Skip to Step 8 unless Step 2.5 recorded approved PRs with this label. + +The prep PR has merged and the tag does not exist yet. This is the only window +in which these PRs land in `v` and its artifacts. + +For each approved PR: + +1. Check it is still mergeable and its checks are green: + ```bash + gh pr view --repo atuinsh/atuin \ + --json mergeable,mergeStateStatus,statusCheckRollup + ``` + If it is not mergeable, or checks are red, report that and ask the user how + to proceed. Do not force it through. + +2. **Checkpoint:** Show the PR number and title and ask the user to confirm this + specific merge. Step 2.5 approved the *timing*; this confirms merging *now*. + +3. Merge: + ```bash + gh pr merge --repo atuinsh/atuin --squash + ``` + +These commits land in the tag but are absent from the changelog generated in +Step 5, which was cut before they merged. That is expected — do not regenerate +the changelog to include them. + +--- + ## Step 8 — Tag Release Back in the working directory: @@ -175,6 +260,62 @@ triggered. --- +## Step 8.5 — Merge `merge-immediately-after-release` PRs + +Skip to Step 9 unless Step 2.5 recorded approved PRs with this label. + +"After the release" means **after the release workflow has finished and the +assets exist** — not merely after the tag was pushed. These PRs deploy the +instant they merge, so a docs change announcing the new version must not go +live while the release it points at is still building. + +1. Wait for the release workflow the tag just triggered: + ```bash + gh run list --repo atuinsh/atuin --workflow release.yml \ + --branch "v" --limit 1 + gh run watch --repo atuinsh/atuin --exit-status + ``` + `--exit-status` is what makes a failed run exit non-zero. Without it + `gh run watch` prints the failure but still exits `0`, and a broken release + sails through into the merges below. If it exits non-zero, **stop** here — + do not go on to the release lookup. + +2. Confirm the release exists and has assets attached: + ```bash + gh release view "v" --repo atuinsh/atuin --json assets,isDraft + ``` + If the release is missing, is still a draft, or has no assets, **stop**. + Report it and merge nothing — these PRs keep until the release is actually + out. A release object alone is not evidence: it may predate this run or have + been left half-built by a failed workflow. What clears this gate is a + non-draft release with assets attached. + +3. Re-check that each approved PR is still mergeable and its checks are green: + ```bash + gh pr view --repo atuinsh/atuin \ + --json mergeable,mergeStateStatus,statusCheckRollup + ``` + Step 2.5 surveyed these PRs before the release was even built, so its + findings are now many minutes stale — long enough for a PR to pick up a + conflict or a red check. If it is not mergeable, or checks are red, report + that and ask the user how to proceed. Do not force it through. These PRs + deploy the instant they merge, so there is no CI gate downstream to catch a + bad one. + +4. **Checkpoint:** For each approved PR, show its number and title and ask the + user to confirm this specific merge. Step 2.5 approved the *timing*; this + confirms merging *now*. + +5. Merge each PR the user confirms: + ```bash + gh pr merge --repo atuinsh/atuin --squash + ``` + +Merging a `docs/` change here fires `trigger-docs-deploy.yml` and the docs go +out immediately. That is the whole point of the label. + +--- + ## Step 9 — Publish to crates.io **If this is a prerelease**, skip this step entirely and tell the user. @@ -211,5 +352,6 @@ Summarize what was done: - Version released - PR URL - Tag name +- Which label-timed PRs were merged, and which the user declined (if any) - Which crates were published (if any) - Working directory path and how to clean it up (`rm -rf`)