Skip to content

Release / prepare-release-pr / main #58

Release / prepare-release-pr / main

Release / prepare-release-pr / main #58

Workflow file for this run

name: Release
run-name: Release / ${{ inputs.operation }} / ${{ github.ref_name }}
on:
workflow_dispatch:
inputs:
operation:
description: Prepare, dry-run, publish with trusted publishers, or bootstrap first registry versions
required: true
type: choice
default: prepare-release-pr
options:
- prepare-release-pr
- publish-dry-run
- publish
- publish-bootstrap
release_commit:
description: Optional full commit SHA assertion; when set it must equal the workflow commit
required: false
type: string
default: ""
continuation_pointer:
description: Internal exact-parent continuation pointer; leave empty for a maintainer dispatch
required: false
type: string
default: ""
permissions:
contents: read
env:
NODE_VERSION: 22.22.3
concurrency:
# Every registry-writing or release-branch-writing operation shares one
# non-cancelling lock. GitHub permits one pending run while the active run
# completes, so maintainers must not stack mutation dispatches. Dry-runs are
# read-only and may run once per exact SHA.
group: release-${{ inputs.operation == 'publish-dry-run' && github.sha || 'mutation' }}
cancel-in-progress: false
jobs:
validate-inputs:
name: Validate release inputs
runs-on: ubuntu-24.04
timeout-minutes: 2
permissions:
contents: read
steps:
- name: Checkout exact workflow commit
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Reject unsupported or stale release inputs
id: validate_release_inputs
env:
RELEASE_OPERATION: ${{ inputs.operation }}
RELEASE_COMMIT: ${{ inputs.release_commit }}
RELEASE_CONTINUATION_POINTER: ${{ inputs.continuation_pointer }}
run: bash .github/scripts/validate-release-workflow-inputs.sh
# GitHub validates the permission requests of every nested job in a reusable
# workflow before evaluating job-level `if` conditions. Each caller must
# therefore expose the complete reusable-workflow ceiling. The explicit
# permissions on the called jobs in release-execute.yml still reduce the
# token used by the one operation that actually runs.
prepare-release-pr:
name: Prepare release PR
needs: validate-inputs
if: ${{ inputs.operation == 'prepare-release-pr' }}
permissions:
actions: read
attestations: write
contents: write
id-token: write
issues: write
pull-requests: write
uses: ./.github/workflows/release-execute.yml
with:
operation: prepare-release-pr
release_commit: ${{ inputs.release_commit }}
continuation_pointer: ${{ inputs.continuation_pointer }}
publish-dry-run:
name: Publish dry run
needs: validate-inputs
if: ${{ inputs.operation == 'publish-dry-run' }}
permissions:
actions: read
attestations: write
contents: write
id-token: write
issues: write
pull-requests: write
uses: ./.github/workflows/release-execute.yml
with:
operation: publish-dry-run
release_commit: ${{ inputs.release_commit }}
continuation_pointer: ${{ inputs.continuation_pointer }}
publish-bootstrap:
name: Bootstrap registry identities
needs: validate-inputs
if: ${{ inputs.operation == 'publish-bootstrap' }}
permissions:
actions: read
attestations: write
contents: write
id-token: write
issues: write
pull-requests: write
uses: ./.github/workflows/release-execute.yml
with:
operation: publish-bootstrap
release_commit: ${{ inputs.release_commit }}
continuation_pointer: ${{ inputs.continuation_pointer }}
dispatch-bootstrap-continuation:
name: Dispatch verified bootstrap continuation
needs: publish-bootstrap
if: ${{ needs.publish-bootstrap.outputs.continuation_required == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
actions: write
contents: read
steps:
- name: Checkout exact release transport
timeout-minutes: 3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Set up pinned Node.js
id: setup_dispatch_node
timeout-minutes: 3
uses: ./.github/actions/setup-node-runtime
with:
node-version: ${{ env.NODE_VERSION }}
- name: Dispatch exact verified child run
id: dispatch_continuation
timeout-minutes: 40
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_OPERATION: publish-bootstrap
RELEASE_HEAD_SHA: ${{ github.sha }}
CONTINUATION_ARTIFACT_ID: ${{ needs.publish-bootstrap.outputs.continuation_artifact_id }}
CONTINUATION_ARTIFACT_DIGEST: ${{ needs.publish-bootstrap.outputs.continuation_artifact_digest }}
CONTINUATION_CONTRACT_DIGEST: ${{ needs.publish-bootstrap.outputs.continuation_contract_digest }}
CONTINUATION_AUTHORIZATION_PATH: ${{ runner.temp }}/release-continuation-authorization.json
run: node .github/scripts/dispatch-release-continuation.mjs
- name: Publish exact dispatched-child authorization
id: preserve_continuation_authorization
timeout-minutes: 5
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: ${{ steps.dispatch_continuation.outputs.authorization_artifact_name }}
path: ${{ runner.temp }}/release-continuation-authorization.json
if-no-files-found: error
compression-level: 0
retention-days: 90
publish:
name: Publish release
needs: validate-inputs
if: ${{ inputs.operation == 'publish' }}
permissions:
actions: read
attestations: write
contents: write
id-token: write
issues: write
pull-requests: write
uses: ./.github/workflows/release-execute.yml
with:
operation: publish
release_commit: ${{ inputs.release_commit }}
continuation_pointer: ${{ inputs.continuation_pointer }}
dispatch-publish-continuation:
name: Dispatch verified registry continuation
needs: publish
if: ${{ needs.publish.outputs.continuation_required == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
actions: write
contents: read
steps:
- name: Checkout exact release transport
timeout-minutes: 3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- name: Set up pinned Node.js
id: setup_dispatch_node
timeout-minutes: 3
uses: ./.github/actions/setup-node-runtime
with:
node-version: ${{ env.NODE_VERSION }}
- name: Dispatch exact verified child run
id: dispatch_continuation
timeout-minutes: 40
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_OPERATION: publish
RELEASE_HEAD_SHA: ${{ github.sha }}
CONTINUATION_ARTIFACT_ID: ${{ needs.publish.outputs.continuation_artifact_id }}
CONTINUATION_ARTIFACT_DIGEST: ${{ needs.publish.outputs.continuation_artifact_digest }}
CONTINUATION_CONTRACT_DIGEST: ${{ needs.publish.outputs.continuation_contract_digest }}
CONTINUATION_AUTHORIZATION_PATH: ${{ runner.temp }}/release-continuation-authorization.json
run: node .github/scripts/dispatch-release-continuation.mjs
- name: Publish exact dispatched-child authorization
id: preserve_continuation_authorization
timeout-minutes: 5
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: ${{ steps.dispatch_continuation.outputs.authorization_artifact_name }}
path: ${{ runner.temp }}/release-continuation-authorization.json
if-no-files-found: error
compression-level: 0
retention-days: 90