diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 30a4417..58d1e76 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -658,6 +658,11 @@ jobs: "+refs/heads/${RELEASE_BRANCH}:refs/remotes/origin/${RELEASE_BRANCH}" release_ref="refs/remotes/origin/${RELEASE_BRANCH}" branch_sha="$(git rev-parse "$release_ref")" + branch_parent="$(git rev-parse "${release_ref}^")" + if [[ "$branch_parent" != "$GITHUB_SHA" ]]; then + echo "The prepared Release Please branch is not based directly on current main." >&2 + exit 1 + fi gh api --paginate --slurp \ "repos/${GITHUB_REPOSITORY}/pulls?state=open&base=main&per_page=100" \ | jq 'add' > "$pull_requests_file" diff --git a/AGENTS.md b/AGENTS.md index d25d86e..ec32281 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -86,13 +86,17 @@ manually against the exact merged release commit, and the publish workflow completed exact-artifact verification, the bounded live smoke, npm OIDC publication, and registry verification. -Release Please remains disabled between releases after its post-0.1.0 run -generated an unreviewed `0.2.0` temporary-branch commit and then failed to create -a pull request. The temporary branch is failure evidence only. Do not merge it -or use it as a 0.2 starting point. The authorized 0.1.1 maintenance task repairs -the workflow around the current read-only-default Actions baseline with +Release Please remains disabled between release operations after its post-0.1.0 +run generated an unreviewed `0.2.0` temporary-branch commit and then failed to +create a pull request. That branch was verified as failure-only evidence before +the authorized 0.1.1 operation replaced it with the action-owned patch branch. +Do not use either branch as a 0.2 starting point. The 0.1.1 maintenance task +repairs the workflow around the current read-only-default Actions baseline with action-created pull requests enabled; any later enablement still requires an explicit maintainer request and the fail-closed checks in `RELEASING.md`. +For this repair, merge the anchor-removal finalization PR first, then use a new +first-attempt manual dispatch to refresh the same action-owned 0.1.1 PR before +its final CI and human-owner review. ## Product Contract diff --git a/README.md b/README.md index 70f4d4c..7b0a262 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ defaulting the client to CometAPI. > The supported API is limited to the contract-tested 0.1 surface documented > here and in [COMPATIBILITY.md](./COMPATIBILITY.md). > -> A `0.1.1` maintenance release is being prepared to correct the public options -> contract and restore the normal Release Please path. It is not released until -> the immutable release, npm OIDC publication, and public-registry verification -> complete. +> **Approved maintenance candidate:** `0.1.1` is approved for npm publication +> through the reviewed Release Please path. This approval is not a release +> claim: `0.1.1` remains unpublished until the immutable release, npm OIDC +> publication, and public-registry verification complete. ## Supported 0.1 surface @@ -58,9 +58,9 @@ For source-checkout testing, retain and verify one exact tarball: ```bash mkdir -p .artifacts npm pack --pack-destination .artifacts -npm run test:package -- --tarball .artifacts/cometapi-0.1.0.tgz -npm run test:examples -- --tarball .artifacts/cometapi-0.1.0.tgz -npm run test:fixtures -- --tarball .artifacts/cometapi-0.1.0.tgz +npm run test:package -- --tarball .artifacts/cometapi-$(node -p 'require("./package.json").version').tgz +npm run test:examples -- --tarball .artifacts/cometapi-$(node -p 'require("./package.json").version').tgz +npm run test:fixtures -- --tarball .artifacts/cometapi-$(node -p 'require("./package.json").version').tgz ``` Install that path in a separate consumer when needed. Do not treat a locally diff --git a/RELEASING.md b/RELEASING.md index f0491ac..fd4aab8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -454,12 +454,15 @@ executed README examples against the packed artifact, release-PR/tag/changelog/ manifest version agreement, reviewed security and compatibility status, and post-publication registry evidence. -The 0.1.1 repair uses one explicit `last-release-sha` boundary at the immutable -0.1.0 release commit, `1752cbb57f11dc6dca8dd1b13f0f8d5e8b5fdfca`. It exists -only to prevent pre-0.1.0 features from being rediscovered while the normal -Release Please history is repaired. The generated 0.1.1 PR must remove that -temporary override before merge; future releases must discover the Release -Please-created `v0.1.1` boundary normally. +The 0.1.1 repair used one explicit `last-release-sha` boundary at the immutable +0.1.0 release commit, `1752cbb57f11dc6dca8dd1b13f0f8d5e8b5fdfca`, only for +the initial preparation dispatch. That dispatch proved the normal action-owned +0.1.1 PR without rediscovering pre-0.1.0 features. A normal topic PR then removes +the temporary override and records final candidate approval on `main`; a fresh +preparation dispatch refreshes the action-owned release PR from that state. The +finalization commit must use a releasable `fix:` subject so Release Please +updates the generated notes and cannot treat the old branch as unchanged. +Future releases discover the Release Please-created `v0.1.1` boundary normally. Before enabling the repaired workflow, create the standard `autorelease: pending` and `autorelease: tagged` labels if they are still @@ -494,8 +497,13 @@ The `GITHUB_TOKEN`-created PR's `pull_request` CI starts in GitHub's approval-required state. A human with write access must explicitly authorize those workflow runs before their results can satisfy required checks; this is separate from the final-head administrator review. -Remove the one-cycle `last-release-sha` from that branch, complete the -release-ready documentation, run the full matrix on its final head, and obtain +After the finalization topic PR removes the one-cycle `last-release-sha` and +completes the release-ready documentation on `main`, start a new first-attempt +manual dispatch. Require it to refresh the same action-owned release PR with +only the four generated release files and release notes identical to the +generated CHANGELOG section. Require the refreshed release commit to have the +post-finalization `main` commit as its direct parent; an unchanged older head is +not a refreshed candidate. Run the full matrix on that final head and obtain approval from a different human repository administrator. The release-PR merge creates the `push` run that may tag and publish. A later push cannot tag an older outstanding release PR; its merge SHA must equal the triggering SHA before @@ -518,13 +526,12 @@ mutate the release branch during that window. The workflow repeats those checks after the action and stops publication on any drift, but it cannot delete or replace an immutable Release created during an external race. -The stale branch -`release-please--branches--main--components--cometapi` at -`3f0949e5c0ccd0923d10595437f7a315f013af7c` is the failed run's evidence, not a -release candidate. Immediately before replacing or deleting it, confirm that -it still contains the documented generated 0.2.0 state, has no associated open -PR, and contains no independent work. Do not delete or rewrite any other -branch. +The stale branch at `3f0949e5c0ccd0923d10595437f7a315f013af7c` was revalidated +as the failed run's generated 0.2.0 evidence, with no associated open PR or +independent work, then deleted. Release Please recreated the canonical +`release-please--branches--main--components--cometapi` branch for the +action-owned 0.1.1 PR. Do not use that branch as a 0.2 starting point or delete +or rewrite any other branch. For 0.1.1, `always-bump-patch` keeps every releasable Conventional Commit on the 0.1.x maintenance line; changing that strategy requires a separately authorized @@ -643,11 +650,9 @@ layers: `3f0949e5c0ccd0923d10595437f7a315f013af7c`, a generated `0.2.0` draft, but before creating a pull request. It did not modify `main`, create a tag, or publish a package. `RELEASE_PLEASE_ENABLED` was set to `false` before the - closeout push; the branch is retained as failure evidence and must not be - merged or treated as the start of 0.2. Release Please remains disabled until - the authorized 0.1.1 repair is merged, the stale branch is revalidated and - removed, and the normal action-created PR path is ready for one first-attempt - preparation run. + closeout push. During the authorized 0.1.1 repair, the branch was revalidated + as failure-only evidence with no associated PR or independent work, deleted, + and then recreated by Release Please for the normal action-owned 0.1.1 PR. ## Verification record diff --git a/ROADMAP.md b/ROADMAP.md index f785a02..0bd7d79 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -106,30 +106,33 @@ Actions to create or approve pull requests at that time. The run did not change `main`, create a tag or published Release, or publish to npm. The 0.1.1 maintenance work makes the component and stable-patch policy -explicit, anchors the one repair cycle at the exact 0.1.0 release commit, and -restores Release Please ownership of the reviewed version/changelog PR plus the -immutable tag and GitHub Release. The scoped Release Please job now uses the -repository's enabled Actions PR authorization to create and label the normal PR; +explicit, used the exact 0.1.0 release commit to anchor only the initial repair +dispatch, and restores Release Please ownership of the reviewed +version/changelog PR plus the immutable tag and GitHub Release. A normal topic +PR removes that temporary anchor and records final candidate approval before a +fresh preparation dispatch refreshes the action-owned release PR. The scoped +Release Please job now uses the repository's enabled Actions PR authorization +to create and label the normal PR; a human owner reviews its exact final head. Default workflow permissions remain read-only, bot approval is never accepted, and the workflow does not modify the repository setting. Patch-only versioning prevents an implicit 0.2 bump during -this maintenance window. The temporary anchor must be removed in that release -PR before merge. The explicit component identifies the temporary branch but, -for this root package, does not enter the Release Please title or public tag; +this maintenance window. The explicit component identifies the temporary +branch but, for this root package, does not enter the Release Please title or public tag; the only accepted patch tag is `v0.1.1`. Publication is triggered from the successful attempt-qualified Release Please push run and independently verifies that run's schema-v2 result artifact, default-branch commit, tag, immutable Release, and package artifact before the existing bounded live smoke and npm -OIDC steps. A -push rerun is bounded to the same run ID, SHA, candidate, Release-producing +OIDC steps. A push rerun is bounded to the same run ID, SHA, candidate, +Release-producing attempt, and exact Release state; manual preparation remains attempt-1-only. -The Release notes must equal the reviewed `CHANGELOG` entry. The post-merge run also -requires an administrator's approval on the release PR's final head. - -The exact stale branch remains failure evidence until its contents, lack of an -open PR, and lack of independent work are reconfirmed immediately before -cleanup. It must never be merged or treated as the start of 0.2. Repository -foundation may become Complete only after the real 0.1.1 release flow, public +The Release notes must equal the reviewed `CHANGELOG` entry. The post-merge run +also requires an administrator's approval on the release PR's final head. + +The exact stale 0.2 branch was revalidated as failure-only evidence with no +associated PR or independent work, then deleted. Release Please recreated the +canonical branch for the action-owned 0.1.1 PR; it must never be treated as the +start of 0.2. Repository foundation may become Complete only after the real +0.1.1 release flow, public registry installation, and a separate post-release documentation PR recording ROADMAP and RELEASING evidence succeed. Until then, `RELEASE_PLEASE_ENABLED` remains a temporary release-operation control, diff --git a/release-please-config.json b/release-please-config.json index 3dda4a8..0d7075a 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,7 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "label": "autorelease: pending", - "last-release-sha": "1752cbb57f11dc6dca8dd1b13f0f8d5e8b5fdfca", "release-label": "autorelease: tagged", "separate-pull-requests": true, "packages": { diff --git a/tests/workflow-contract.test.mjs b/tests/workflow-contract.test.mjs index bcca2b4..2b3e253 100644 --- a/tests/workflow-contract.test.mjs +++ b/tests/workflow-contract.test.mjs @@ -243,6 +243,12 @@ describe("GitHub Actions workflow contract", () => { "release-please-result-${{ github.run_id }}-${{ github.run_attempt }}", ); expect(releasePlease).toContain("validateReleasePleaseActionResult"); + expect(releasePlease).toContain( + 'branch_parent="$(git rev-parse "${release_ref}^")"', + ); + expect(releasePlease).toContain( + 'if [[ "$branch_parent" != "$GITHUB_SHA" ]]', + ); expect(releasePlease).toContain("schemaVersion: 2"); expect(releasePlease).toContain("actionOutcome"); expect(releasePlease).toContain("recovered"); @@ -268,9 +274,7 @@ describe("GitHub Actions workflow contract", () => { ), ).toBeLessThan(releasePlease.indexOf("Run Release Please")); - expect(releasePleaseConfig["last-release-sha"]).toBe( - "1752cbb57f11dc6dca8dd1b13f0f8d5e8b5fdfca", - ); + expect(releasePleaseConfig).not.toHaveProperty("last-release-sha"); expect(releasePleaseConfig.label).toBe("autorelease: pending"); expect(releasePleaseConfig["release-label"]).toBe("autorelease: tagged"); expect(releasePleaseConfig["separate-pull-requests"]).toBe(true);