fix(release): restore automatic release proposals on main

This commit is contained in:
morluto committed 2026-10-09 01:25:36 +08:00
1 parent 3db46813f8
commit acb3e0f2e5
4 files changed
+70 -13

No files matched your search

+18 -1
View File
@@ -1,6 +1,8 @@
name: Release
on:
push:
branches: [main]
workflow_dispatch:
inputs:
release_branch:
@@ -18,12 +20,27 @@ env:
HUSKY: "0"
concurrency:
group: release-${{ inputs.release_branch }}
group: release-${{ inputs.release_branch || github.ref_name }}
cancel-in-progress: false
jobs:
release-proposal:
name: Update release proposal
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: googleapis/release-please-action@v4
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
target-branch: main
skip-github-release: true
release-please:
name: Release Please
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: write
+7 -5
View File
@@ -138,11 +138,13 @@ Describe the behavior change and verification performed in the pull request. Nev
## Maintainer release checklist
Use the [checkpoint release guide](docs/releasing.md). Releases start from an
explicit `release/VERSION` branch cut at a recorded commit. Manually prepare
the bot PR, wait for its exact-head CI and review, merge into that frozen
branch, and manually publish through the official Release workflow. Main
pushes do not update release PRs or publish packages. Both publishers build
Use the [checkpoint release guide](docs/releasing.md). Main pushes automatically
refresh a release proposal with the next version and changelog. Keep this preview
PR unmerged until it is superseded by the published release's metadata sync.
Publication starts from an explicit `release/VERSION` branch cut at a recorded
application commit. Manually prepare its bot PR, wait for its exact-head CI and
review, merge into that frozen branch, and manually publish through the official
Release workflow. Main pushes cannot publish packages. Both publishers build
the exact SHA tagged by Release Please.
Keep new implementation commits on main for the next release. The workflow
+17 -5
View File
@@ -1,8 +1,12 @@
# Releasing from a checkpoint
REA releases use an explicit source checkpoint. Main can continue accepting
changes while a release is tested and published. The Release workflow runs
only when a maintainer dispatches it; main pushes do not refresh release PRs.
Pushes to main automatically open or refresh a Release Please proposal with
the next version and changelog. This proposal cannot create a GitHub release
or publish packages. It previews the next release as main continues changing.
Publication uses an explicit source checkpoint. A maintainer selects a frozen
release branch and dispatches preparation and publication, so main can keep
accepting changes without changing the candidate being tested.
## 1. Select the source
@@ -11,6 +15,12 @@ breaking changes. Record the full source SHA and create `release/VERSION` at
that commit. The version is a maintainer choice; Release Please's proposed
version must agree before publication.
Use the automatic main proposal to review the suggested version and notes.
Keep that proposal unmerged: select the application commit from main, create
the frozen branch, and prepare its own release PR using the steps below.
Merging the proposal into main would advance the release baseline before
publication. The reviewed frozen-branch PR is the publication candidate.
`release/VERSION` also sets the expected version for the workflow. Use an exact
SemVer such as `release/6.1.0` or `release/6.1.0-rc.1`, without build metadata.
The checkpoint validator rejects a candidate whose package, lockfile, manifest,
@@ -163,8 +173,10 @@ git fetch origin main --tags
git merge-base --is-ancestor rea-agents-5.0.0 origin/main
```
Close any superseded rolling release PR. Future releases repeat the checkpoint
procedure from main; never resume automatic release-PR refreshes on main pushes.
Close the superseded main proposal before merging the synchronization PR.
That merge's main push opens a proposal for the following release using the
updated baseline. Future publication repeats the checkpoint procedure;
automatic proposals do not move frozen branches.
Preparation generates and validates the catalog, portable conformance
projections, and packaged skill from the candidate checkout without committing
them. The checkpoint validator binds tracked version authority to the source
@@ -27,7 +27,9 @@ async function readReleaseWorkflow() {
return z
.object({
on: z.record(z.string(), z.unknown()),
concurrency: z.object({ group: z.string() }),
jobs: z.object({
"release-proposal": jobSchema,
"release-please": jobSchema,
publish: jobSchema,
"publish-mcp": jobSchema,
@@ -80,9 +82,33 @@ it("validates the source before release creation and the prepared candidate befo
}
});
it("requires explicit release preparation or publication instead of main pushes", async () => {
it("refreshes a release proposal on main pushes without creating or publishing a release", async () => {
const workflow = await readReleaseWorkflow();
expect(workflow.on.push).toEqual({ branches: ["main"] });
const proposal = workflow.jobs["release-proposal"];
expect(proposal.if).toBe("github.event_name == 'push'");
const action = proposal.steps.find((step) =>
step.uses?.startsWith("googleapis/release-please-action@"),
);
expect(action?.with).toMatchObject({
token: "${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}",
"target-branch": "main",
"skip-github-release": true,
});
expect(action?.with?.["skip-github-pull-request"]).not.toBe(true);
expect(workflow.jobs["release-please"].if).toBe(
"github.event_name == 'workflow_dispatch'",
);
for (const job of [workflow.jobs.publish, workflow.jobs["publish-mcp"]]) {
expect(job.if).toContain("inputs.phase == 'publish'");
}
expect(workflow.concurrency.group).toBe(
"release-${{ inputs.release_branch || github.ref_name }}",
);
});
it("keeps frozen candidate preparation and publication explicit", async () => {
const workflow = await readReleaseWorkflow();
expect(Object.keys(workflow.on)).toEqual(["workflow_dispatch"]);
expect(workflow.on.workflow_dispatch).toMatchObject({
inputs: {
release_branch: { required: true, type: "string" },