Skip to content
Merged
62 changes: 56 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ name: Release
on:
push:
branches: [main]
# Recovery path. A release tag is created by the job below and only that run
# carries `release_created`, so a publish that fails for a reason outside the
# tag — a missing tool on the runner, a registry outage — cannot be retried by
# re-running it: the re-run replays the workflow file of that commit, which is
# the one that failed.
#
# Dispatch this **with the release tag selected as the ref**, not from a
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
# branch with the tag as a parameter. Taking it as a free-form input would let
# a dispatch publish any branch or commit through a job holding npm OIDC
# rights, and npm's provenance records the event's ref and sha rather than
# whatever the workspace was checked out to — so a tarball built from a tag
# while the event pointed at a branch would be attested to the wrong commit.
# The ref picker only offers refs that exist, and `ref_type` below rejects
# everything that is not a tag.
workflow_dispatch:
Comment thread
jlucaso1 marked this conversation as resolved.
Comment thread
jlucaso1 marked this conversation as resolved.

permissions:
contents: read
Expand All @@ -26,6 +41,7 @@ env:
jobs:
release-please:
name: Prepare release
if: github.event_name == 'push'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
Expand Down Expand Up @@ -77,17 +93,46 @@ jobs:
verify:
name: Verify the tag
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
# `!cancelled()` rather than `always()`: the dispatch path needs this to run
# past a skipped release-please, but a cancelled run must not go on to
# publish.
if: >-
!cancelled() &&
(needs.release-please.outputs.release_created == 'true' ||
(github.event_name == 'workflow_dispatch' && github.ref_type == 'tag'))
Comment thread
jlucaso1 marked this conversation as resolved.
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
# The commit the event recorded, never a ref. A ref can move between
# the event and either checkout, and npm records this sha as the
# package's source regardless of what the workspace holds — so
# resolving a tag here could publish one tree while attesting another.
ref: ${{ github.sha }}
persist-credentials: false

# Guards the assumption on the push path: release-please tags the commit
# it just merged, so a tag pointing elsewhere means this run would verify
# and publish something the release does not name.
- name: Confirm the release tag points at this commit
if: github.event_name == 'push'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
ref=$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG")
target=$(jq -r '.object.sha' <<<"$ref")
if [ "$(jq -r '.object.type' <<<"$ref")" = tag ]; then
target=$(gh api "repos/$GITHUB_REPOSITORY/git/tags/$target" --jq '.object.sha')
fi
if [ "$target" != "$GITHUB_SHA" ]; then
echo "::error::$TAG points at $target, not $GITHUB_SHA"
exit 1
fi

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
Expand All @@ -100,7 +145,9 @@ jobs:
- name: Install wasm-pack
uses: taiki-e/install-action@91ddec75689c4c78665b598d188dc821c5a43e5c # v2.85.9
with:
tool: wasm-pack
# protoc: `bun run build` regenerates the proto codec, which ci.yml
# never exercises because it calls wasm-pack and build:ts directly.
tool: wasm-pack,protoc

- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
Expand Down Expand Up @@ -131,7 +178,7 @@ jobs:
publish:
name: Publish to npm
needs: [release-please, verify]
if: needs.release-please.outputs.release_created == 'true'
if: ${{ !cancelled() && needs.verify.result == 'success' }}
Comment thread
jlucaso1 marked this conversation as resolved.
runs-on: ubuntu-latest
timeout-minutes: 45
# Gate for the publish step: add required reviewers here to make releases
Expand All @@ -145,7 +192,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
# Same immutable commit verify checked out and vouched for.
ref: ${{ github.sha }}
# Nothing here talks to the remote after checkout, and the steps below
# run cargo, bun and third-party build scripts in a job holding OIDC
# publish rights. Don't leave the token in .git/config for them.
Expand All @@ -163,7 +211,9 @@ jobs:
- name: Install wasm-pack
uses: taiki-e/install-action@91ddec75689c4c78665b598d188dc821c5a43e5c # v2.85.9
with:
tool: wasm-pack
# protoc: `bun run build` regenerates the proto codec, which ci.yml
# never exercises because it calls wasm-pack and build:ts directly.
tool: wasm-pack,protoc
Comment thread
jlucaso1 marked this conversation as resolved.
Outdated

# Pinned, unlike ci.yml: this bun builds the wasm artifact that ships to
# npm, so a floating version would change the published bytes without a
Expand Down
Loading