Repository navigation
ci: automated beta → latest → stable release pipeline - #97
Merged
Merged
Conversation
PRs into master are type-checked, tested and built. Each merge that changes the published package cuts the next X.Y.Z-beta.N under the npm `beta` tag; a beta that soaks 14 days with no Jira bugs labelled ryuu.js-X.Y.Z ships as `latest` (with a release/vX.Y.Z branch), and a GA with 30 bug-free days is tagged `stable`. Publishing uses npm trusted publishing; automatic runs stay off until the RELEASE_ENABLED repo variable is `true`. Setup and runbook: RELEASING.md. Supersedes #65. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Customers who resolve `latest` (plain installs, CDN URLs, and npm ranges like ^6.0.9) now only move to a version that has passed both soaks. A beta that soaks 14 bug-free days is republished unchanged as X.Y.Z-rc.N under `rc`; an rc that soaks 30 bug-free days becomes X.Y.Z under `latest` with its release/vX.Y.Z branch. Betas and rcs are prereleases, so no package manager resolves them from a normal range. The separate `stable` dist-tag, its jobs and the second npm trusted publisher are gone. force_rc/force_ga cover urgent fixes, and verify-tag.sh now checks the whole GA → rc → beta → master chain. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
RELEASING.md now walks through the beta → rc → latest cycle with a Mermaid flowchart, an example rollout (Gantt chart plus a day-by-day table), what each interrupt does, every variable, secret and Run workflow option with its UI path and gh command, and a one-time setup checklist. Adds `npm run release:plan` (what Release would do now, with SIMULATE_NOW / MASTER_REF) and `npm run release:rehearse` (merge → beta → publish rehearsal in a throwaway clone that never pushes or publishes). The main README gains a release channels table and a pointer to RELEASING.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Soaks drop from 14 + 30 days to about two weeks: a line becomes an rc once its first beta is 7 days old and its newest beta has been quiet for 3 days, and an rc reaches latest after 7 bug-free days. New betas restart only the quiet clock, so steady merging can no longer hold a release back forever. A merged PR labelled release:hotfix sends its release straight through: Release looks up the label when it cuts the beta (scripts/ci/github.ts), records "(hotfix)" in the tag annotation, and the following runs promote the beta, rc and latest back to back without the soaks or the Jira check. Every build, test, tag verification and package-identity check still runs. RELEASING.md, README and CLAUDE.md are updated for the new timings, with a Hotfixes section and a recomputed example rollout. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Acting on five independent reviews of the release pipeline: Trust boundary - Resolve master as refs/remotes/origin/master everywhere; a tag named origin/master used to shadow it and let an attacker's commit be built. - Split release.yml into plan / prepare / push. Build and tests now run in a job with no secrets; the deploy key only reaches a job that runs git and bash and re-verifies the tag. force_rc/force_ga need the admin role. The release:hotfix label only counts if a maintainer or admin applied it before the PR merged (scripts/ci/github.ts). - verify-tag.sh no longer fails open on big lockfiles or npm errors. Decision logic - Retry a GA publish even when the next version's betas are already on npm. - A labelled hotfix always releases and is looked up before the soak gates, so a no-op labelled PR cannot make a later PR a hotfix and a Jira outage cannot block one. - The first-beta clock is capped at 14 days so frequent merging cannot starve a release; a one-hour grace makes cron timing predictable. - Lowering master's version never moves the line back, a rolled-back latest cannot re-release a superseded rc, and master's own version counts as taken so "start 6.1.0" no longer wedges the pipeline. Workflows: queue: max so pending runs are not cancelled, job timeouts, and dispatch on refs/tags/. Adds tests for verify-tag, push-release and same-artifact against real git repos, and updates RELEASING.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Takes master's Dependabot bumps and re-applies this PR's two dependency changes (standard-version removed, @types/node added) to package-lock.json. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
verify-tag's "not a pipeline tag" test made an annotated tag with no identity. It passed on a laptop with a global git identity and failed on the CI runner, which has none. The helper now configures one per repo, and the ci project passes with HOME and the global git config removed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ent the scripts Because every PR is squash-merged, the commit being released is one PR, so the hotfix check now looks only at master's latest commit instead of scanning a range of up to 50. That removes the verdict cache and the case where a labelled PR that shipped nothing made a later, unrelated merge look like a hotfix, so prepare-release.sh no longer needs to release an unchanged package for a hotfix. If another PR lands before Release runs, the change takes the normal soak, which can only be slower, never faster. github.ts follows CONVENTIONS.md (no push/pop, no guard-then-assign) and uses clearer names (verifyLabel, isTrustedLabel). Every named function in lib.ts, jira.ts, github.ts and release.ts now has a plain-language JSDoc block with @PARAM and @returns; the compiled output is unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
plumppig
added a commit
that referenced
this pull request
Oct 10, 2026
With no RELEASE_DEPLOY_KEY secret, actions/checkout quietly falls back to the read-only workflow token. A dry run then passed, and a real run only failed at the very end of the push job with a bare 403 (seen on the first run after #97 merged). The push job now starts by failing if the secret is empty, and asserts that checkout used an SSH remote. push-release.sh turns a rejected push into a message that names the likely causes: a missing or read-only deploy key, or rulesets that deploy keys cannot bypass. RELEASING.md describes what a green dry run does and does not prove, and lists the three failure messages. Co-authored-by: JSON <Jason.Hansen@domo.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an automated release pipeline: PRs into master are type-checked, tested and built, and each merge that changes the package publishes the next beta. A version becomes an rc after its first beta is 7 days old and its newest has been quiet for 3 (capped at 14), then reaches latest after 7 more days with no Jira bugs labeled ryuu.js-X.Y.Z, and a release:hotfix label applied by a maintainer skips both soaks. Releases stay off until the RELEASE_ENABLED repo variable is true; setup is in RELEASING.md, and this supersedes #65.