ci(scripts): skipped duplicate release CI runs and enabled OIDC npm publishes
- Added a workflow `gate` job that marks `main` pushes with a `v*` tag at `HEAD` as duplicate release runs. - Conditioned native, lint/test, and install CI jobs on that gate so redundant build and publish work is skipped on duplicate tagged pushes. - Updated `scripts/ci-release-publish.ts` to publish packed tarballs via `npm publish` after `bun pm pack`, handling already-published versions as a no-op.
This commit is contained in:
@@ -18,6 +18,36 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# During a release the version-bump commit and its `v*` tag are pushed
|
||||
# atomically (`git push --atomic origin main refs/tags/v*` in
|
||||
# scripts/release.ts), so GitHub fires two `push` events — one for
|
||||
# `refs/heads/main`, one for the tag — that would each run the full build.
|
||||
# The tag run is authoritative: it self-contains the native build and runs
|
||||
# the release/publish jobs (release_binary downloads natives from its own
|
||||
# run). Detect when this branch-push run is for a commit that already
|
||||
# carries a release tag and skip the duplicate build here; normal main
|
||||
# pushes (no `v*` tag at HEAD) and PRs are unaffected.
|
||||
gate:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
skip: ${{ steps.check.outputs.skip }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
- name: Detect duplicate release branch-push run
|
||||
id: check
|
||||
shell: bash
|
||||
run: |
|
||||
skip=false
|
||||
if [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
||||
if git tag --points-at HEAD | grep -qE '^v[0-9]'; then
|
||||
echo "HEAD carries a release tag; skipping the duplicate branch-push build (the tag run is authoritative)."
|
||||
skip=true
|
||||
fi
|
||||
fi
|
||||
echo "skip=$skip" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Compute a stable hash of every input that affects the native cdylib output,
|
||||
# then look for any prior successful main run that already uploaded the
|
||||
# native artifacts for this hash. Two independent outputs:
|
||||
@@ -30,6 +60,8 @@ jobs:
|
||||
# Non-tag native jobs are skipped when their canary hits; the canary
|
||||
# retention window (see build-native action) is the effective TTL.
|
||||
rust-hash:
|
||||
needs: [gate]
|
||||
if: ${{ needs.gate.outputs.skip != 'true' }}
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
hash: ${{ steps.compute.outputs.hash }}
|
||||
@@ -118,6 +150,8 @@ jobs:
|
||||
|
||||
# Fast lint + type check (no Rust, no native build needed)
|
||||
check:
|
||||
needs: [gate]
|
||||
if: ${{ needs.gate.outputs.skip != 'true' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -136,8 +170,8 @@ jobs:
|
||||
# Linux x64 baseline + modern: required by `test`, so it runs on every PR
|
||||
# unless rust-hash found a cached run. Tags always rebuild for fresh artifacts.
|
||||
native_linux:
|
||||
needs: [rust-hash]
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || needs.rust-hash.outputs.linux-run-id == '' }}
|
||||
needs: [gate, rust-hash]
|
||||
if: ${{ needs.gate.outputs.skip != 'true' && (startsWith(github.ref, 'refs/tags/v') || needs.rust-hash.outputs.linux-run-id == '') }}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -160,8 +194,8 @@ jobs:
|
||||
# building the artifacts that ship in release tags. Skipped on main when the
|
||||
# rust-hash canary already found a recent run with all artifacts intact.
|
||||
native_release:
|
||||
needs: [rust-hash]
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.rust-hash.outputs.release-run-id == '') }}
|
||||
needs: [gate, rust-hash]
|
||||
if: ${{ needs.gate.outputs.skip != 'true' && (startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.rust-hash.outputs.release-run-id == '')) }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -184,8 +218,8 @@ jobs:
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [native_linux, rust-hash]
|
||||
if: ${{ !cancelled() && needs.native_linux.result != 'failure' }}
|
||||
needs: [gate, native_linux, rust-hash]
|
||||
if: ${{ !cancelled() && needs.gate.outputs.skip != 'true' && needs.native_linux.result != 'failure' }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -234,6 +268,8 @@ jobs:
|
||||
run: bun run ci:test:smoke
|
||||
|
||||
install_methods:
|
||||
needs: [gate]
|
||||
if: ${{ needs.gate.outputs.skip != 'true' }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -417,6 +453,13 @@ jobs:
|
||||
!inputs.skip_npm }}
|
||||
needs: [release_binary, release_github_verify, rust-hash]
|
||||
runs-on: ubuntu-22.04
|
||||
# `id-token: write` lets npm mint the GitHub OIDC token it exchanges for a
|
||||
# short-lived publish token (trusted publishing + provenance). When a
|
||||
# package has no matching trusted publisher configured, npm silently falls
|
||||
# back to NODE_AUTH_TOKEN below — which also covers first-ever publishes.
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
@@ -426,6 +469,9 @@ jobs:
|
||||
with:
|
||||
node-version: "24"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
# Trusted publishing (OIDC) and auto-provenance need npm >= 11.5.1.
|
||||
- name: Ensure npm supports OIDC trusted publishing
|
||||
run: npm install -g npm@latest
|
||||
- name: Cache bun dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -440,5 +486,8 @@ jobs:
|
||||
merge-multiple: true
|
||||
- name: Publish to npm
|
||||
env:
|
||||
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
# Fallback auth: setup-node wrote an .npmrc referencing
|
||||
# NODE_AUTH_TOKEN; npm uses it only when OIDC has no trusted
|
||||
# publisher for the package (or on a first publish).
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: bun run ci:release:publish
|
||||
|
||||
Reference in New Issue
Block a user