Repository navigation
chore(release): replace AI release scripts with a Claude Code release skill - #1300
dangrondahl wants to merge 1 commit into
Conversation
… skill The release skill drafts the next semver tag and dist/release_notes.md with the releaser, then hands off to `make release tag=vX.Y.Z`, which remains the only path that creates and pushes the annotated tag. This removes bin/suggest-version-ai.sh, bin/release-interactive.sh and the suggest-version-ai make target, and with them the shared Anthropic API key in 1Password: the skill runs under the releaser's own Claude login. `make release` now requires tag=.
|
Claude finished @dangrondahl's task in 1m 52s —— View job PR review: replace AI release scripts with a Claude Code
|
|
|
||
| **1. Check the starting point.** Run `git fetch origin --tags`. Confirm the current | ||
| branch is `main`, it matches `origin/main`, and the working tree has no tracked changes. | ||
| Find the base with `git describe --tags --abbrev=0`. If any check fails, stop and tell |
There was a problem hiding this comment.
git describe --tags --abbrev=0 returns the nearest tag, and that includes pre-release tags. The repo has some already (v2.0.0-rc3, v2.10.3-rc5, …). Once a v2.49.0-rc1 exists, the base becomes the rc. Step 3's "base + bump" then gives an unclear answer (v2.49.0-rc1 + minor = ?), and the notes leave out everything that shipped before the rc. The old script had the same problem, but this is an easy place to fix it:
| Find the base with `git describe --tags --abbrev=0`. If any check fails, stop and tell | |
| Find the base with `git describe --tags --abbrev=0 --match 'v[0-9]*' --exclude '*-*'` (the last stable release; pre-release tags are skipped). If any check fails, stop and tell |
| **6. Tag and push.** Pushing the tag starts the release pipeline, so ask once more: | ||
| "Create and push `<tag>`?". On a yes, run `make release tag=<tag>`. Then report the run | ||
| with `gh run list --workflow release.yml --limit 1`. |
There was a problem hiding this comment.
Two small issues with the last step:
- Leftover notes file. After a successful push,
dist/release_notes.mdstays on disk. The next hand-runmake release tag=quietly uses it as the tag body. The PR description and the guide both mention this, but the skill can prevent it by deleting the file. The old script had atrapthat did a similar cleanup. - Wrong run reported.
gh run list --workflow release.yml --limit 1runs straight after the push. GitHub often hasn't registered the new run yet, so this can show the previous release. A tag push's run hasheadBranchset to the tag name, so filtering on the tag avoids that.
| **6. Tag and push.** Pushing the tag starts the release pipeline, so ask once more: | |
| "Create and push `<tag>`?". On a yes, run `make release tag=<tag>`. Then report the run | |
| with `gh run list --workflow release.yml --limit 1`. | |
| **6. Tag and push.** Pushing the tag starts the release pipeline, so ask once more: | |
| "Create and push `<tag>`?". On a yes, run `make release tag=<tag>`, then delete | |
| `dist/release_notes.md` so a later hand-run `make release` can't reuse it. Report the run | |
| with `gh run list --workflow release.yml --branch <tag> --limit 1` (retry for a few seconds if it isn't listed yet). |
| @@ -0,0 +1,54 @@ | |||
| --- | |||
| name: release | |||
| description: Cut a Kosli CLI release - suggest the next semver tag from the changes since the last tag, draft the release notes with the user, then tag and push via `make release`. Use when asked to "release", "cut a release", "tag a new version", or "draft release notes". | |||
There was a problem hiding this comment.
Something to consider: the last step of this skill pushes a release tag, and the description triggers on loose phrases like "draft release notes" and "tag a new version". If you want it to run only on an explicit /release, add disable-model-invocation: true to the frontmatter. Steps 5 and 6 already ask for confirmation twice, so this is optional. It does mean Claude won't load the skill by itself, though, which goes against the "or ask Claude to cut a release" path in the PR description. Your call.
| ([ -f dist/release_notes.md ] && git tag -a $(tag) --cleanup=verbatim -F dist/release_notes.md) || git tag -a $(tag) -m"$(tag)"; \ | ||
| git push origin $(tag); \ | ||
| fi | ||
| if [ -z "$(tag)" ]; then echo "Usage: make release tag=vX.Y.Z (or run /release in Claude Code to draft version and notes)"; exit 1; fi; \ |
There was a problem hiding this comment.
Nit: this check comes after the main branch check. So running a bare make release from a feature branch prints "must be run from main" rather than the usage line that points to /release. Putting the tag check first would show the usage hint wherever it's run. It's harmless either way.
💊 Red pill. One of two alternative PRs that remove the shared Anthropic API key from the release flow. Only one should merge; the other is the blue pill, #1299.
The scripted AI step is replaced by a Claude Code skill,
.claude/skills/release/. Run/release(or ask Claude to cut a release) and it:mainand finds the last tag.dist/release_notes.md(same scope and heading rules as the old prompt).make release tag=vX.Y.Zand shows the release workflow run.make release tag=stays the only path that creates the annotated tag. Also in this PR:bin/suggest-version-ai.sh,bin/release-interactive.shand thesuggest-version-aitarget.make releasenow requirestag=and points at/releasewhen it's missing.CLAUDE.mdandrelease-guide.md.Choose this if you're happy for releasing with AI help to require Claude Code. In return, the release notes are drafted in conversation, and Claude can read commit messages and PR titles, not only a diff capped at 50k characters.
Not yet exercised end to end: the skill only runs from
main, and its last step pushes a tag. It loads, andmake helpshows the new target text. A leftoverdist/release_notes.mdwould end up in a hand-runmake release tag=; the guide warns about this.Checklist
charts/k8s-reporter/) updated, if needed (n/a)