Add release-train freeze/release-PR/unfreeze reusable workflows#32
Open
pnewsam wants to merge 3 commits into
Open
Add release-train freeze/release-PR/unfreeze reusable workflows#32pnewsam wants to merge 3 commits into
pnewsam wants to merge 3 commits into
Conversation
Centralizes the weekly staging→main release cycle as three reusable
(workflow_call) workflows so all repos share one source of truth, called
from ~25-line per-repo wrappers (same pattern as stale-deploy-label.yml).
- Auth via the mindsdb-release-train GitHub App (actions/create-github-app-token,
SHA-pinned) instead of a PAT; no standing admin, no PAT readable by public-repo
workflows.
- Freeze/unfreeze toggle a pre-provisioned `staging-freeze` ruleset's enforcement
(active/disabled) rather than round-tripping branch protection, so the toggle
can never clobber protection config. set-branch-lock.js is gone.
- actions/checkout and create-github-app-token SHA-pinned with version comments;
persist-credentials: false on the read-only checkouts.
- README documents prerequisites and the caller wrappers.
Callers keep the workflow names identical ("Staging Freeze" etc.) so the
workflow_run chain still fires. Fork-PR guard on unfreeze lives in the caller.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keeps the README caller wrappers in step with the callers shipped to the repos (CodeQL actions/missing-workflow-permissions). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 9, 2026
- Use `client-id` (not `app-id`) for actions/create-github-app-token — the stored credential is the App's client ID, not the numeric app id. - Rename reusable workflows to release-freeze.yml / release-pr.yml / release-unfreeze.yml (matches the step-by-step spec). - Ruleset toggle now GETs the full ruleset, flips only `enforcement`, and PUTs the whole body back (partial PUT does not guarantee omitted fields survive). Body written to a temp file, never echoed — three consumer repos are public. - Fail loudly if the staging-freeze ruleset is missing (provisioning drift). - Expose should_freeze (and ahead) as job outputs on the freeze workflow. - URL-encode the bot username (%5Bbot%5D) for the users API lookup. - README: rename table + caller `uses:` paths, note SHA-pinning callers. Co-Authored-By: Claude Opus 4.8 <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.
Summary
Centralizes the weekly
staging → mainrelease cycle into three reusable (workflow_call) workflows so all 7 release-train repos share one source of truth, driven by ~25-line per-repo caller wrappers (same pattern asstale-deploy-label.yml). This is the central PR that the per-repo release-train PRs (mindshub_inference#319 et al.) will call once merged.staging-freeze.ymlStaging Freezestaging-freezeruleset to lock staging (skips ifstaging == main)weekly-merge-staging.ymlCreate staging to main release PRstaging → mainPR (idempotent)staging-unfreeze.ymlStaging Unfreezemainback intostagingThe chain stays event-driven:
Staging Freezefinishing fires the release-PR workflow viaworkflow_run; merging that PR firesStaging Unfreeze.workflow_runmatches on the caller workflow's name, so callers keep the names verbatim.What changed vs. the original per-repo implementation
Implements the three structural changes from the coordinated review of the 7 release-train PRs:
actions/create-github-app-token(mindsdb-release-trainApp). No standing admin on any repo, and no PAT readable by workflows in the public repos. Readsvars.RELEASE_APP_CLIENT_ID+secrets.RELEASE_APP_PRIVATE_KEY(org-provisioned; the secret reaches the reusable workflows viasecrets: inherit).workflow_runchain still fires.staging-freezeruleset betweenenforcement: active/disabledinstead of round-tripping branch protection. Rulesets layer on top of protection, so the toggle can't clobber the protection config.set-branch-lock.jsis deleted (does not exist in this PR).Folded-in hardening
head.repo.full_name == github.repositoryalongsidehead.ref == 'staging') — lives in the caller wrapper.actions/checkout@34e1148…(v4.3.1),actions/create-github-app-token@bcd2ba4…(v3.2.0).persist-credentials: falseon the read-only checkouts (freeze, release-PR). Only the unfreeze sync-back checkout carries the App token, since it is the one step that pushes.47 13 * * 5(documented in the README;xx:00is GitHub's high-load slot and the old "6am PST" comment was only true in winter).Notes
github.repository/github.eventinside a reusable workflow reflect the caller repo, so the workflows operate on the calling repo with notarget-repoinput.GITHUB_TOKEN) so CI actually fires on it.staging.Prerequisites (provisioned once, org level, scoped to the 7 repos)
mindsdb-release-trainGitHub App (Administration / Contents / PRs: write), installed on each repo, set as bypass actor on the staging ruleset.vars.RELEASE_APP_CLIENT_ID(org variable) +secrets.RELEASE_APP_PRIVATE_KEY(org secret).staging-freezeruleset per repo (oneupdaterule onstaging, createddisabled, App as bypass actor).Rollout
Merge this first, then add caller wrappers (see README) per repo: canary on
cowork-serverwith one manual full cycle (freeze → release PR → merge → unfreeze → sync-back), then the remaining six.Refs Linear ENG-669.
🤖 Generated with Claude Code