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.
644 lines
26 KiB
YAML
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 }}
|