From cddafa496e1126360583f816f029264974ece169 Mon Sep 17 00:00:00 2001 From: htnabe Date: Wed, 19 Aug 2026 08:30:52 +0900 Subject: [PATCH] docs: gate release merges and tagging on polled CI success Also pin the publish job to npm 11 so trusted publishing works on Node 22.22.1. --- .github/workflows/publish.yml | 4 ++-- docs/development/publishing.md | 44 ++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aad2513..7a61e60 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -100,9 +100,9 @@ jobs: registry-url: "https://registry.npmjs.org" cache: "npm" - # Ensure npm 11.5.1 or later is installed + # Trusted publishing needs npm >= 11.5.1; npm 12 requires a newer Node than this workflow uses. - name: Update npm - run: npm install -g npm@latest + run: npm install -g npm@^11 - name: Install for publish run: npm ci diff --git a/docs/development/publishing.md b/docs/development/publishing.md index 89dd09a..08e98f1 100644 --- a/docs/development/publishing.md +++ b/docs/development/publishing.md @@ -11,15 +11,17 @@ Before using the publish flow, configure the GitHub Actions settings required by - Configure npm Trusted Publishing (OIDC) for this GitHub repository/workflow. - Configure branch protection for `main` so the required CI checks for the test workflow must pass before a merge is allowed. - No npm token secret is required. +- The publish job pins npm to the `11` line: trusted publishing needs npm 11.5.1 or later, while npm 12 requires a newer Node than the workflow uses. ## Goal - Release without direct pushes to `main`. - Keep `package.json` version and Git tag aligned. +- Merge a release PR only after its CI checks have been polled to success. - Publish to npm only after the required CI succeeds for the `main` merge commit. - Publish to npm automatically only when a release version was intentionally bumped. - Keep stable releases on npm `latest` and pre-releases on the matching channel (`beta`, `rc`, or `next`). -- Create the git tag and GitHub Release locally after the npm release succeeds. +- Create the git tag and GitHub Release locally only after the publish workflow succeeds. ## Release Policy (Main-First) @@ -35,6 +37,14 @@ Before using the publish flow, configure the GitHub Actions settings required by 6. Create the tag and GitHub Release locally from the published `main` commit - The GitHub Actions publish workflow is intentionally not triggered by a GitHub Release event. +## CI Polling Rule (Required) + +- Before merging any release PR, poll its CI checks until every required check succeeds. +- Wait at most 5 minutes. If the checks have not all succeeded by then, treat the release as failed and stop immediately. +- Do not merge, tag, or publish a release while checks are pending, failing, or unresolved. +- Apply the same rule to the publish workflow run on `main`: poll it, cap the wait at 5 minutes, and stop on timeout or failure. +- Never create the tag or GitHub Release before the publish workflow has succeeded. + ## npm Distribution Tag Behavior - Stable versions (for example `0.0.15`) are published with npm dist-tag `latest`. @@ -65,11 +75,11 @@ This prevents routine documentation or maintenance merges from accidentally runn - Example: `release/v0.0.13` 2. Bump version on the release branch only. - `npm version 0.0.13 --no-git-tag-version` -3. Open a PR from the release branch to `dev`. -4. Open a PR from `dev` to `main`. -5. Wait for CI to pass on the merge commit to `main`. +3. Open a PR from the release branch to `dev`, poll its CI, and merge only after it succeeds. +4. Open a PR from `dev` to `main`, poll its CI, and merge only after it succeeds. +5. Poll the publish workflow run for the `main` merge commit. 6. If the `main` push changed `package.json` or `package-lock.json`, the publish workflow automatically publishes to npm. -7. After successful npm publish, create the tag and GitHub Release locally. +7. After the publish workflow succeeds, create the tag and GitHub Release locally. ## Command Example @@ -92,15 +102,25 @@ gh pr create --base dev --head release/v0.0.13 --title "chore(release): 0.0.13" gh pr create --base main --head dev --title "dev" ``` -### 3) Publish to npm after CI success on main +### 3) Poll CI before merging each PR + +```bash +# stops with a non-zero status on failure or after 5 minutes +timeout 300 gh pr checks --watch --fail-fast +gh pr merge --merge --delete-branch=false +``` + +### 4) Poll the publish workflow after the merge to main ```bash git checkout main git pull origin main # The publish workflow runs automatically when package.json / package-lock.json changed. +RUN_ID=$(gh run list --workflow="Secure Publish to npm" --branch main --limit 1 --json databaseId --jq '.[0].databaseId') +timeout 300 gh run watch "${RUN_ID}" --exit-status ``` -### 4) Create the tag and GitHub Release locally after npm publish succeeds +### 5) Create the tag and GitHub Release locally after npm publish succeeds ```bash git checkout main @@ -110,7 +130,7 @@ git push origin v0.0.13 gh release create v0.0.13 --target main --title "v0.0.13" --generate-notes ``` -### 5) Pre-release example (beta) +### 6) Pre-release example (beta) ```bash git checkout dev @@ -148,15 +168,15 @@ The publish workflow detects the prerelease identifier and maps it to `beta`, `r - It can unintentionally delete the `dev` branch. - Always create the release tag on the exact `main` commit that was successfully published to npm. - Do not rely on GitHub Releases to trigger the publish workflow. +- Do not bypass a blocked or pending merge; a timeout is a release failure, not a reason to force the merge. ## Troubleshooting Checklist - Was the `main` branch push a deliberate version bump in `package.json` or `package-lock.json`? +- Did every required CI check reach success within the 5-minute polling window before the merge? - Did the required CI checks pass on the merge commit before the publish workflow started? - Does the npm dist-tag match the version channel (for example `latest`, `beta`, `rc`, `next`)? -- Were the git tag and GitHub Release created locally after the npm publish succeeded? - -- Does the tag name match package version format (e.g., `v0.0.13` or `v0.0.15-beta.1`)? -- Did the `publish.yml` workflow start from the `release` event? +- Does the tag name match the package version format (for example `v0.0.13` or `v0.0.15-beta.1`)? +- Were the git tag and GitHub Release created only after the publish workflow succeeded? - Did the tag/version consistency check pass? >>>>>>> origin/main