Every gate and every candidate now needs only admit, so the signed macOS and Windows builds and the docker image stop waiting behind the full CI run. acceptance stays the one join: it still needs ci, docker and all six candidates, so what can be promoted is unchanged. The four gates that skipped under --skip-tests only because ci skipped (nix, termux-checks, windows-live, install-e2e) and pm-bundle needed their own condition. SKIPPED_BY requires the gate to observe 'skipped', so dropping the edge alone would have left them running and blocked the release instead of failing it.
618 lines
24 KiB
YAML
618 lines
24 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
|
|
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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
|
|
with:
|
|
release-phase: test
|
|
skip-tests: ${{ needs.admit.outputs.skip-tests == 'true' }}
|
|
tag: ${{ needs.admit.outputs.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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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 }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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 }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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
|
|
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
|
|
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
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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
|
|
with:
|
|
release-phase: publish
|
|
tag: ${{ needs.admit.outputs.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
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
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 }}
|