Skip to content

ci: move the release cut into a GitHub Actions workflow - #28

Merged
boristane merged 2 commits into
mainfrom
claude/release-ci
Aug 13, 2026
Merged

ci: move the release cut into a GitHub Actions workflow#28
boristane merged 2 commits into
mainfrom
claude/release-ci

Conversation

@claude

@claude claude Bot commented Aug 12, 2026

Copy link
Copy Markdown

Requested by boris · Slack thread

Before: cutting a release means boris runs ./release.sh on his laptop — it bumps package.json, runs the checks, commits, tags, and pushes; the tag push then triggers the existing release.yml publish pipeline.

After: a Cut Release workflow in the Actions tab does the same thing. Pick "Cut Release" → Run workflow → enter the version (e.g. 0.3.0). Everything downstream (release.yml: npm publish, GitHub release, Homebrew bump) is unchanged and still triggers off the v* tag.

How

The workflow (.github/workflows/cut-release.yml) runs release.sh itself rather than duplicating its logic in YAML — one source of truth. The script got two minimal, backwards-compatible edits (it still works locally exactly as before):

  • CI mode (when CI is set): no interactive prompts — the version argument is required and the branch must be main, otherwise it dies.
  • RELEASE_DRY_RUN=1: runs the version bump and the full gate, then reverts the bump and exits before committing/tagging/pushing.

The order of operations is preserved: typecheck (codegen against the live prod OpenAPI spec — the hard gate that protects fresh installs from polylane.com), lint, test, and build all run before anything is committed, tagged, or pushed. If any check fails, no tag is created and release.yml never fires.

One non-obvious detail: the workflow pushes the version-bump commit and tag using a short-lived coreplane-bot GitHub App token, minted at run time from App credentials loaded out of the 1Password CI vault (the org-standard pattern used by our other repos) — not the default GITHUB_TOKEN. Tags pushed with GITHUB_TOKEN deliberately do not trigger other workflows, so release.yml would silently never run. Dry runs skip the 1Password/App-token steps entirely and check out with the default read-only token, since they never push.

Secrets to add

Before the first CI release, add this in repo Settings → Secrets and variables → Actions → New repository secret:

Secret Purpose
OP_SERVICE_ACCOUNT_TOKEN The org-standard 1Password service-account token — the same one the other repos (nominal, polylanedotcom, leaderboards, cloudevals, polylane-k8s) already use. It lets the workflow read the coreplane-bot App credentials from the 1Password CI vault and mint a short-lived App token with Contents: Read and write, which pushes the version-bump commit and v* tag so the push triggers release.yml.

The workflow also reads POLYLANE_API_DOMAIN, POLYLANE_OAUTH_CLIENT_ID, and POLYLANE_OAUTH_CLIENT_SECRET for the build gate — these already exist (used by checks.yml / release.yml), nothing new to add there.

Dry run

Run the workflow with dry_run checked: it bumps, runs the full gate (including the live-prod-spec typecheck), then reverts and stops — no commit, no tag, no publish. Dry runs skip the 1Password/App-token steps, so this works even before OP_SERVICE_ACCOUNT_TOKEN is configured — a good first smoke test of this PR.

Validation done here

  • bash -n release.sh and actionlint on all workflows: clean.
  • npm ci && npm run typecheck && npm run lint && npm run test && npm run build against the live prod spec: all pass.
  • Full CI-mode dry run exercised locally (CI=1 RELEASE_DRY_RUN=1 ./release.sh 9.9.9): bump → all checks → revert, exit 0; the no-version and wrong-branch CI guards both die as intended.
  • Not validated: an actual workflow_dispatch run on GitHub (needs the secret and a merge).

Generated by Claude Code

claude added 2 commits August 12, 2026 23:47
Releases previously required running ./release.sh locally. Add a
'Cut Release' workflow that runs release.sh in CI: bump package.json,
run the full gate (typecheck against the live prod OpenAPI spec, lint,
test, build), then commit, tag, and push. The v* tag push triggers the
existing release.yml publish pipeline unchanged.

release.sh changes are minimal and keep it usable locally:
- CI mode (CI env set): version arg required, branch must be main,
  no interactive prompts
- RELEASE_DRY_RUN=1: run the bump and all checks, then revert and
  exit before commit/tag/push

The workflow pushes with a RELEASE_PUSH_TOKEN PAT secret rather than
GITHUB_TOKEN, because tags pushed with GITHUB_TOKEN do not trigger
other workflows (release.yml would never fire).
…ored PAT

Replace the RELEASE_PUSH_TOKEN fine-grained PAT with the org-standard
pattern: load coreplane-bot GitHub App credentials from the 1Password CI
vault (op://CI/coreplane-bot) via load-secrets-action, mint a short-lived
App installation token with create-github-app-token, and hand that to
actions/checkout so release.sh's push still triggers release.yml.

Dry runs skip the 1Password/App-token steps entirely and check out with
the default read-only GITHUB_TOKEN, so they keep working without any
secret configured.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LekzRRztX696SLGyefENYm
@boristane
boristane merged commit 7c0c63a into main Aug 13, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants