mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
1039 lines
53 KiB
YAML
1039 lines
53 KiB
YAML
name: release-beta
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
exact_name:
|
|
description: "Exact name: 1-12 lowercase letters or digits."
|
|
required: true
|
|
type: string
|
|
default: beta
|
|
ref:
|
|
description: "Branch, tag, or full commit to build. Empty uses the dispatched ref."
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
amr_profile:
|
|
description: "Optional AMR profile override; exact channels default to test."
|
|
required: false
|
|
type: string
|
|
default: test
|
|
publish:
|
|
description: "Publish immutable assets and staged metadata."
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
promote:
|
|
description: "Accept public artifacts and move the exact latest pointer."
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
release_public_origin:
|
|
description: "Optional public release origin override."
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
workflow_call:
|
|
inputs:
|
|
exact_name:
|
|
description: "Exact release name: 1-12 lowercase letters or digits."
|
|
required: false
|
|
type: string
|
|
default: beta
|
|
publish:
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
promote:
|
|
description: "Promote this build to the exact channel latest pointer after publication."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
release_public_origin:
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
ref:
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
amr_profile:
|
|
required: false
|
|
type: string
|
|
default: test
|
|
notification_stream:
|
|
required: false
|
|
type: string
|
|
default: release
|
|
|
|
permissions:
|
|
actions: write
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: open-design-release-beta-${{ inputs.exact_name }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
OPEN_DESIGN_AMR_PROFILE: ${{ inputs.amr_profile || 'test' }}
|
|
RELEASE_MAC_ARM64_SIGN_MODE: notarized
|
|
RELEASE_MAC_X64_SIGN_MODE: notarized
|
|
RELEASE_WIN_X64_SIGN_MODE: unsigned
|
|
# Release runners repeatedly install the same workspace before metadata and
|
|
# platform work. Reuse the repository's dependency-aware postinstall scheduler
|
|
# at a deliberately conservative, cross-platform fixed width; this keeps the
|
|
# release hot path simple while avoiding the serial workspace rebuild default.
|
|
OPEN_DESIGN_POSTINSTALL_CONCURRENCY: 2
|
|
LEGACY_MAC_ARM64_DIGEST: sha256:6d9c2fea2106fc0207acd4ee78bc8d08f9563f967121dbffd399b8d510d0c37f
|
|
LEGACY_MAC_ARM64_VERSION: 0.16.2-beta.155
|
|
LEGACY_WIN_X64_DIGEST: sha256:a0c2ef5d8b0da1ef7f93d375211fff396aa73d90b2cc3c591c27268fe6966330
|
|
LEGACY_WIN_X64_VERSION: 0.16.2-beta.155
|
|
OPEN_DESIGN_TELEMETRY_RELAY_URL: ${{ vars.OPEN_DESIGN_TELEMETRY_RELAY_URL }}
|
|
# `publish` governs distribution metadata only. Build inputs must remain
|
|
# identical between publish=false QA and the final publish=true lane so the
|
|
# verified immutable Shell bytes can be reused without a signing/notary pass.
|
|
POSTHOG_KEY: ${{ secrets.POSTHOG_KEY }}
|
|
POSTHOG_HOST: ${{ vars.POSTHOG_HOST }}
|
|
POSTHOG_CLI_API_KEY: ${{ secrets.POSTHOG_CLI_API_KEY }}
|
|
POSTHOG_CLI_PROJECT_ID: ${{ vars.POSTHOG_CLI_PROJECT_ID }}
|
|
# Vela web console origin for the AMR profile this build targets. Held in a
|
|
# per-profile repository secret instead of the source tree: the non-prod AMR
|
|
# environments are internal deployments and this repository is public, so
|
|
# neither the workflow nor the product code may name their hostnames.
|
|
#
|
|
# tools-pack bakes it into open-design-config.json and the packaged runtime
|
|
# forwards it to the daemon as OD_VELA_WEB_URL, which is the second half of the
|
|
# workspace-team gate (the first being the AMR profile allowlist). A profile
|
|
# whose secret is not configured therefore ships with workspace-team dormant
|
|
# rather than pointed at an unknown backend. Exact channels default to test;
|
|
# an explicit profile override selects its matching origin as one transaction.
|
|
#
|
|
# Secrets read here: VELA_WEB_URL_FEATURE_TEST, VELA_WEB_URL_TEST,
|
|
# VELA_WEB_URL_PROD.
|
|
OD_VELA_WEB_URL: ${{ inputs.amr_profile == 'feature-test' && secrets.VELA_WEB_URL_FEATURE_TEST || (inputs.amr_profile == 'test' || inputs.amr_profile == '') && secrets.VELA_WEB_URL_TEST || inputs.amr_profile == 'prod' && secrets.VELA_WEB_URL_PROD || '' }}
|
|
RELEASE_BRANCH: ${{ inputs.ref != '' && inputs.ref || github.ref_name }}
|
|
RELEASE_REPOSITORY: ${{ github.repository }}
|
|
RELEASE_RUN_ATTEMPT: ${{ github.run_attempt }}
|
|
RELEASE_RUN_ID: ${{ github.run_id }}
|
|
RELEASE_WORKFLOW: ${{ github.workflow }}
|
|
|
|
jobs:
|
|
metadata:
|
|
name: Prepare exact metadata and shared Closure
|
|
if: github.repository == 'nexu-io/open-design'
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
OPEN_DESIGN_POSTINSTALL_LEVEL: release-prepare
|
|
RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
OPEN_DESIGN_EXACT_METADATA_URL: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}/${{ inputs.exact_name }}/latest/metadata.json
|
|
OPEN_DESIGN_STABLE_METADATA_URL: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}/stable/latest/metadata.json
|
|
outputs:
|
|
candidate_id: ${{ steps.candidate.outputs.candidate_id }}
|
|
base_version: ${{ steps.exact.outputs.base_version }}
|
|
release_version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
shell_version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
closure_version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
closure_min_shell_version: ${{ steps.exact.outputs.closure_min_shell_version }}
|
|
closure_shared_identity_digest: ${{ steps.execution.outputs.shared_closure_digest }}
|
|
mac_arm64_closure_identity_digest: ${{ steps.execution.outputs.mac_arm64_closure_digest }}
|
|
mac_arm64_shell_identity_digest: ${{ steps.execution.outputs.mac_arm64_shell_digest }}
|
|
mac_x64_closure_identity_digest: ${{ steps.execution.outputs.mac_x64_closure_digest }}
|
|
mac_x64_shell_identity_digest: ${{ steps.execution.outputs.mac_x64_shell_digest }}
|
|
win_x64_closure_identity_digest: ${{ steps.execution.outputs.win_x64_closure_digest }}
|
|
win_x64_shell_identity_digest: ${{ steps.execution.outputs.win_x64_shell_digest }}
|
|
branch: ${{ steps.identity.outputs.branch }}
|
|
commit: ${{ steps.identity.outputs.commit }}
|
|
previous_commit: ${{ steps.prev.outputs.previous_commit }}
|
|
promote: ${{ inputs.promote }}
|
|
release_name: ${{ steps.exact.outputs.release_name }}
|
|
state_source: ${{ steps.reservation.outputs.state_source || steps.exact.outputs.state_source }}
|
|
version_lock_key: ${{ steps.reservation.outputs.version_lock_key }}
|
|
build_matrix: ${{ steps.selection.outputs.build_matrix }}
|
|
build_count: ${{ steps.selection.outputs.build_count }}
|
|
hot_activated: ${{ steps.hot_activate.outcome == 'success' }}
|
|
hot_activation_completed_at: ${{ steps.hot_activate.outputs.activated_at }}
|
|
hot_staged: ${{ steps.hot_stage.outcome == 'success' }}
|
|
hot_acceptance_latest_url: ${{ steps.hot_stage.outputs.acceptance_latest_url }}
|
|
hot_release_state: ${{ steps.hot_stage.outputs.release_state }}
|
|
hot_version_metadata_url: ${{ steps.hot_stage.outputs.version_metadata_url }}
|
|
hot_mac_arm64_url: ${{ steps.hot_stage.outputs.mac_arm64_url }}
|
|
hot_mac_x64_url: ${{ steps.hot_stage.outputs.mac_x64_url }}
|
|
hot_win_x64_url: ${{ steps.hot_stage.outputs.win_x64_url }}
|
|
steps:
|
|
- name: Validate checkout ref shape
|
|
env:
|
|
REQUESTED_REF: ${{ inputs.ref }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ "$REQUESTED_REF" =~ ^[0-9a-fA-F]{7,39}$ ]]; then
|
|
echo "release-beta ref must be a branch, tag, or full 40-character commit SHA; abbreviated SHA '$REQUESTED_REF' is ambiguous" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v6.0.2
|
|
with:
|
|
ref: ${{ inputs.ref != '' && inputs.ref || github.ref }}
|
|
fetch-depth: 1
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v5
|
|
with:
|
|
version: 10.33.2
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 24.18.0
|
|
cache: pnpm
|
|
cache-dependency-path: pnpm-lock.yaml
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Resolve built identity
|
|
id: identity
|
|
env:
|
|
BUILD_REF: ${{ inputs.ref != '' && inputs.ref || github.ref_name }}
|
|
DISPLAY_BRANCH: ${{ github.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
built_sha="$(git rev-parse HEAD)"
|
|
display_branch="$BUILD_REF"
|
|
if [[ "$BUILD_REF" =~ ^[0-9a-fA-F]{40}$ ]]; then
|
|
display_branch="$DISPLAY_BRANCH"
|
|
fi
|
|
echo "BUILT_SHA=$built_sha" >> "$GITHUB_ENV"
|
|
{
|
|
echo "branch=$display_branch"
|
|
echo "commit=$built_sha"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Validate exact publisher inputs and ref
|
|
if: ${{ inputs.publish }}
|
|
env:
|
|
REQUESTED_REF: ${{ inputs.ref != '' && inputs.ref || github.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
built_sha="$(git rev-parse HEAD)"
|
|
if [ -z "$REQUESTED_REF" ]; then
|
|
echo "release-beta publish requires an explicit branch, tag, or full commit identity" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$REQUESTED_REF" =~ ^[0-9a-fA-F]{40}$ ]]; then
|
|
expected_sha="${REQUESTED_REF,,}"
|
|
else
|
|
remote_refs="$(git ls-remote origin "refs/heads/$REQUESTED_REF" "refs/tags/$REQUESTED_REF^{}" "refs/tags/$REQUESTED_REF")"
|
|
expected_sha="$(printf '%s\n' "$remote_refs" | awk '
|
|
$2 ~ /\^\{\}$/ { print $1; found = 1; exit }
|
|
first == "" { first = $1 }
|
|
END { if (!found) print first }
|
|
')"
|
|
fi
|
|
if [ -z "$expected_sha" ]; then
|
|
echo "Could not resolve exact publisher ref '$REQUESTED_REF'" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$built_sha" != "$expected_sha" ]; then
|
|
echo "release-beta publisher ref drifted: expected $expected_sha, built $built_sha" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Capture previous exact commit
|
|
id: prev
|
|
run: |
|
|
set -euo pipefail
|
|
prev="$(curl -fsSL "$OPEN_DESIGN_EXACT_METADATA_URL" | jq -r '.github.commit // ""' 2>/dev/null || true)"
|
|
echo "previous exact commit: ${prev:-<none>}"
|
|
echo "previous_commit=$prev" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Validate exact inputs
|
|
env:
|
|
EXACT_NAME: ${{ inputs.exact_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ ! "$EXACT_NAME" =~ ^[a-z0-9]{1,12}$ ]] || [ "$EXACT_NAME" = "stable" ] || [ "$EXACT_NAME" = "prerelease" ] || [ "$EXACT_NAME" = "local" ]; then
|
|
echo "exact_name must be 1-12 lowercase letters or digits and cannot be stable, prerelease, or local" >&2
|
|
exit 1
|
|
fi
|
|
if [ "${{ inputs.promote }}" = "true" ] && [ "${{ inputs.publish }}" != "true" ]; then
|
|
echo "promote=true requires publish=true" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Validate R2 release access
|
|
env:
|
|
GITHUB_SHA: ${{ env.BUILT_SHA }}
|
|
R2_ACCESS_PROBE_NAME: release-${{ inputs.exact_name }}
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
RELEASE_PUBLIC_ORIGIN: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
run: pnpm exec tools-release check-storage
|
|
|
|
- name: Prepare exact release metadata
|
|
id: exact
|
|
env:
|
|
GITHUB_SHA: ${{ env.BUILT_SHA }}
|
|
GITHUB_REF_NAME: ${{ inputs.ref != '' && inputs.ref || github.ref_name }}
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
run: pnpm exec tools-release prepare "${{ inputs.exact_name }}"
|
|
|
|
- name: Reserve immutable exact version
|
|
id: reservation
|
|
env:
|
|
BASE_VERSION: ${{ steps.exact.outputs.base_version }}
|
|
GITHUB_SHA: ${{ env.BUILT_SHA }}
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
RELEASE_LANE: exact
|
|
RELEASE_METADATA_DIR: ${{ runner.temp }}/release-metadata
|
|
RELEASE_COMMIT: ${{ env.BUILT_SHA }}
|
|
RELEASE_PUBLIC_ORIGIN: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION_CANDIDATE: ${{ steps.exact.outputs.release_version }}
|
|
RELEASE_VERSION_MANUAL_OVERRIDE: "false"
|
|
run: pnpm exec tools-release reserve-version "${{ inputs.exact_name }}"
|
|
|
|
- name: Prepare immutable candidate identity
|
|
id: candidate
|
|
if: ${{ !inputs.promote }}
|
|
env:
|
|
RELEASE_CANDIDATE_SPEC_PATH: ${{ runner.temp }}/release-candidate/spec.json
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p "$(dirname "$RELEASE_CANDIDATE_SPEC_PATH")"
|
|
jq -n \
|
|
--arg amrProfile "${{ inputs.amr_profile || 'test' }}" \
|
|
--arg channel "${{ inputs.exact_name }}" \
|
|
--arg closureMinShellVersion "${{ steps.exact.outputs.closure_min_shell_version }}" \
|
|
--arg commit "$BUILT_SHA" \
|
|
--arg releaseVersion "${{ steps.reservation.outputs.release_version }}" \
|
|
'{
|
|
amrProfile: $amrProfile,
|
|
channel: $channel,
|
|
closureMinShellVersion: $closureMinShellVersion,
|
|
commit: $commit,
|
|
macArm64SignMode: "notarized",
|
|
macX64SignMode: "notarized",
|
|
releaseVersion: $releaseVersion,
|
|
schemaVersion: 1,
|
|
targets: ["mac_arm64", "mac_x64", "win_x64"],
|
|
winX64SignMode: "unsigned"
|
|
}' > "$RELEASE_CANDIDATE_SPEC_PATH"
|
|
pnpm exec tools-release prepare-candidate
|
|
|
|
- name: Upload immutable candidate spec
|
|
if: ${{ !inputs.promote }}
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-candidate-spec
|
|
path: ${{ runner.temp }}/release-candidate/spec.json
|
|
if-no-files-found: error
|
|
retention-days: 30
|
|
|
|
- name: Resolve release target identities
|
|
id: execution
|
|
uses: actions/github-script@v8
|
|
env:
|
|
APPLE_SIGNING_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_BASE64 }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
OD_UPDATE_METADATA_URL: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}/${{ inputs.exact_name }}/latest/metadata.json
|
|
RELEASE_ACTIVATE: ${{ inputs.promote && 'true' || 'false' }}
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
RELEASE_COMMIT: ${{ env.BUILT_SHA }}
|
|
RELEASE_MIN_SHELL_VERSION: ${{ steps.exact.outputs.closure_min_shell_version }}
|
|
RELEASE_PROFILE: ${{ inputs.amr_profile || 'test' }}
|
|
RELEASE_PUBLIC_ORIGIN: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
RELEASE_PUBLISH: ${{ inputs.publish && 'true' || 'false' }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
with:
|
|
script: |
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const identityRoot = path.join(process.env.RUNNER_TEMP, "release-identities");
|
|
const profileRoot = path.join(process.env.RUNNER_TEMP, "release-identity-profiles");
|
|
fs.mkdirSync(identityRoot, { recursive: true });
|
|
fs.mkdirSync(profileRoot, { recursive: true });
|
|
|
|
const shellVersion = process.env.RELEASE_VERSION;
|
|
const channel = process.env.RELEASE_CHANNEL;
|
|
async function compileProfile(name, platform, target, args) {
|
|
const result = await exec.getExecOutput("pnpm", [
|
|
"exec", "tools-pack", platform, "identity",
|
|
"--dir", path.join(profileRoot, name),
|
|
"--cache-dir", path.join(profileRoot, `cache-${name}`),
|
|
...args,
|
|
"--portable",
|
|
"--release-version", shellVersion,
|
|
"--shell-version", shellVersion,
|
|
"--json",
|
|
]);
|
|
const profile = JSON.parse(result.stdout);
|
|
profile.target = target;
|
|
fs.writeFileSync(path.join(profileRoot, `${name}.json`), JSON.stringify(profile, null, 2));
|
|
return profile.profileDigest;
|
|
}
|
|
|
|
const macArm64Digest = await compileProfile("mac-arm64", "mac", "darwin-arm64", [
|
|
"--namespace", `release-${channel}`,
|
|
"--mac-compression", "normal", "--to", "dmg", "--sign-mode", "notarized",
|
|
]);
|
|
const macX64Digest = await compileProfile("mac-x64", "mac", "darwin-x64", [
|
|
"--namespace", `release-${channel}-x64`,
|
|
"--mac-compression", "normal", "--to", "all", "--sign-mode", "notarized",
|
|
]);
|
|
const winX64Digest = await compileProfile("win-x64", "win", "win32-x64", [
|
|
"--namespace", `release-${channel}-win`, "--to", "all", "--sign-mode", "unsigned",
|
|
]);
|
|
const identityInputPath = path.join(identityRoot, "input.json");
|
|
const identityPath = path.join(identityRoot, "resolved.json");
|
|
fs.writeFileSync(identityInputPath, JSON.stringify({
|
|
minShellVersion: process.env.RELEASE_MIN_SHELL_VERSION,
|
|
shellProfiles: { mac_arm64: macArm64Digest, mac_x64: macX64Digest, win_x64: winX64Digest },
|
|
}));
|
|
await exec.exec("pnpm", ["exec", "tools-release", "resolve-release-identities", "--input", identityInputPath, "--output", identityPath]);
|
|
const identities = JSON.parse(fs.readFileSync(identityPath, "utf8"));
|
|
core.setOutput("shared_closure_digest", identities.sharedClosureIdentityDigest);
|
|
for (const identity of identities.buildMatrix.include) {
|
|
core.setOutput(`${identity.target}_closure_digest`, identity.closure_identity_digest);
|
|
core.setOutput(`${identity.target}_shell_digest`, identity.shell_identity_digest);
|
|
}
|
|
|
|
- name: Probe mac_arm64 content proof
|
|
id: mac_arm64_proof
|
|
uses: ./.github/actions/hash-skip
|
|
env:
|
|
HASH_SKIP_EXTRA_CLOSURE: ${{ steps.execution.outputs.mac_arm64_closure_digest }}
|
|
HASH_SKIP_EXTRA_SHELL: ${{ steps.execution.outputs.mac_arm64_shell_digest }}
|
|
with:
|
|
hash_skip: release.smoke.mac
|
|
|
|
- name: Probe mac_x64 content proof
|
|
id: mac_x64_proof
|
|
uses: ./.github/actions/hash-skip
|
|
env:
|
|
HASH_SKIP_EXTRA_CLOSURE: ${{ steps.execution.outputs.mac_x64_closure_digest }}
|
|
HASH_SKIP_EXTRA_SHELL: ${{ steps.execution.outputs.mac_x64_shell_digest }}
|
|
with:
|
|
hash_skip: release.smoke.mac
|
|
|
|
- name: Probe win_x64 content proof
|
|
id: win_x64_proof
|
|
uses: ./.github/actions/hash-skip
|
|
env:
|
|
HASH_SKIP_EXTRA_CLOSURE: ${{ steps.execution.outputs.win_x64_closure_digest }}
|
|
HASH_SKIP_EXTRA_SHELL: ${{ steps.execution.outputs.win_x64_shell_digest }}
|
|
with:
|
|
hash_skip: release.smoke.win
|
|
|
|
- name: Select content execution topology
|
|
id: selection
|
|
uses: actions/github-script@v8
|
|
env:
|
|
MAC_ARM64_REUSE: ${{ steps.mac_arm64_proof.outputs.skip }}
|
|
MAC_X64_REUSE: ${{ steps.mac_x64_proof.outputs.skip }}
|
|
PROMOTE: ${{ inputs.promote }}
|
|
WIN_X64_REUSE: ${{ steps.win_x64_proof.outputs.skip }}
|
|
with:
|
|
script: |
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const identities = JSON.parse(fs.readFileSync(path.join(process.env.RUNNER_TEMP, "release-identities", "resolved.json"), "utf8"));
|
|
const reusable = {
|
|
mac_arm64: process.env.PROMOTE === "true" && process.env.MAC_ARM64_REUSE === "true",
|
|
mac_x64: process.env.PROMOTE === "true" && process.env.MAC_X64_REUSE === "true",
|
|
win_x64: process.env.PROMOTE === "true" && process.env.WIN_X64_REUSE === "true",
|
|
};
|
|
const include = identities.buildMatrix.include.filter(({ target }) => !reusable[target]);
|
|
core.setOutput("build_matrix", JSON.stringify({ include }));
|
|
core.setOutput("build_count", String(include.length));
|
|
await core.summary.addHeading("Release content topology", 3).addTable([
|
|
[{ data: "Target", header: true }, { data: "Content", header: true }, { data: "Version projection", header: true }],
|
|
...identities.buildMatrix.include.map(({ target }) => [
|
|
target,
|
|
reusable[target] ? "reuse verified registry content" : "runner execution",
|
|
reusable[target] ? "metadata job" : "platform job",
|
|
]),
|
|
]).write();
|
|
|
|
- name: Materialize canonical shared Standalone Closure
|
|
uses: ./.github/actions/release/closure/shared
|
|
env:
|
|
RELEASE_COMMIT: ${{ env.BUILT_SHA }}
|
|
RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION_LOCK_KEY: ${{ steps.reservation.outputs.version_lock_key }}
|
|
RELEASE_VERSION_LOCK_REQUIRED: "true"
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
handoff-enabled: ${{ steps.selection.outputs.build_count != '0' || !inputs.publish || !inputs.promote }}
|
|
identity-digest: ${{ steps.execution.outputs.shared_closure_digest }}
|
|
min-shell-version: ${{ steps.exact.outputs.closure_min_shell_version }}
|
|
publish-enabled: "true"
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
|
|
- name: Project verified mac_arm64 content
|
|
if: ${{ steps.mac_arm64_proof.outputs.skip == 'true' && inputs.promote }}
|
|
uses: ./.github/actions/release/platform/project
|
|
env: &projection_env
|
|
GITHUB_SHA: ${{ env.BUILT_SHA }}
|
|
RELEASE_COMMIT: ${{ env.BUILT_SHA }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION_LOCK_KEY: ${{ steps.reservation.outputs.version_lock_key }}
|
|
RELEASE_VERSION_LOCK_REQUIRED: "true"
|
|
with:
|
|
artifact-id: mac-arm64
|
|
channel: ${{ inputs.exact_name }}
|
|
handoff-enabled: ${{ steps.selection.outputs.build_count != '0' || !inputs.publish || !inputs.promote }}
|
|
closure-identity-digest: ${{ steps.execution.outputs.mac_arm64_closure_digest }}
|
|
platform: darwin-arm64
|
|
public-origin: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
shell-identity-digest: ${{ steps.execution.outputs.mac_arm64_shell_digest }}
|
|
shell-plan-path: ${{ runner.temp }}/release-identity-profiles/mac-arm64.json
|
|
target: mac_arm64
|
|
|
|
- name: Project verified mac_x64 content
|
|
if: ${{ steps.mac_x64_proof.outputs.skip == 'true' && inputs.promote }}
|
|
uses: ./.github/actions/release/platform/project
|
|
env: *projection_env
|
|
with:
|
|
artifact-id: mac-x64
|
|
channel: ${{ inputs.exact_name }}
|
|
handoff-enabled: ${{ steps.selection.outputs.build_count != '0' || !inputs.publish || !inputs.promote }}
|
|
closure-identity-digest: ${{ steps.execution.outputs.mac_x64_closure_digest }}
|
|
platform: darwin-x64
|
|
public-origin: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
shell-identity-digest: ${{ steps.execution.outputs.mac_x64_shell_digest }}
|
|
shell-plan-path: ${{ runner.temp }}/release-identity-profiles/mac-x64.json
|
|
target: mac_x64
|
|
|
|
- name: Project verified win_x64 content
|
|
if: ${{ steps.win_x64_proof.outputs.skip == 'true' && inputs.promote }}
|
|
uses: ./.github/actions/release/platform/project
|
|
env: *projection_env
|
|
with:
|
|
artifact-id: win-x64
|
|
channel: ${{ inputs.exact_name }}
|
|
handoff-enabled: ${{ steps.selection.outputs.build_count != '0' || !inputs.publish || !inputs.promote }}
|
|
closure-identity-digest: ${{ steps.execution.outputs.win_x64_closure_digest }}
|
|
platform: win32-x64
|
|
public-origin: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
shell-identity-digest: ${{ steps.execution.outputs.win_x64_shell_digest }}
|
|
shell-plan-path: ${{ runner.temp }}/release-identity-profiles/win-x64.json
|
|
target: win_x64
|
|
|
|
- name: Stage fully reused exact content
|
|
id: hot_stage
|
|
if: ${{ steps.selection.outputs.build_count == '0' && inputs.publish && inputs.promote }}
|
|
uses: ./.github/actions/release/exact/stage
|
|
env:
|
|
BASE_VERSION: ${{ steps.exact.outputs.base_version }}
|
|
RELEASE_ACTIVATE_LATEST: "false"
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
RELEASE_CLOSURE_DISTRIBUTION_MANIFEST_PATH: ${{ runner.temp }}/release-closure/closure-distribution.json
|
|
RELEASE_CLOSURE_DISTRIBUTION_REQUIRED: "true"
|
|
RELEASE_INSTALLATION_VERSION_MIN_BETA: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_BETA }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_STABLE: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_STABLE }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_URL_BETA: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_URL_BETA }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_URL_STABLE: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_URL_STABLE }}
|
|
RELEASE_LATEST_CAS_REQUIRED: "true"
|
|
RELEASE_LEGACY_INSTALLATION_MIGRATION_REQUIRED: "true"
|
|
RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests
|
|
RELEASE_PUBLIC_ORIGIN: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
RELEASE_SHELL_REQUIRED: "true"
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
RELEASE_VERSION_LOCK_KEY: ${{ steps.reservation.outputs.version_lock_key }}
|
|
RELEASE_VERSION_LOCK_REQUIRED: "true"
|
|
STATE_SOURCE: ${{ steps.reservation.outputs.state_source || steps.exact.outputs.state_source }}
|
|
with:
|
|
exact-name: ${{ inputs.exact_name }}
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
|
|
- name: Plan fully reused public acceptance
|
|
id: hot_acceptance
|
|
if: ${{ steps.hot_stage.outcome == 'success' }}
|
|
uses: ./.github/actions/release/public-acceptance/plan
|
|
with:
|
|
acceptance-matrix: '{"include":[{"artifact_dir":"dmg","os":"mac","runner":"macos-14","target":"mac_arm64"},{"artifact_dir":"dmg","os":"mac","runner":"macos-15-intel","target":"mac_x64"},{"artifact_dir":"builder","os":"win","runner":"windows-latest","target":"win_x64"}]}'
|
|
content-identities: ${{ format('{{"mac_arm64":{{"closure":"{0}","shell":"{1}"}},"mac_x64":{{"closure":"{2}","shell":"{3}"}},"win_x64":{{"closure":"{4}","shell":"{5}"}}}}', steps.execution.outputs.mac_arm64_closure_digest, steps.execution.outputs.mac_arm64_shell_digest, steps.execution.outputs.mac_x64_closure_digest, steps.execution.outputs.mac_x64_shell_digest, steps.execution.outputs.win_x64_closure_digest, steps.execution.outputs.win_x64_shell_digest) }}
|
|
|
|
- name: Activate fully reused exact release
|
|
id: hot_activate
|
|
if: ${{ steps.hot_acceptance.outputs.acceptance_count == '0' }}
|
|
uses: ./.github/actions/release/public-acceptance/activate
|
|
env:
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
commit: ${{ env.BUILT_SHA }}
|
|
metadata-url: ${{ steps.hot_stage.outputs.version_metadata_url }}
|
|
public-origin: ${{ env.RELEASE_PUBLIC_ORIGIN }}
|
|
release-version: ${{ steps.reservation.outputs.release_version || steps.exact.outputs.release_version }}
|
|
reuse-json: ${{ steps.hot_acceptance.outputs.reuse_json }}
|
|
|
|
build:
|
|
name: Build exact ${{ matrix.target }}
|
|
needs: metadata
|
|
if: ${{ needs.metadata.outputs.build_count != '0' }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.metadata.outputs.build_matrix) }}
|
|
runs-on: ${{ matrix.runner }}
|
|
env:
|
|
CLOUDFLARE_R2_RELEASES_AK: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
CLOUDFLARE_R2_RELEASES_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN: ${{ vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
CLOUDFLARE_R2_RELEASES_SK: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
CLOUDFLARE_R2_RELEASES_URL: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
CLOSURE_MIN_SHELL_VERSION: ${{ needs.metadata.outputs.closure_min_shell_version }}
|
|
OPEN_DESIGN_POSTINSTALL_LEVEL: release-smoke
|
|
OD_UPDATE_METADATA_URL: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}/${{ inputs.exact_name }}/latest/metadata.json
|
|
RELEASE_COMMIT: ${{ needs.metadata.outputs.commit }}
|
|
RELEASE_CANDIDATE_ID: ${{ needs.metadata.outputs.candidate_id }}
|
|
RELEASE_VERSION_LOCK_KEY: ${{ needs.metadata.outputs.version_lock_key }}
|
|
RELEASE_VERSION_LOCK_REQUIRED: "true"
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6.0.2
|
|
with:
|
|
ref: ${{ needs.metadata.outputs.commit }}
|
|
- name: Resolve and materialize exact macOS ${{ matrix.target }}
|
|
id: mac_prepare
|
|
if: ${{ matrix.target != 'win_x64' }}
|
|
uses: ./.github/actions/release/platform/mac/exact
|
|
env:
|
|
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_SIGNING_CERTIFICATE_BASE64: ${{ secrets.APPLE_SIGNING_CERTIFICATE_BASE64 }}
|
|
APPLE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_SIGNING_CERTIFICATE_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
amr-profile: ${{ inputs.amr_profile || 'test' }}
|
|
arch: ${{ matrix.target == 'mac_arm64' && 'arm64' || 'x64' }}
|
|
artifact-id: ${{ matrix.target == 'mac_arm64' && 'mac-arm64' || 'mac-x64' }}
|
|
build-target: ${{ matrix.target == 'mac_arm64' && 'dmg' || 'all' }}
|
|
candidate-id: ${{ needs.metadata.outputs.candidate_id }}
|
|
closure-identity-digest: ${{ matrix.closure_identity_digest }}
|
|
closure-shared-identity-digest: ${{ needs.metadata.outputs.closure_shared_identity_digest }}
|
|
closure-version: ${{ needs.metadata.outputs.closure_version }}
|
|
candidate-enabled: ${{ !inputs.promote }}
|
|
legacy-migration-enabled: ${{ matrix.target == 'mac_arm64' && inputs.exact_name == 'beta' && 'true' || 'false' }}
|
|
namespace: ${{ matrix.target == 'mac_arm64' && format('release-{0}', inputs.exact_name) || format('release-{0}-x64', inputs.exact_name) }}
|
|
platform: ${{ matrix.target == 'mac_arm64' && 'darwin-arm64' || 'darwin-x64' }}
|
|
phase: prepare
|
|
publish: "true"
|
|
release-public-origin: ${{ inputs.release_public_origin }}
|
|
release-version: ${{ needs.metadata.outputs.release_version }}
|
|
shell-smoke-matrix: ${{ matrix.target == 'mac_arm64' && 'mac-shell-v3' || 'mac-shell-v2' }}
|
|
shell-identity-digest: ${{ matrix.shell_identity_digest }}
|
|
shell-version: ${{ needs.metadata.outputs.shell_version }}
|
|
sign-mode: notarized
|
|
smoke-lanes-on-miss: ${{ matrix.target == 'mac_x64' && 'shell,standalone' || '' }}
|
|
smoke-mode: full
|
|
target: ${{ matrix.target }}
|
|
update-metadata-url: ""
|
|
update-target-version: ""
|
|
|
|
- name: Smoke and publish exact macOS ${{ matrix.target }}
|
|
id: mac_finish
|
|
if: ${{ matrix.target != 'win_x64' }}
|
|
uses: ./.github/actions/release/platform/mac/exact
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
amr-profile: ${{ inputs.amr_profile || 'test' }}
|
|
arch: ${{ matrix.target == 'mac_arm64' && 'arm64' || 'x64' }}
|
|
artifact-id: ${{ matrix.target == 'mac_arm64' && 'mac-arm64' || 'mac-x64' }}
|
|
build-target: ${{ matrix.target == 'mac_arm64' && 'dmg' || 'all' }}
|
|
candidate-id: ${{ needs.metadata.outputs.candidate_id }}
|
|
closure-identity-digest: ${{ matrix.closure_identity_digest }}
|
|
closure-shared-identity-digest: ${{ needs.metadata.outputs.closure_shared_identity_digest }}
|
|
closure-version: ${{ needs.metadata.outputs.closure_version }}
|
|
candidate-enabled: ${{ !inputs.promote }}
|
|
legacy-migration-enabled: ${{ matrix.target == 'mac_arm64' && inputs.exact_name == 'beta' && 'true' || 'false' }}
|
|
namespace: ${{ matrix.target == 'mac_arm64' && format('release-{0}', inputs.exact_name) || format('release-{0}-x64', inputs.exact_name) }}
|
|
phase: finish
|
|
platform: ${{ matrix.target == 'mac_arm64' && 'darwin-arm64' || 'darwin-x64' }}
|
|
publish: "true"
|
|
release-public-origin: ${{ inputs.release_public_origin }}
|
|
release-version: ${{ needs.metadata.outputs.release_version }}
|
|
shell-smoke-matrix: ${{ matrix.target == 'mac_arm64' && 'mac-shell-v3' || 'mac-shell-v2' }}
|
|
shell-identity-digest: ${{ matrix.shell_identity_digest }}
|
|
shell-version: ${{ needs.metadata.outputs.shell_version }}
|
|
sign-mode: notarized
|
|
smoke-lanes-on-miss: ${{ matrix.target == 'mac_x64' && 'shell,standalone' || '' }}
|
|
smoke-mode: full
|
|
target: ${{ matrix.target }}
|
|
update-metadata-url: ""
|
|
update-target-version: ""
|
|
|
|
- name: Resolve and materialize exact win_x64
|
|
id: win_prepare
|
|
if: ${{ matrix.target == 'win_x64' }}
|
|
uses: ./.github/actions/release/platform/win/exact
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
candidate-id: ${{ needs.metadata.outputs.candidate_id }}
|
|
candidate-enabled: ${{ !inputs.promote }}
|
|
closure-identity-digest: ${{ matrix.closure_identity_digest }}
|
|
closure-shared-identity-digest: ${{ needs.metadata.outputs.closure_shared_identity_digest }}
|
|
release-version: ${{ needs.metadata.outputs.release_version }}
|
|
closure-version: ${{ needs.metadata.outputs.closure_version }}
|
|
shell-version: ${{ needs.metadata.outputs.shell_version }}
|
|
shell-identity-digest: ${{ matrix.shell_identity_digest }}
|
|
amr-profile: ${{ inputs.amr_profile || 'test' }}
|
|
phase: prepare
|
|
publish: "true"
|
|
release-public-origin: ${{ inputs.release_public_origin }}
|
|
sign-mode: unsigned
|
|
smoke-mode: full
|
|
build-target: all
|
|
update-metadata-url: ""
|
|
update-target-version: ""
|
|
|
|
- name: Smoke and publish exact win_x64
|
|
id: win_finish
|
|
if: ${{ matrix.target == 'win_x64' }}
|
|
uses: ./.github/actions/release/platform/win/exact
|
|
with:
|
|
channel: ${{ inputs.exact_name }}
|
|
candidate-id: ${{ needs.metadata.outputs.candidate_id }}
|
|
candidate-enabled: ${{ !inputs.promote }}
|
|
closure-identity-digest: ${{ matrix.closure_identity_digest }}
|
|
closure-shared-identity-digest: ${{ needs.metadata.outputs.closure_shared_identity_digest }}
|
|
release-version: ${{ needs.metadata.outputs.release_version }}
|
|
closure-version: ${{ needs.metadata.outputs.closure_version }}
|
|
shell-version: ${{ needs.metadata.outputs.shell_version }}
|
|
shell-identity-digest: ${{ matrix.shell_identity_digest }}
|
|
amr-profile: ${{ inputs.amr_profile || 'test' }}
|
|
phase: finish
|
|
publish: "true"
|
|
release-public-origin: ${{ inputs.release_public_origin }}
|
|
sign-mode: unsigned
|
|
smoke-mode: full
|
|
build-target: all
|
|
update-metadata-url: ""
|
|
update-target-version: ""
|
|
|
|
- name: Write ${{ matrix.target }} build result
|
|
if: ${{ always() }}
|
|
uses: actions/github-script@v8
|
|
env:
|
|
RESULT_SMOKE: ${{ steps.mac_finish.outputs.smoke_result || steps.win_finish.outputs.smoke_result }}
|
|
RESULT_TARGET: ${{ matrix.target }}
|
|
RESULT_URL: ${{ steps.mac_finish.outputs.dmg_url || steps.win_finish.outputs.win_x64_url || steps.mac_prepare.outputs.candidate_primary_url || steps.win_prepare.outputs.candidate_primary_url }}
|
|
RESULT_CANDIDATE_MANIFEST_URL: ${{ steps.mac_prepare.outputs.candidate_manifest_url || steps.win_prepare.outputs.candidate_manifest_url }}
|
|
with:
|
|
script: |
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const root = path.join(process.env.RUNNER_TEMP, "release-platform-result");
|
|
fs.mkdirSync(root, { recursive: true });
|
|
fs.writeFileSync(path.join(root, `${process.env.RESULT_TARGET}.json`), JSON.stringify({
|
|
candidateManifestUrl: process.env.RESULT_CANDIDATE_MANIFEST_URL || "",
|
|
smokeResult: process.env.RESULT_SMOKE || "",
|
|
target: process.env.RESULT_TARGET,
|
|
url: process.env.RESULT_URL || "",
|
|
}));
|
|
|
|
- name: Upload ${{ matrix.target }} build result
|
|
if: ${{ always() }}
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-${{ matrix.target }}-build-result
|
|
path: ${{ runner.temp }}/release-platform-result/${{ matrix.target }}.json
|
|
if-no-files-found: error
|
|
|
|
candidate:
|
|
name: Seal exact candidate
|
|
needs: [metadata, build, stage]
|
|
if: ${{ !cancelled() && !inputs.promote && needs.metadata.result == 'success' && (needs.build.result == 'success' || needs.build.result == 'skipped') && needs.stage.result == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
manifest_url: ${{ steps.finalize.outputs.candidate_manifest_url }}
|
|
mac_arm64_url: ${{ steps.links.outputs.mac_arm64_url }}
|
|
mac_x64_url: ${{ steps.links.outputs.mac_x64_url }}
|
|
win_x64_url: ${{ steps.links.outputs.win_x64_url }}
|
|
steps:
|
|
- name: Checkout candidate finalizer
|
|
uses: actions/checkout@v6.0.2
|
|
with:
|
|
ref: ${{ needs.metadata.outputs.commit }}
|
|
- name: Setup release toolchain
|
|
uses: ./.github/actions/release/platform/setup
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Download candidate spec
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-candidate-spec
|
|
path: ${{ runner.temp }}/release-candidate
|
|
- name: Download platform results
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: open-design-${{ inputs.exact_name }}-*-build-result
|
|
path: ${{ runner.temp }}/release-platform-results
|
|
merge-multiple: true
|
|
- name: Prepare candidate target URLs and links
|
|
id: links
|
|
run: |
|
|
set -euo pipefail
|
|
jq -s '[.[].candidateManifestUrl | select(length > 0)]' "$RUNNER_TEMP"/release-platform-results/*.json > "$RUNNER_TEMP/release-candidate/target-urls.json"
|
|
for target in mac_arm64 mac_x64 win_x64; do
|
|
url="$(jq -r --arg target "$target" '. | select(.target == $target) | .url' "$RUNNER_TEMP"/release-platform-results/*.json)"
|
|
echo "${target}_url=$url" >> "$GITHUB_OUTPUT"
|
|
done
|
|
- name: Seal candidate manifest
|
|
id: finalize
|
|
env:
|
|
RELEASE_CANDIDATE_SPEC_PATH: ${{ runner.temp }}/release-candidate/spec.json
|
|
RELEASE_CANDIDATE_TARGET_URLS_PATH: ${{ runner.temp }}/release-candidate/target-urls.json
|
|
RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION_METADATA_URL: ${{ needs.stage.outputs.version_metadata_url }}
|
|
run: pnpm exec tools-release finalize-candidate
|
|
|
|
stage:
|
|
name: Stage exact metadata
|
|
needs:
|
|
- metadata
|
|
- build
|
|
if: >-
|
|
${{
|
|
always() &&
|
|
!cancelled() &&
|
|
needs.metadata.result == 'success' &&
|
|
needs.metadata.outputs.hot_staged != 'true' &&
|
|
(needs.build.result == 'success' || needs.build.result == 'skipped')
|
|
}}
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
acceptance_latest_url: ${{ steps.staged.outputs.acceptance_latest_url }}
|
|
release_state: ${{ steps.staged.outputs.release_state }}
|
|
version_metadata_url: ${{ steps.staged.outputs.version_metadata_url }}
|
|
mac_arm64_url: ${{ steps.staged.outputs.mac_arm64_url }}
|
|
win_x64_url: ${{ steps.staged.outputs.win_x64_url }}
|
|
mac_x64_url: ${{ steps.staged.outputs.mac_x64_url }}
|
|
mac_arm64_smoke_result: ${{ steps.platform_results.outputs.mac_arm64_smoke_result }}
|
|
mac_x64_smoke_result: ${{ steps.platform_results.outputs.mac_x64_smoke_result }}
|
|
win_x64_smoke_result: ${{ steps.platform_results.outputs.win_x64_smoke_result }}
|
|
env:
|
|
GITHUB_SHA: ${{ needs.metadata.outputs.commit }}
|
|
OPEN_DESIGN_POSTINSTALL_LEVEL: release-prepare
|
|
RELEASE_COMMIT: ${{ needs.metadata.outputs.commit }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6.0.2
|
|
with:
|
|
ref: ${{ needs.metadata.outputs.commit }}
|
|
|
|
- name: Download mac_arm64 publish manifest
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-mac-arm64-publish-manifest
|
|
path: ${{ runner.temp }}/release-platform-manifests
|
|
|
|
- name: Download mac_x64 publish manifest
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-mac-x64-publish-manifest
|
|
path: ${{ runner.temp }}/release-platform-manifests
|
|
|
|
- name: Download win_x64 publish manifest
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-win-x64-publish-manifest
|
|
path: ${{ runner.temp }}/release-platform-manifests
|
|
|
|
- name: Download shared Standalone contract
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-closure-shared
|
|
path: ${{ runner.temp }}/release-closure/shared
|
|
|
|
- name: Download mac_arm64 Standalone contribution
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-closure-darwin-arm64
|
|
path: ${{ runner.temp }}/release-closure/targets/darwin-arm64
|
|
|
|
- name: Download mac_x64 Standalone contribution
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-closure-darwin-x64
|
|
path: ${{ runner.temp }}/release-closure/targets/darwin-x64
|
|
|
|
- name: Download win_x64 Standalone contribution
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: open-design-${{ inputs.exact_name }}-closure-win32-x64
|
|
path: ${{ runner.temp }}/release-closure/targets/win32-x64
|
|
|
|
- name: Setup pnpm
|
|
uses: pnpm/action-setup@v5
|
|
with:
|
|
version: 10.33.2
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: 24.18.0
|
|
cache: pnpm
|
|
cache-dependency-path: pnpm-lock.yaml
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Download platform build results
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: open-design-${{ inputs.exact_name }}-*-build-result
|
|
merge-multiple: true
|
|
path: ${{ runner.temp }}/release-platform-results
|
|
|
|
- name: Read platform build results
|
|
id: platform_results
|
|
uses: actions/github-script@v8
|
|
with:
|
|
script: |
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const root = path.join(process.env.RUNNER_TEMP, "release-platform-results");
|
|
for (const target of ["mac_arm64", "mac_x64", "win_x64"]) {
|
|
const file = path.join(root, `${target}.json`);
|
|
if (!fs.existsSync(file)) continue;
|
|
const result = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
core.setOutput(`${target}_smoke_result`, String(result.smokeResult || ""));
|
|
}
|
|
|
|
- name: Stage exact release content
|
|
id: staged
|
|
uses: ./.github/actions/release/exact/stage
|
|
with:
|
|
exact-name: ${{ inputs.exact_name }}
|
|
release-version: ${{ needs.metadata.outputs.release_version }}
|
|
env:
|
|
BASE_VERSION: ${{ needs.metadata.outputs.base_version }}
|
|
RELEASE_ACTIVATE_LATEST: "false"
|
|
RELEASE_CHANNEL: ${{ inputs.exact_name }}
|
|
RELEASE_CLOSURE_DISTRIBUTION_MANIFEST_PATH: ${{ runner.temp }}/release-closure/closure-distribution.json
|
|
RELEASE_CLOSURE_DISTRIBUTION_REQUIRED: "true"
|
|
RELEASE_SHELL_REQUIRED: "true"
|
|
RELEASE_INSTALLATION_VERSION_MIN_BETA: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_BETA }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_STABLE: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_STABLE }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_URL_BETA: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_URL_BETA }}
|
|
RELEASE_INSTALLATION_VERSION_MIN_URL_STABLE: ${{ vars.RELEASE_LAUNCHER_VERSION_MIN_URL_STABLE }}
|
|
RELEASE_LEGACY_INSTALLATION_MIGRATION_REQUIRED: ${{ inputs.exact_name == 'beta' && 'true' || 'false' }}
|
|
RELEASE_LATEST_CAS_REQUIRED: "true"
|
|
RELEASE_VERSION_LOCK_KEY: ${{ needs.metadata.outputs.version_lock_key }}
|
|
RELEASE_VERSION_LOCK_REQUIRED: "true"
|
|
RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests
|
|
RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_RELEASES_AK }}
|
|
RELEASE_STORAGE_BUCKET: ${{ secrets.CLOUDFLARE_R2_RELEASES_BUCKET }}
|
|
RELEASE_STORAGE_ENDPOINT: ${{ secrets.CLOUDFLARE_R2_RELEASES_URL }}
|
|
RELEASE_STORAGE_REGION: auto
|
|
RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_RELEASES_SK }}
|
|
RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }}
|
|
STATE_SOURCE: ${{ needs.metadata.outputs.state_source }}
|
|
|
|
|
|
accept:
|
|
name: Accept and activate exact release
|
|
needs:
|
|
- metadata
|
|
- stage
|
|
if: >-
|
|
${{
|
|
!cancelled() &&
|
|
inputs.publish &&
|
|
inputs.promote &&
|
|
needs.metadata.result == 'success' &&
|
|
needs.metadata.outputs.hot_activated != 'true' &&
|
|
(needs.stage.result == 'success' || needs.metadata.outputs.hot_staged == 'true') &&
|
|
(needs.stage.outputs.release_state == 'complete' || needs.metadata.outputs.hot_release_state == 'complete')
|
|
}}
|
|
uses: ./.github/workflows/distribution-exact-accept.yml
|
|
secrets: inherit
|
|
with:
|
|
commit: ${{ needs.metadata.outputs.commit }}
|
|
content_identities: ${{ format('{{"mac_arm64":{{"closure":"{0}","shell":"{1}"}},"mac_x64":{{"closure":"{2}","shell":"{3}"}},"win_x64":{{"closure":"{4}","shell":"{5}"}}}}', needs.metadata.outputs.mac_arm64_closure_identity_digest, needs.metadata.outputs.mac_arm64_shell_identity_digest, needs.metadata.outputs.mac_x64_closure_identity_digest, needs.metadata.outputs.mac_x64_shell_identity_digest, needs.metadata.outputs.win_x64_closure_identity_digest, needs.metadata.outputs.win_x64_shell_identity_digest) }}
|
|
exact_name: ${{ inputs.exact_name }}
|
|
metadata_url: ${{ needs.metadata.outputs.hot_version_metadata_url || needs.stage.outputs.version_metadata_url }}
|
|
mutable_metadata_url: ${{ needs.metadata.outputs.hot_acceptance_latest_url || needs.stage.outputs.acceptance_latest_url }}
|
|
public_origin: ${{ inputs.release_public_origin != '' && inputs.release_public_origin || vars.CLOUDFLARE_R2_RELEASES_PUBLIC_ORIGIN }}
|
|
release_version: ${{ needs.metadata.outputs.release_version }}
|
|
|
|
notify:
|
|
name: Report exact release
|
|
needs:
|
|
- metadata
|
|
- build
|
|
- candidate
|
|
- stage
|
|
- accept
|
|
if: ${{ always() && !cancelled() }}
|
|
uses: ./.github/workflows/release-notify.yml
|
|
with:
|
|
activation_completed_at: ${{ needs.metadata.outputs.hot_activation_completed_at || needs.accept.outputs.activation_completed_at }}
|
|
actor: ${{ github.actor }}
|
|
branch: ${{ needs.metadata.outputs.branch }}
|
|
channel: ${{ inputs.exact_name }}
|
|
commit: ${{ needs.metadata.outputs.commit }}
|
|
event_name: ${{ github.event_name }}
|
|
mac_arm64_smoke: ${{ needs.metadata.outputs.hot_staged == 'true' && 'success' || needs.stage.outputs.mac_arm64_smoke_result }}
|
|
mac_arm64_url: ${{ !inputs.publish && needs.candidate.outputs.mac_arm64_url || needs.metadata.outputs.hot_mac_arm64_url || needs.stage.outputs.mac_arm64_url }}
|
|
mac_x64_smoke: ${{ needs.metadata.outputs.hot_staged == 'true' && 'success' || needs.stage.outputs.mac_x64_smoke_result }}
|
|
mac_x64_url: ${{ !inputs.publish && needs.candidate.outputs.mac_x64_url || needs.metadata.outputs.hot_mac_x64_url || needs.stage.outputs.mac_x64_url }}
|
|
metadata_url: ${{ !inputs.publish && needs.candidate.outputs.manifest_url || needs.metadata.outputs.hot_version_metadata_url || needs.stage.outputs.version_metadata_url }}
|
|
notification_stream: ${{ inputs.notification_stream || 'release' }}
|
|
previous_commit: ${{ needs.metadata.outputs.previous_commit }}
|
|
release_mode: ${{ inputs.publish && (inputs.promote && 'promote' || 'publish') || 'candidate' }}
|
|
release_result: ${{ needs.metadata.outputs.hot_activated == 'true' && 'success' || needs.accept.result != 'skipped' && needs.accept.result || needs.stage.result != 'skipped' && needs.stage.result || needs.build.result }}
|
|
release_state: ${{ needs.metadata.outputs.hot_activated == 'true' && 'complete' || needs.accept.result == 'success' && 'complete' || needs.metadata.outputs.hot_release_state || needs.stage.outputs.release_state || (needs.build.result == 'success' && 'partial' || 'failed') }}
|
|
run_attempt: ${{ github.run_attempt }}
|
|
run_number: ${{ github.run_number }}
|
|
triggering_actor: ${{ github.triggering_actor }}
|
|
version: ${{ needs.metadata.outputs.release_version }}
|
|
win_x64_smoke: ${{ needs.metadata.outputs.hot_staged == 'true' && 'success' || needs.stage.outputs.win_x64_smoke_result }}
|
|
win_x64_url: ${{ !inputs.publish && needs.candidate.outputs.win_x64_url || needs.metadata.outputs.hot_win_x64_url || needs.stage.outputs.win_x64_url }}
|
|
workflow_name: ${{ github.workflow }}
|
|
secrets:
|
|
bot: ${{ secrets.RELEASE_FEISHU_BETA }}
|