Skip to content
Merged
49 changes: 43 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,34 @@ 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
outputs:
# The exact commit this job verified. Publish checks that out instead of
# resolving the ref a second time, so nothing can move in between.
sha: ${{ steps.verified.outputs.sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
# On dispatch, the sha the event recorded rather than the ref: a tag
# force-updated between the event and this checkout would otherwise be
# built here while provenance still names the original commit. On the
# push path the event sha is the main commit, so the tag is the ref.
ref: ${{ github.event_name == 'workflow_dispatch' && github.sha || format('refs/tags/{0}', needs.release-please.outputs.tag_name) }}
persist-credentials: false

- id: verified
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
Expand All @@ -100,7 +133,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 +166,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 +180,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}
ref: ${{ needs.verify.outputs.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 +198,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