CodeCannon deploy
Code Cannon: Bump the project version, create a GitHub Release, and promote to production — handles both versioning and releasing in one step
git clone https://github.com/LightbridgeLab/CodeCannon
T=$(mktemp -d) && git clone --depth=1 https://github.com/LightbridgeLab/CodeCannon "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/deploy" ~/.claude/skills/lightbridgelab-codecannon-deploy && rm -rf "$T"
.agents/skills/deploy/SKILL.mdCodex CLI: This skill is triggered by description matching. State any arguments in your message. Sub-agent spawning is not supported — perform any review steps inline.
What /deploy
does
/deploy/deploy is the final step in the workflow. It combines version bumping and release creation into a single command: check state, optionally bump the version, then create a GitHub Release (and in multi-branch mode, promote to production).
Step 1 — Verify branch
Run:
git branch --show-current
Required branch:
dev (two-branch mode).
If not on the required branch, abort and say: "Switch to
<required-branch> before running /deploy."
Pull the latest changes before proceeding:
git pull
Step 2 — Check current state
Find the latest version tag
git describe --tags --abbrev=0 2>/dev/null
If no tag exists, note this is the first release.
Read current version
cat VERSION
Show commits since last tag
If a previous tag exists, show what's on the branch since that tag:
git log main..dev --merges --pretty=format:"%s"
Parse PR numbers from merge commit subjects (format:
Merge pull request #N from branch/name).
For each PR number found, retrieve the PR body:
gh pr view <N> --json number,title,body
Extract
Issue #N and Closes #N references from PR bodies. Compile:
- List of PRs included (number + title)
- List of issues linked to those PRs
Check for open unmerged PRs
gh pr list --state open --json number,title,headRefName --jq '.[] | "#\(.number) \(.title) (\(.headRefName))"'
Present the summary
Tell the user:
Current version: X.Y.Z Latest tag: vX.Y.Z Commits/PRs since last tag: #17 — Add /docs directory #18 — Fix checkout runtime error Open PRs not yet merged: #19 — Add dark mode (feature/dark-mode) Would you like to bump the version before deploying? - **patch** → X.Y.C - **minor** → X.B.0 - **major** → A.0.0 - **specific** → enter a version number - **skip** → proceed to release with the latest existing tag
Wait for their response.
Step 3 — Version bump (if requested)
If the user chose to skip, find the latest version tag in the branch history:
git describe --tags --abbrev=0 2>/dev/null
If no tag is found at all (first release), warn: "No version tag found. You must bump the version before deploying." Return to the version bump prompt. Otherwise, use the tag found as the release version.
If the user chose a bump level, map their response to a command:
| User says | Run |
|---|---|
| "patch" / anything mentioning patch | |
| "minor" | |
| "major" | |
| A specific version e.g. "2.4.5" | |
These commands update the version manifest, create a git commit, and create a git tag. Do not create commits or tags manually.
Push the version bump:
git push git push --tags
Both the version bump commit and the tag must be pushed.
Step 4 — Compute release contents
Determine the version tag (either from the bump just performed, or from the existing HEAD tag if the user skipped bumping).
Find the previous tag to determine the range:
git describe --abbrev=0 <version-tag>^ 2>/dev/null
Use the PR/issue list already computed in Step 2. If the version bump added new commits, re-fetch if needed.
Step 5 — HUMAN GATE
Show the user the release summary. Example format:
Ready to release vX.Y.Z to production. PRs included: #17 — Add /docs directory #18 — Fix checkout runtime error Issues that will close: #14 — Add /docs directory #15 — Fix checkout runtime error Have you tested all of the above on preview? Type 'release' to confirm.
Wait for the user to type "release" or an explicit confirmation. Any other response → stop and ask what they'd like to change.
Step 6 — Create PR: dev
→ main
devmainFirst, create a temp directory for this invocation:
mkdir -p /tmp/CodeCannon && mktemp -d /tmp/CodeCannon/XXXXXX
Note the returned path (e.g.
/tmp/CodeCannon/a8f3b2). Use this path for all temp files in this invocation.
Then use your file-writing tool (not Bash) to create
<tmpdir>/release_pr_body.md:
Release vX.Y.Z PRs included: - #17 — Add /docs directory - #18 — Fix checkout runtime error Closes #14 Closes #15
Then create the PR (do NOT use
--body, --body-file -, or heredocs):
gh pr create --base main --head dev \ --title "Release vX.Y.Z" \ --body-file <tmpdir>/release_pr_body.md
Note the PR number from the output.
The
Closes #N lines will auto-close the linked issues because this PR merges into main (the default branch).
Critical: Use the unqualified
form only. Never write#N, even for same-repo refs — GitHub's closing-keyword parser only populatesCloses owner/repo#Nfor the unqualified form, and the qualified form silently breaks auto-close.closingIssuesReferences
Step 7 — Merge
Do NOT use
make merge — it refuses PRs targeting main. Use gh pr merge directly:
gh pr merge <pr-number> --merge
Step 8 — Create GitHub Release
The version tag (from Step 3) and the PR/issue list (from Step 4) are already known. Find the previous tag to build the changelog link:
git describe --abbrev=0 <version-tag>^ 2>/dev/null
If no previous tag exists, omit the "Full changelog" line.
Use your file-writing tool (not Bash) to create
<tmpdir>/release_notes.md (same temp directory from Step 6):
## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag>
Then create the release (do NOT use
--notes, --notes-file -, or heredocs):
gh release create <version-tag> \ --title "<version-tag>" \ --notes-file <tmpdir>/release_notes.md
Format each PR line as
- #<linked-issue> — <PR title> (PR #<N>). If a PR had no linked issue, omit the #<issue> prefix and use just the PR title.
After the command runs, note the release URL from the output.
Step 9 — Report
Tell the user:
<!-- generated by CodeCannon/sync.py | skill: deploy | adapter: codex | hash: 1a6fd564 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->"Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at
. Run<url>to ship to production."make deploy-prod