Files
hermes-agent/.github/workflows/stable-release.yml
ethernet 25a096f317 fix(release): treat any missing stable baseline as no upgrade arm
A release that skipped bundles never writes the stable baseline pointer,
so its absence is normal at any point, not only before the first bundle
release. Drop the final-tag scan. A 404 on the default pointer now always
plans no upgrade arm. A supplied baseline-manifest that does not exist
still blocks, because that is a bad input.
2026-10-09 01:41:35 -04:00

644 lines
26 KiB
YAML

name: Stable Release
run-name: Stable release ${{ inputs.tag }}
# Dispatch on the tag so reusable workflows and github.sha identify the same tree.
on:
workflow_dispatch:
inputs:
tag:
description: Exact annotated claim tag, matching the selected workflow ref
required: true
type: string
baseline-manifest:
description: Optional HTTPS manifest of the previous published stable packages
default: ''
type: string
permissions:
contents: read
# Every reusable workflow called below inherits secrets (`secrets: inherit`)
# because their release-signing jobs need protected-environment secrets. A
# called workflow only sees them when the caller inherits AND the called job
# declares the environment: the job-level `environment:` alone attaches the
# deployment and exposes `vars`, but leaves `secrets.*` empty
# (actions/runner#1490). ci.yaml is deliberately excluded — it runs
# PR-controlled code and must stay secret-free.
concurrency:
group: stable-release
cancel-in-progress: false
jobs:
admit:
name: Admit the claim
# A read token cannot see a draft release, so gh release view answers
# "release not found" for a draft that exists. Write is the permission
# that can read it.
permissions:
contents: write
runs-on: ubuntu-24.04
outputs:
claim-tag: ${{ steps.admit.outputs.claim-tag }}
claim-object: ${{ steps.admit.outputs.claim-object }}
tag: ${{ steps.admit.outputs.tag }}
commit: ${{ steps.admit.outputs.commit }}
version: ${{ steps.admit.outputs.version }}
release-id: ${{ steps.admit.outputs.release-id }}
release-epoch: ${{ steps.admit.outputs.release-epoch }}
skip-bundles: ${{ steps.admit.outputs.skip-bundles }}
skip-tests: ${{ steps.admit.outputs.skip-tests }}
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- id: admit
run: python -m scripts.releases.stable admit
env:
GH_TOKEN: ${{ github.token }}
RELEASE_CLAIM_TAG: ${{ inputs.tag }}
ci:
name: Full CI pipeline
needs: admit
if: needs.admit.outputs.skip-tests != 'true'
permissions:
contents: read
pull-requests: write
actions: read
security-events: write
uses: ./.github/workflows/ci.yaml
with:
release: true
docker:
name: Docker build and tests
needs: admit
# The image publish-docker pushes is built here, so a claim that skipped
# tests still runs this job with its tests off. It builds alongside the
# gates; only the acceptance join waits for CI.
if: >-
!cancelled() && needs.admit.result == 'success'
uses: ./.github/workflows/docker.yml
secrets: inherit
with:
release-phase: test
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
tag: ${{ needs.admit.outputs.claim-tag }}
version: ${{ needs.admit.outputs.version }}
nix:
needs: admit
# The claim's policy removes it, not a gate it happens to need.
if: needs.admit.outputs.skip-tests != 'true'
uses: ./.github/workflows/nix.yml
with:
release: true
version: ${{ needs.admit.outputs.version }}
pm-bundle:
needs: admit
# Bundle acceptance is a test of bundles, so either claim flag removes it.
if: >-
needs.admit.outputs.skip-bundles != 'true'
&& needs.admit.outputs.skip-tests != 'true'
uses: ./.github/workflows/pm-bundle.yml
with:
release: true
ref: ${{ github.sha }}
termux-checks:
needs: admit
if: needs.admit.outputs.skip-tests != 'true'
permissions:
contents: read
actions: read
uses: ./.github/workflows/termux-verify.yml
secrets: inherit
with:
release: true
windows-live:
needs: admit
if: needs.admit.outputs.skip-tests != 'true'
uses: ./.github/workflows/windows-venv-e2e.yml
with:
release: true
install-e2e:
name: Install and update E2E
needs: admit
if: needs.admit.outputs.skip-tests != 'true'
permissions:
contents: read
actions: read
uses: ./.github/workflows/install-e2e.yml
with:
release: true
route: all
tag-count: '3'
exclude-ref: ${{ inputs.tag }}
candidates-darwin-arm64:
name: Build signed release candidates (darwin-arm64)
needs: admit
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: darwin-arm64
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
candidates-darwin-x64:
name: Build signed release candidates (darwin-x64)
needs: admit
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: darwin-x64
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
candidates-win32-arm64:
name: Build signed release candidates (win32-arm64)
needs: admit
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: win32-arm64
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
candidates-win32-x64:
name: Build signed release candidates (win32-x64)
needs: admit
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: win32-x64
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
candidates-win32-bundle:
name: Build signed release candidates (win32-bundle)
needs: [admit, candidates-win32-arm64, candidates-win32-x64]
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
&& needs.candidates-win32-arm64.result == 'success'
&& needs.candidates-win32-x64.result == 'success'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: win32-bundle
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
candidates-termux:
name: Build signed release candidates (termux)
needs: admit
# Starts with the gates; the acceptance join is what requires CI.
if: >-
!cancelled() && needs.admit.result == 'success' && needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: candidate
jobs: termux
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
transitions-darwin-arm64:
name: Pin actual OLD and NEW signed packages (darwin-arm64)
needs: [admit, candidates-darwin-arm64]
if: needs.admit.outputs.skip-tests != 'true'
runs-on: ubuntu-24.04
environment: release-signing
outputs:
windows: ${{ steps.plan.outputs.windows }}
macos: ${{ steps.plan.outputs.macos }}
baseline: ${{ steps.plan.outputs.baseline }}
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- id: plan
run: python -m scripts.releases.stable transitions
env:
GH_TOKEN: ${{ github.token }}
RECEIPT: darwin-arm64
RECEIPT_URL: ${{ needs.candidates-darwin-arm64.outputs.darwin-arm64-receipt-url }}
RECEIPT_SHA256: ${{ needs.candidates-darwin-arm64.outputs.darwin-arm64-receipt-sha256 }}
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_CLAIM_TAG: ${{ needs.admit.outputs.claim-tag }}
RELEASE_CLAIM_OBJECT: ${{ needs.admit.outputs.claim-object }}
BASELINE_MANIFEST_URL: ${{ inputs.baseline-manifest }}
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}
transitions-darwin-x64:
name: Pin actual OLD and NEW signed packages (darwin-x64)
needs: [admit, candidates-darwin-x64]
if: needs.admit.outputs.skip-tests != 'true'
runs-on: ubuntu-24.04
environment: release-signing
outputs:
windows: ${{ steps.plan.outputs.windows }}
macos: ${{ steps.plan.outputs.macos }}
baseline: ${{ steps.plan.outputs.baseline }}
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- id: plan
run: python -m scripts.releases.stable transitions
env:
GH_TOKEN: ${{ github.token }}
RECEIPT: darwin-x64
RECEIPT_URL: ${{ needs.candidates-darwin-x64.outputs.darwin-x64-receipt-url }}
RECEIPT_SHA256: ${{ needs.candidates-darwin-x64.outputs.darwin-x64-receipt-sha256 }}
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_CLAIM_TAG: ${{ needs.admit.outputs.claim-tag }}
RELEASE_CLAIM_OBJECT: ${{ needs.admit.outputs.claim-object }}
BASELINE_MANIFEST_URL: ${{ inputs.baseline-manifest }}
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}
transitions-win32:
name: Pin actual OLD and NEW signed packages (win32)
needs: [admit, candidates-win32-bundle]
if: needs.admit.outputs.skip-tests != 'true'
runs-on: ubuntu-24.04
environment: release-signing
outputs:
windows: ${{ steps.plan.outputs.windows }}
macos: ${{ steps.plan.outputs.macos }}
baseline: ${{ steps.plan.outputs.baseline }}
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- id: plan
run: python -m scripts.releases.stable transitions
env:
GH_TOKEN: ${{ github.token }}
RECEIPT: win32-bundle
RECEIPT_URL: ${{ needs.candidates-win32-bundle.outputs.win32-bundle-receipt-url }}
RECEIPT_SHA256: ${{ needs.candidates-win32-bundle.outputs.win32-bundle-receipt-sha256 }}
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_CLAIM_TAG: ${{ needs.admit.outputs.claim-tag }}
RELEASE_CLAIM_OBJECT: ${{ needs.admit.outputs.claim-object }}
BASELINE_MANIFEST_URL: ${{ inputs.baseline-manifest }}
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}
candidate-manifest:
name: Stage verified stable candidate artifacts
# Runs after every candidate call, so after every smoke (decision 23).
# The recorded smoke results are the calls' own workflow results: a
# call's stable-phase-result fails when its smokes fail, so a failed
# smoke fails this job's RELEASE_NEEDS check and stages no manifest.
if: always() && needs.admit.outputs.skip-bundles != 'true'
needs: [admit, candidates-darwin-arm64, candidates-darwin-x64, candidates-win32-arm64,
candidates-win32-x64, candidates-win32-bundle, candidates-termux]
runs-on: ubuntu-24.04
environment: release-signing
timeout-minutes: 90
outputs:
manifest-url: ${{ steps.manifest.outputs.manifest-url }}
manifest-sha256: ${{ steps.manifest.outputs.manifest-sha256 }}
env:
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_CLAIM_TAG: ${{ needs.admit.outputs.claim-tag }}
RELEASE_CLAIM_OBJECT: ${{ needs.admit.outputs.claim-object }}
RELEASE_NEEDS: ${{ toJSON(needs) }}
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
fetch-tags: true
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- id: manifest
run: python -m scripts.releases.stable candidate-manifest
windows-packaged:
name: Windows signed-package acceptance
needs: transitions-win32
# Without a published stable baseline there is no OLD package to upgrade from.
if: needs.transitions-win32.outputs.baseline != 'none'
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.transitions-win32.outputs.windows) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
install-method: packaged-app
update-method: open-app-update
install-ref: ${{ matrix.old }}
leg-id: stable-${{ matrix.id }}
bundle-manifest-url: ${{ matrix.manifest }}
bundle-manifest-sha256: ${{ matrix.manifest_sha256 }}
bundle-arch: ${{ matrix.arch }}
macos-packaged-arm64:
name: macOS arm64 signed-package acceptance
needs: transitions-darwin-arm64
# Without a published stable baseline there is no OLD package to upgrade from.
if: needs.transitions-darwin-arm64.outputs.baseline != 'none'
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.transitions-darwin-arm64.outputs.macos) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: packaged-app
update-method: open-app-update
install-ref: ${{ matrix.old }}
leg-id: stable-${{ matrix.id }}
bundle-manifest-url: ${{ matrix.manifest }}
bundle-manifest-sha256: ${{ matrix.manifest_sha256 }}
bundle-arch: ${{ matrix.arch }}
macos-packaged-x64:
name: macOS x64 signed-package acceptance
needs: transitions-darwin-x64
# Without a published stable baseline there is no OLD package to upgrade from.
if: needs.transitions-darwin-x64.outputs.baseline != 'none'
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.transitions-darwin-x64.outputs.macos) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: packaged-app
update-method: open-app-update
install-ref: ${{ matrix.old }}
leg-id: stable-${{ matrix.id }}
bundle-manifest-url: ${{ matrix.manifest }}
bundle-manifest-sha256: ${{ matrix.manifest_sha256 }}
bundle-arch: ${{ matrix.arch }}
bootstrap-version:
name: Bootstrap installer release identity
needs: admit
if: needs.admit.outputs.skip-tests != 'true'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ needs.admit.outputs.commit }}
- name: Stamp and verify the Cargo and Tauri release identity
env:
RELEASE_COMMIT: ${{ needs.admit.outputs.commit }}
RELEASE_VERSION: ${{ needs.admit.outputs.version }}
run: |
set -euo pipefail
tree="$RUNNER_TEMP/bootstrap-release"
mkdir -p "$tree"
git archive "$RELEASE_COMMIT" | tar -x -C "$tree"
python3 -m scripts.releases.stamping --tree "$tree" \
--version "$RELEASE_VERSION"
actual="$(cargo metadata --no-deps --format-version 1 \
--manifest-path "$tree/apps/bootstrap-installer/src-tauri/Cargo.toml" \
| jq -r '.packages[] | select(.name == "hermes-bootstrap") | .version')"
test "$actual" = "$RELEASE_VERSION" || {
echo "::error::Bootstrap Cargo version $actual != $RELEASE_VERSION"
exit 1
}
actual_tauri="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["version"])' \
"$tree/apps/bootstrap-installer/src-tauri/tauri.conf.json")"
test "$actual_tauri" = "$RELEASE_VERSION" || {
echo "::error::Bootstrap Tauri version $actual_tauri != $RELEASE_VERSION"
exit 1
}
acceptance:
name: All release acceptance checks pass
if: always()
needs: [admit, ci, docker, nix, pm-bundle, termux-checks, windows-live, install-e2e,
candidates-darwin-arm64, candidates-darwin-x64, candidates-win32-arm64,
candidates-win32-x64, candidates-win32-bundle, candidates-termux,
candidate-manifest, transitions-darwin-arm64, transitions-darwin-x64,
transitions-win32, windows-packaged, macos-packaged-arm64, macos-packaged-x64,
bootstrap-version]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- run: python -m scripts.releases.stable gate admit ci docker nix pm-bundle termux-checks windows-live install-e2e candidates-darwin-arm64 candidates-darwin-x64 candidates-win32-arm64 candidates-win32-x64 candidates-win32-bundle candidates-termux candidate-manifest transitions-darwin-arm64 transitions-darwin-x64 transitions-win32 windows-packaged macos-packaged-arm64 macos-packaged-x64 bootstrap-version
env:
RELEASE_NEEDS: ${{ toJSON(needs) }}
SKIP_BUNDLES: ${{ needs.admit.outputs.skip-bundles }}
SKIP_TESTS: ${{ needs.admit.outputs.skip-tests }}
publish-docker:
name: Publish tested Docker image
# B5: this job pushes only the immutable attempt-ref image tags; the
# stable/latest aliases move in the ordered publication pass.
needs: [admit, docker]
uses: ./.github/workflows/docker.yml
secrets: inherit
with:
release-phase: publish
tag: ${{ needs.admit.outputs.claim-tag }}
version: ${{ needs.admit.outputs.version }}
publish-bundles:
name: Publish tested bundle artifacts
needs: [admit, acceptance, candidate-manifest]
if: needs.admit.outputs.skip-bundles != 'true'
permissions:
contents: write
actions: read
packages: write
id-token: write
uses: ./.github/workflows/desktop-bundled-release.yml
secrets: inherit
with:
tag: ${{ needs.admit.outputs.tag }}
claim-tag: ${{ needs.admit.outputs.claim-tag }}
claim-object: ${{ needs.admit.outputs.claim-object }}
release-phase: publish
manifest-sha256: ${{ needs.candidate-manifest.outputs.manifest-sha256 }}
publication:
name: All artifact publication succeeded
if: always()
needs: [admit, acceptance, publish-docker, publish-bundles]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- run: python -m scripts.releases.stable gate acceptance publish-docker publish-bundles
env:
RELEASE_NEEDS: ${{ toJSON(needs) }}
SKIP_BUNDLES: ${{ needs.admit.outputs.skip-bundles }}
SKIP_TESTS: ${{ needs.admit.outputs.skip-tests }}
complete:
name: Stable release is green
if: always()
needs: [admit, ci, docker, acceptance, candidate-manifest, publication, publish-docker,
windows-packaged, macos-packaged-arm64, macos-packaged-x64]
runs-on: ubuntu-24.04
environment: release-signing
permissions:
contents: write
actions: read
steps:
- uses: actions/checkout@f548e57e544e1ff5a4c46bf1e1b8685f8e4a348a # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
- uses: ./.github/actions/setup-pm
with:
cache-python: false
- name: Set up the native identity reader
uses: ./.github/actions/setup-pm
with:
toolchain: node
cache-python: false
- run: python -m scripts.releases.stable gate admit ci docker acceptance candidate-manifest publication publish-docker
env:
RELEASE_NEEDS: ${{ toJSON(needs) }}
SKIP_BUNDLES: ${{ needs.admit.outputs.skip-bundles }}
SKIP_TESTS: ${{ needs.admit.outputs.skip-tests }}
- name: Validate the accepted candidate archive
if: needs.admit.outputs.skip-bundles != 'true'
run: python -m scripts.releases.stable complete
env:
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_CLAIM_TAG: ${{ needs.admit.outputs.claim-tag }}
RELEASE_CLAIM_OBJECT: ${{ needs.admit.outputs.claim-object }}
CANDIDATE_MANIFEST_URL: ${{ needs.candidate-manifest.outputs.manifest-url }}
CANDIDATE_MANIFEST_SHA256: ${{ needs.candidate-manifest.outputs.manifest-sha256 }}
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}
- name: Render the admitted candidate smoke results
if: needs.admit.outputs.skip-bundles != 'true'
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.admit.outputs.tag }}
RELEASE_COMMIT: ${{ needs.admit.outputs.commit }}
CANDIDATE_MANIFEST_SHA256: ${{ needs.candidate-manifest.outputs.manifest-sha256 }}
run: |
python scripts/render-builds-table.py --tag "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
--archive "$RELEASE_CLAIM_TAG" \
--candidate-manifest-sha256 "$CANDIDATE_MANIFEST_SHA256" --candidate-commit "$RELEASE_COMMIT"
- name: Set up Docker Buildx for ordered alias promotion
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Log in to Docker Hub for ordered alias promotion
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Reconcile ordered stable publication
run: python -m scripts.releases.sequencer
env:
GH_TOKEN: ${{ github.token }}
REQUESTED_VERSION: ''
CLOUDFLARE_R2_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_R2_ACCOUNT_ID }}
CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_BUCKET: ${{ vars.CLOUDFLARE_R2_BUCKET }}
CLOUDFLARE_R2_PUBLIC_URL: ${{ vars.CLOUDFLARE_R2_PUBLIC_URL }}