Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions .github/workflows/recover-mac-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Recover Mac release

on:
workflow_dispatch:
inputs:
version:
description: Version to recover (pinned to 2.1.0)
required: true
type: string
default: '2.1.0'
candidate_sha:
description: Candidate commit SHA (pinned)
required: true
type: string
default: '94c796fc34fd699776764d67d2f26013909a308e'
draft_id:
description: Draft release ID (pinned to 442117184)
required: true
type: string
default: '442117184'
action:
description: 'Recovery action: verify (read-only draft check) or publish (publish Latest and reconcile release-state)'
required: true
type: choice
options:
- verify
- publish
default: verify

permissions: {}

concurrency:
group: recover-mac-release-${{ github.ref }}
cancel-in-progress: false

jobs:
verify:
runs-on: xcode-27
permissions:
contents: read
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
persist-credentials: false
- name: Select Xcode (.xcode-version)
run: scripts/ci/select-xcode.sh
- name: Verify Mac release candidate draft
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
CANDIDATE_SHA: ${{ inputs.candidate_sha }}
DRAFT_ID: ${{ inputs.draft_id }}
run: |
set -euo pipefail
scripts/release/recover-mac-release.sh --verify
# Verify reconciliation can start BEFORE Mac becomes public.
scripts/release/reconcile-mac-release.sh --preflight

publish:
needs: verify
if: ${{ inputs.action == 'publish' }}
runs-on: xcode-27
environment: release-publish
permissions:
contents: write
pull-requests: write
actions: read
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
persist-credentials: false
- name: Select Xcode (.xcode-version)
run: scripts/ci/select-xcode.sh
- name: Deployment branch guard
env:
REF: ${{ github.ref }}
run: |
set -euo pipefail
case "$REF" in
"refs/heads/release/"*) ;;
*) echo "::error::Publication must run on a release/* branch to satisfy release-publish deployment branch policy (got $REF)"; exit 1 ;;
esac
- name: Environment requires human approval
id: check-env
env:
GH_TOKEN: ${{ github.token }}
run: scripts/release/check-environment.sh release-publish --require-reviewers
- name: Release state token (release App, contents only)
id: state-token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
permission-contents: write
- name: Publish Mac release as Latest
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
CANDIDATE_SHA: ${{ inputs.candidate_sha }}
DRAFT_ID: ${{ inputs.draft_id }}
run: |
set -euo pipefail
scripts/release/recover-mac-release.sh --publish
- name: Reconcile release state
env:
RELEASE_STATE_TOKEN: ${{ steps.state-token.outputs.token }}
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
CANDIDATE_SHA: ${{ inputs.candidate_sha }}
run: |
set -euo pipefail
scripts/release/reconcile-mac-release.sh --execute
23 changes: 22 additions & 1 deletion scripts/release/check-release-workflows.rb
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ def transitive_needs(jobs, id, seen = [])
REFERENCE_MERGE = %r{(git (merge|cherry-pick|rebase)[^\n]*reference)|(gh pr (create|merge)[^\n]*reference/opendisplay)}.freeze

RELEASE_WORKFLOWS = %w[release-candidate.yml release-mac.yml release-ios.yml release-android.yml release-publish.yml
release-pr.yml release-dry-run.yml release-monitor.yml release-state-access.yml].freeze
release-pr.yml release-dry-run.yml release-monitor.yml release-state-access.yml
recover-mac-release.yml].freeze
SCHEDULE_SWITCHES = { "release-monitor.yml" => "RELEASE_AUTOMATION", "reference-sync.yml" => "REFERENCE_SYNC",
"repository-guard.yml" => "REPOSITORY_GUARD" }.freeze

Expand Down Expand Up @@ -337,6 +338,26 @@ def release_ref_guard?(step, version_from_input:)
end
end

# MARK: - Mac release recovery

if (doc = load("recover-mac-release.yml"))
name = "recover-mac-release.yml"
common(name, doc)
only_trigger(name, doc, "workflow_dispatch")
secrets_behind_environments(name, doc, %w[release-publish])
jobs = doc["jobs"] || {}
ver = jobs["verify"]
err(name, "verify must preflight candidate configuration") unless ver && steps(ver).any? { |s| run_text(s).include?("reconcile-mac-release.sh --preflight") }
pub = jobs["publish"]
if pub.nil?
err(name, "missing the publish job")
else
err(name, "publish job must use the release-publish environment") unless env_name(pub) == "release-publish"
err(name, "publish job must depend on verify") unless needs(pub).include?("verify")
err(name, "publish job must check release-publish with required reviewers") unless steps(pub).any? { |s| run_text(s).include?("check-environment.sh release-publish --require-reviewers") }
end
end

# MARK: - Release PR, dry run, monitor

if (doc = load("release-pr.yml"))
Expand Down
Loading
Loading