name: release-beta-s on: workflow_dispatch: inputs: enable_mac_arm64: description: "Run the self-hosted macOS arm64 betas lane." required: true type: boolean default: true enable_win_x64: description: "Run the self-hosted Windows x64 betas lane." required: true type: boolean default: true enable_mac_x64: description: "Run the self-hosted macOS x64 betas lane." required: true type: boolean default: false enable_linux_x64: description: "Run the self-hosted Linux x64 betas lane." required: true type: boolean default: false publish: description: "Publish betas assets and metadata to the selected S3-compatible origin." required: true type: boolean default: true release_version: description: "Optional betas version override. Empty resolves the next betas version from metadata." required: false type: string default: "" release_origin: description: "Release storage origin." required: true type: choice options: - nexu-s3 default: nexu-s3 release_public_origin: description: "Anonymous-read public origin for the self-hosted S3 publish target." required: true type: string default: "https://s3.nexu.space/od-releases" ref: description: "Optional git ref to build. Empty builds the dispatched ref." required: false type: string default: "" mac_arm64_delivery_mode: description: "macOS arm64 delivery policy. Internal updater signs payloads without notarization; public notarized validates first-install DMGs." required: true type: choice options: - "internal-updater" - "public-notarized" default: "internal-updater" mac_arm64_sign_mode: description: "macOS arm64 signing mode used when delivery mode is public-notarized." required: true type: choice options: - "no" - "sign-only" - "notarize" default: "sign-only" mac_arm64_smoke_mode: description: "macOS arm64 smoke coverage." required: true type: choice options: - skip - core - full default: core mac_arm64_target: description: "macOS arm64 build target." required: true type: choice options: - dmg - all default: dmg mac_arm64_update_metadata_url: description: "Optional external updater metadata URL for full macOS arm64 payload smoke." required: false type: string default: "" mac_arm64_update_target_version: description: "Optional external updater target version expected by full macOS arm64 payload smoke." required: false type: string default: "" mac_x64_sign_mode: description: "macOS x64 signing mode." required: true type: choice options: - "no" - "sign-only" - "notarize" default: "no" mac_x64_smoke_mode: description: "macOS x64 smoke coverage." required: true type: choice options: - skip - core - full default: skip mac_x64_target: description: "macOS x64 build target." required: true type: choice options: - dmg - all default: all win_x64_sign_mode: description: "Windows x64 signing mode." required: true type: choice options: - "off" - "on" default: "off" win_x64_smoke_mode: description: "Windows x64 smoke coverage." required: true type: choice options: - skip - core - full default: core win_x64_target: description: "Windows x64 build target." required: true type: choice options: - nsis - all - zip - dir default: all linux_x64_smoke_mode: description: "Linux x64 smoke coverage." required: true type: choice options: - skip - core - full default: core win_x64_update_metadata_url: description: "Optional external updater metadata URL for full Windows smoke." required: false type: string default: "" win_x64_update_target_version: description: "Optional external updater target version expected by full Windows smoke." required: false type: string default: "" workflow_call: inputs: enable_mac_arm64: required: false type: boolean default: true enable_win_x64: required: false type: boolean default: true enable_mac_x64: required: false type: boolean default: false enable_linux_x64: required: false type: boolean default: false publish: required: false type: boolean default: true release_version: required: false type: string default: "" release_origin: required: false type: string default: nexu-s3 release_public_origin: required: false type: string default: "https://s3.nexu.space/od-releases" ref: required: false type: string default: "" mac_arm64_delivery_mode: required: false type: string default: internal-updater mac_arm64_sign_mode: required: false type: string default: sign-only mac_arm64_smoke_mode: required: false type: string default: core mac_arm64_target: required: false type: string default: dmg mac_arm64_update_metadata_url: required: false type: string default: "" mac_arm64_update_target_version: required: false type: string default: "" mac_x64_sign_mode: required: false type: string default: "no" mac_x64_smoke_mode: required: false type: string default: skip mac_x64_target: required: false type: string default: all win_x64_sign_mode: required: false type: string default: "off" win_x64_smoke_mode: required: false type: string default: core win_x64_target: required: false type: string default: all linux_x64_smoke_mode: required: false type: string default: core win_x64_update_metadata_url: required: false type: string default: "" win_x64_update_target_version: required: false type: string default: "" outputs: release_version: description: "The betas version that was built." value: ${{ jobs.metadata.outputs.release_version }} branch: description: "The branch that was built." value: ${{ jobs.metadata.outputs.branch }} commit: description: "The commit SHA that was built." value: ${{ jobs.metadata.outputs.commit }} previous_commit: description: "Commit SHA of the previously published betas." value: ${{ jobs.metadata.outputs.previous_commit }} release_state: description: "complete | partial | failed." value: ${{ jobs.publish.outputs.release_state }} version_metadata_url: description: "Public URL of this build's version metadata.json." value: ${{ jobs.publish.outputs.version_metadata_url }} mac_arm64_url: description: "macOS arm64 dmg download URL." value: ${{ jobs.publish.outputs.mac_arm64_url }} win_x64_url: description: "Windows x64 installer download URL." value: ${{ jobs.publish.outputs.win_x64_url }} mac_x64_url: description: "macOS x64 dmg download URL." value: ${{ jobs.publish.outputs.mac_x64_url }} linux_x64_url: description: "Linux x64 AppImage download URL." value: ${{ jobs.publish.outputs.linux_x64_url }} permissions: contents: read actions: read env: OPEN_DESIGN_TELEMETRY_RELAY_URL: ${{ vars.OPEN_DESIGN_TELEMETRY_RELAY_URL }} 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 }} RELEASE_BRANCH: ${{ github.ref_name }} RELEASE_REPOSITORY: ${{ github.repository }} RELEASE_RUN_ATTEMPT: ${{ github.run_attempt }} RELEASE_RUN_ID: ${{ github.run_id }} RELEASE_WORKFLOW: ${{ github.workflow }} OPEN_DESIGN_RELEASE_PROFILE: /Users/runner/.profile jobs: metadata: name: Prepare betas metadata if: ${{ inputs.enable_mac_arm64 || inputs.enable_win_x64 || inputs.enable_mac_x64 || inputs.enable_linux_x64 }} runs-on: [self-hosted, macOS, ARM64, nexu-mac, release-beta] env: OPEN_DESIGN_BETAS_METADATA_URL: ${{ inputs.release_public_origin }}/betas/latest/metadata.json OPEN_DESIGN_STABLE_METADATA_URL: https://releases.open-design.ai/stable/latest/metadata.json outputs: asset_version_suffix: ${{ steps.betas.outputs.asset_version_suffix }} base_version: ${{ steps.betas.outputs.base_version }} release_version: ${{ inputs.publish && steps.reserve.outputs.release_version || inputs.release_version != '' && inputs.release_version || steps.betas.outputs.release_version }} branch: ${{ steps.betas.outputs.branch }} commit: ${{ steps.betas.outputs.commit }} previous_commit: ${{ steps.prev.outputs.previous_commit }} release_name: ${{ inputs.publish && steps.reserve.outputs.release_name || steps.betas.outputs.release_name }} state_source: ${{ inputs.publish && steps.reserve.outputs.state_source || steps.betas.outputs.state_source }} version_lock_key: ${{ steps.reserve.outputs.version_lock_key }} version_lock_url: ${{ steps.reserve.outputs.version_lock_url }} steps: - name: Checkout metadata sources id: checkout env: CHECKOUT_REF: ${{ inputs.ref != '' && inputs.ref || github.ref_name }} GITHUB_TOKEN: ${{ github.token }} run: | set -euo pipefail repo_dir="$PWD/_release-metadata" repository_url="https://github.com/${GITHUB_REPOSITORY}.git" auth_token="$(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 | tr -d '\n')" auth_config="http.https://github.com/.extraheader=AUTHORIZATION: basic $auth_token" case "$CHECKOUT_REF" in refs/heads/*) fetch_source="$CHECKOUT_REF" ;; refs/tags/*) fetch_source="$CHECKOUT_REF" ;; *) if [[ "$CHECKOUT_REF" =~ ^[0-9a-fA-F]{40}$ ]]; then fetch_source="$CHECKOUT_REF" else fetch_source="refs/heads/$CHECKOUT_REF" fi ;; esac checkout_branch="_release-metadata" checkout_start="refs/remotes/origin/$checkout_branch" fetch_ref="+$fetch_source:$checkout_start" mkdir -p "$repo_dir" if [ ! -d "$repo_dir/.git" ]; then find "$repo_dir" -mindepth 1 -maxdepth 1 -exec rm -rf {} + git init "$repo_dir" git -C "$repo_dir" remote add origin "$repository_url" else current_url="$(git -C "$repo_dir" config --local --get remote.origin.url || true)" if [ "$current_url" != "$repository_url" ]; then find "$repo_dir" -mindepth 1 -maxdepth 1 -exec rm -rf {} + git init "$repo_dir" git -C "$repo_dir" remote add origin "$repository_url" else rm -f "$repo_dir/.git/index.lock" "$repo_dir/.git/shallow.lock" git -C "$repo_dir" remote set-url origin "$repository_url" fi fi git config --global --add safe.directory "$repo_dir" git -C "$repo_dir" config --local gc.auto 0 git -C "$repo_dir" sparse-checkout disable || true git -C "$repo_dir" config --local core.sparseCheckout false git -C "$repo_dir" config --local core.sparseCheckoutCone false sparse_path="$(git -C "$repo_dir" rev-parse --git-path info/sparse-checkout)" rm -f "$sparse_path" for attempt in 1 2 3; do if git -C "$repo_dir" -c protocol.version=2 -c "$auth_config" fetch --no-tags --prune --no-recurse-submodules --filter=blob:none --depth=1 origin "$fetch_ref"; then if git -C "$repo_dir" -c "$auth_config" checkout --progress --force -B "$checkout_branch" "$checkout_start"; then break fi fi if [ "$attempt" -eq 3 ]; then echo "metadata checkout failed after $attempt attempts" >&2 exit 1 fi sleep "$((attempt * 5))" done commit="$(git -C "$repo_dir" rev-parse HEAD)" test -d "$repo_dir/packages" || { echo "metadata checkout is missing packages/; pnpm workspace install cannot run" >&2 exit 1 } echo "checked out metadata sources at $commit" echo "commit=$commit" >> "$GITHUB_OUTPUT" - name: Install metadata toolchain working-directory: _release-metadata run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm install --frozen-lockfile --prefer-offline - name: Validate self-hosted beta inputs run: | set -euo pipefail if [ "${{ inputs.release_origin }}" != "nexu-s3" ]; then echo "release-beta-s supports release_origin=nexu-s3 only" >&2 exit 1 fi if [ -z "${{ inputs.release_public_origin }}" ]; then echo "release_public_origin is required" >&2 exit 1 fi if [ "${{ inputs.enable_mac_arm64 }}" != "true" ] && [ "${{ inputs.enable_win_x64 }}" != "true" ] && [ "${{ inputs.enable_mac_x64 }}" != "true" ] && [ "${{ inputs.enable_linux_x64 }}" != "true" ]; then echo "release-beta-s requires at least one target to be enabled" >&2 exit 1 fi if [ "${{ inputs.publish }}" = "true" ] && [ "${{ inputs.enable_win_x64 }}" = "true" ] && [ "${{ inputs.win_x64_target }}" != "nsis" ] && [ "${{ inputs.win_x64_target }}" != "all" ]; then echo "release-beta-s publish requires win_x64_target=nsis or all so the installer and updater feed are produced" >&2 exit 1 fi case "${{ inputs.mac_arm64_delivery_mode }}" in internal-updater | public-notarized) ;; *) echo "unsupported mac_arm64_delivery_mode: ${{ inputs.mac_arm64_delivery_mode }}" >&2 exit 1 ;; esac if [ "${{ inputs.mac_arm64_delivery_mode }}" = "public-notarized" ] && [ "${{ inputs.mac_arm64_sign_mode }}" != "notarize" ]; then echo "public-notarized mac_arm64_delivery_mode requires mac_arm64_sign_mode=notarize" >&2 exit 1 fi - name: Capture previous betas commit id: prev run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" prev="$(curl -fsSL "$OPEN_DESIGN_BETAS_METADATA_URL" | jq -r '.github.commit // ""' 2>/dev/null || true)" echo "previous betas commit: ${prev:-}" echo "previous_commit=$prev" >> "$GITHUB_OUTPUT" - name: Prepare betas release metadata id: betas working-directory: _release-metadata env: GITHUB_REF_NAME: ${{ inputs.ref != '' && inputs.ref || github.ref_name }} GITHUB_SHA: ${{ steps.checkout.outputs.commit }} run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release prepare betas - name: Reserve betas version if: ${{ inputs.publish }} id: reserve working-directory: _release-metadata env: BASE_VERSION: ${{ steps.betas.outputs.base_version }} RELEASE_CHANNEL: betas RELEASE_COMMIT: ${{ steps.checkout.outputs.commit }} RELEASE_LANE: release-beta-s RELEASE_METADATA_DIR: ${{ runner.temp }}/release-version-reservation RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin }} RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_VERSION_CANDIDATE: ${{ inputs.release_version != '' && inputs.release_version || steps.betas.outputs.release_version }} RELEASE_VERSION_MANUAL_OVERRIDE: ${{ inputs.release_version != '' && 'true' || 'false' }} run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release reserve-version betas unsupported_mac_x64: name: Reject unsupported self-hosted mac_x64 if: ${{ inputs.enable_mac_x64 }} runs-on: [self-hosted, macOS, ARM64, nexu-mac, release-beta] steps: - run: | echo "release-beta-s does not have a self-hosted mac_x64 runner lane yet" >&2 exit 1 unsupported_linux_x64: name: Reject unsupported self-hosted linux_x64 if: ${{ inputs.enable_linux_x64 }} runs-on: [self-hosted, macOS, ARM64, nexu-mac, release-beta] steps: - run: | echo "release-beta-s does not have a self-hosted linux_x64 runner lane yet" >&2 exit 1 build_mac_arm64: name: Build self-hosted beta mac_arm64 needs: metadata if: ${{ inputs.enable_mac_arm64 }} runs-on: [self-hosted, macOS, ARM64, nexu-mac, release-beta] timeout-minutes: 45 env: MAC_TOOLS_PACK_CACHE_DIR: /Users/runner/.tmp/runner/od-beta/mac_arm64/tools-pack-cache MAC_TOOLS_PACK_DIR: /Users/runner/.tmp/runner/od-beta/mac_arm64/tools-pack RELEASE_COMMIT: ${{ needs.metadata.outputs.commit }} steps: - name: Checkout uses: actions/checkout@v6.0.2 with: clean: true fetch-depth: 1 lfs: false path: _release-build ref: ${{ needs.metadata.outputs.commit }} - name: Prepare self-hosted mac toolchain working-directory: _release-build run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- corepack prepare pnpm@10.33.2 --activate fnm exec --using=24 -- pnpm install --frozen-lockfile - name: Build betas mac_arm64 working-directory: _release-build env: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_NOTARY_KEYCHAIN_PROFILE: open-design-release-notary 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 }} BUILD_JSON_PATH: ${{ runner.temp }}/release-build/mac_arm64/build.json BUILD_LOG_PATH: ${{ runner.temp }}/release-build/mac_arm64/build.log CSC_KEYCHAIN: /Library/Keychains/open-design-release-signing.keychain OD_UPDATE_METADATA_URL: ${{ inputs.release_public_origin }}/betas/latest/metadata.json OD_PACKAGED_E2E_MAC_UPDATE_METADATA_URL: ${{ inputs.mac_arm64_update_metadata_url }} OD_PACKAGED_E2E_MAC_UPDATE_VERSION: ${{ inputs.mac_arm64_update_target_version }} RELEASE_BUILD_TARGET: ${{ inputs.mac_arm64_target }} RELEASE_CHANNEL: betas RELEASE_DELIVERY_MODE: ${{ inputs.mac_arm64_delivery_mode }} RELEASE_NAMESPACE: release-betas RELEASE_OUTPUTS_PATH: ${{ runner.temp }}/release-build/mac_arm64/outputs.json RELEASE_REPORT_DIR: ${{ runner.temp }}/release-report/mac_arm64 RELEASE_SIGN_MODE: ${{ inputs.mac_arm64_delivery_mode == 'internal-updater' && 'sign-only' || inputs.mac_arm64_sign_mode }} RELEASE_SMOKE_MODE: ${{ inputs.mac_arm64_smoke_mode }} RELEASE_TARGET: mac_arm64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} RELEASE_WORK_DIR: ${{ runner.temp }}/release-work/mac_arm64 REQUIRE_VELA_CLI: "true" TOOLS_PACK_CACHE_DIR: ${{ env.MAC_TOOLS_PACK_CACHE_DIR }} TOOLS_PACK_DIR: ${{ env.MAC_TOOLS_PACK_DIR }} run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" export PATH="/usr/local/libexec/open-design/wrappers:$PATH" if [ "${{ inputs.mac_arm64_delivery_mode == 'internal-updater' && 'sign-only' || inputs.mac_arm64_sign_mode }}" != "no" ] && [ -n "${OPEN_DESIGN_MAC_SIGNING_HELPER:-}" ]; then cert_path="${{ runner.temp }}/open-design-signing.p12" password_path="${{ runner.temp }}/open-design-signing.p12.password" if ! printf '%s' "$APPLE_SIGNING_CERTIFICATE_BASE64" | base64 --decode > "$cert_path" 2>/dev/null; then printf '%s' "$APPLE_SIGNING_CERTIFICATE_BASE64" | base64 -D > "$cert_path" fi printf '%s' "$APPLE_SIGNING_CERTIFICATE_PASSWORD" > "$password_path" chmod 600 "$password_path" sudo -n "$OPEN_DESIGN_MAC_SIGNING_HELPER" "$cert_path" "$password_path" rm -f "$password_path" export CSC_KEYCHAIN="${OPEN_DESIGN_MAC_SIGNING_KEYCHAIN:-/Library/Keychains/open-design-release-signing.keychain}" security list-keychains -d user -s "$CSC_KEYCHAIN" /Library/Keychains/System.keychain fi fnm exec --using=24 -- bash tools/release/scripts/build-platform.sh - name: Write mac_arm64 release report if: ${{ always() }} working-directory: _release-build env: BUILD_JSON_PATH: ${{ runner.temp }}/release-build/mac_arm64/build.json BUILD_LOG_PATH: ${{ runner.temp }}/release-build/mac_arm64/build.log RELEASE_BUILD_TARGET: ${{ inputs.mac_arm64_target }} RELEASE_CHANNEL: betas RELEASE_DELIVERY_MODE: ${{ inputs.mac_arm64_delivery_mode }} RELEASE_NAMESPACE: release-betas RELEASE_REPORT_DIR: ${{ runner.temp }}/release-report/mac_arm64 RELEASE_REPORT_JSON_PATH: ${{ runner.temp }}/release-report/mac_arm64/report.json RELEASE_REPORT_SUMMARY_PATH: ${{ runner.temp }}/release-report/mac_arm64/summary.md RELEASE_SMOKE_MODE: ${{ inputs.mac_arm64_smoke_mode }} RELEASE_TARGET: mac_arm64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} REPORT_TITLE: self-hosted mac_arm64 betas build run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release write-report - name: Publish mac_arm64 report summary if: ${{ always() }} run: cat "${{ runner.temp }}/release-report/mac_arm64/summary.md" >> "$GITHUB_STEP_SUMMARY" - name: Prepare mac_arm64 assets if: ${{ inputs.publish }} working-directory: _release-build env: RELEASE_ARTIFACT_MODE: dmg-and-payload RELEASE_ASSET_SUFFIX: ${{ (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && '.signed' || '.unsigned' }} RELEASE_ASSETS_DIR: ${{ runner.temp }}/release-assets/mac_arm64 RELEASE_CHANNEL: betas RELEASE_NAMESPACE: release-betas RELEASE_NOTES: Open Design betas ${{ needs.metadata.outputs.release_version }}${{ (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && '.signed' || '.unsigned' }} ${{ inputs.mac_arm64_delivery_mode }} RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin }} RELEASE_TARGET: mac_arm64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} TOOLS_PACK_DIR: ${{ env.MAC_TOOLS_PACK_DIR }} run: bash tools/release/scripts/prepare-platform-assets.sh - name: Publish mac_arm64 platform if: ${{ inputs.publish }} working-directory: _release-build env: RELEASE_ASSET_SUFFIX: ${{ (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && '.signed' || '.unsigned' }} RELEASE_ASSETS_DIR: ${{ runner.temp }}/release-assets/mac_arm64 RELEASE_ARTIFACT_MODE: dmg-and-payload RELEASE_CHANNEL: betas RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests RELEASE_OUTPUTS_PATH: ${{ runner.temp }}/release-platform-outputs/mac_arm64.json RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin }} RELEASE_REPORT_DIR: ${{ runner.temp }}/release-report/mac_arm64 RELEASE_REPORT_ZIP_PATH: ${{ runner.temp }}/release-report/mac_arm64-report.zip RELEASE_SIGNED: ${{ (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && 'true' || 'false' }} RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_TARGET: mac_arm64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} RELEASE_VERSION_LOCK_KEY: ${{ needs.metadata.outputs.version_lock_key }} RELEASE_VERSION_LOCK_REQUIRED: "true" run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release publish-platform - name: Upload mac_arm64 publish manifest fallback if: ${{ inputs.publish && success() }} uses: actions/upload-artifact@v7 continue-on-error: true with: name: open-design-betas-mac-arm64-publish-manifest path: ${{ runner.temp }}/release-platform-manifests/mac_arm64.json if-no-files-found: warn build_win_x64: name: Build self-hosted beta win_x64 needs: metadata if: ${{ inputs.enable_win_x64 }} runs-on: [self-hosted, Windows, X64, nexu-win, release-beta] timeout-minutes: 30 env: RELEASE_COMMIT: ${{ needs.metadata.outputs.commit }} steps: - name: Checkout uses: actions/checkout@v6.0.2 with: clean: false fetch-depth: 1 lfs: false ref: ${{ needs.metadata.outputs.commit }} - name: Prepare self-hosted Windows toolchain shell: pwsh run: | & "C:\Users\runner\.cargo\bin\fnm.exe" exec --using=24 -- pnpm.cmd install --frozen-lockfile --prefer-offline - name: Probe Windows signing capability id: sign_probe shell: pwsh run: .\.github\scripts\release\probe-win-signing.ps1 -SignMode "${{ inputs.win_x64_sign_mode }}" - name: Build betas win_x64 shell: pwsh env: OD_BETA_WINDOWS_SIGNING_CERTIFICATE_FOUND: ${{ steps.sign_probe.outputs.certificate_found }} OD_BETA_WINDOWS_SIGNING_ENABLED: ${{ steps.sign_probe.outputs.enabled }} OD_BETA_WINDOWS_SIGNING_MODE: ${{ steps.sign_probe.outputs.mode }} OD_BETA_WINDOWS_SIGNING_PROBED: ${{ steps.sign_probe.outputs.probed }} OD_BETA_WINDOWS_SIGNING_REASON: ${{ steps.sign_probe.outputs.reason }} OD_BETA_WINDOWS_SIGNING_REQUESTED: ${{ steps.sign_probe.outputs.requested }} OD_BETA_WINDOWS_SIGNING_SIGNTOOL_FOUND: ${{ steps.sign_probe.outputs.signtool_found }} OD_BETA_WINDOWS_SIGNTOOL_PATH: ${{ steps.sign_probe.outputs.signtool_path }} OD_BETA_WINDOWS_SIGN_CERT_SHA1: ${{ steps.sign_probe.outputs.thumbprint }} OD_UPDATE_METADATA_URL: ${{ inputs.release_public_origin }}/betas/latest/metadata.json OD_PACKAGED_E2E_WIN_UPDATE_METADATA_URL: ${{ inputs.win_x64_update_metadata_url }} OD_PACKAGED_E2E_WIN_UPDATE_VERSION: ${{ inputs.win_x64_update_target_version }} RELEASE_CHANNEL: betas run: | & "C:\Users\runner\.cargo\bin\fnm.exe" exec --using=24 -- pwsh -NoProfile -File tools\release\scripts\build-platform.ps1 ` -ReleaseTarget win_x64 ` -ReleaseNamespace release-betas-win ` -ReleaseVersion "${{ needs.metadata.outputs.release_version }}" ` -SmokeMode "${{ inputs.win_x64_smoke_mode }}" ` -BuildTarget "${{ inputs.win_x64_target }}" ` -SignMode "${{ inputs.win_x64_sign_mode }}" ` -WorkRoot "C:\.tmp\runner\od-beta\win_x64" ` -ToolsPackDir "C:\.tmp\runner\od-beta\win_x64\tools-pack" ` -CacheDir "C:\.tmp\runner\od-beta\win_x64\tools-pack-cache" ` -BuildJsonPath "C:\.tmp\runner\od-beta\win_x64\build\build.json" ` -IndexPath "C:\.tmp\runner\od-beta\win_x64\build\index.json" ` -ReportRoot "C:\.tmp\runner\od-beta\win_x64\release-report\win_x64" ` -OutputsPath "C:\.tmp\runner\od-beta\win_x64\build\outputs.json" - name: Write win_x64 release report if: ${{ always() }} shell: pwsh env: BUILD_JSON_PATH: C:\.tmp\runner\od-beta\win_x64\build\build.json INDEX_PATH: C:\.tmp\runner\od-beta\win_x64\build\index.json RELEASE_BUILD_TARGET: ${{ inputs.win_x64_target }} RELEASE_CHANNEL: betas RELEASE_NAMESPACE: release-betas-win RELEASE_REPORT_DIR: C:\.tmp\runner\od-beta\win_x64\release-report\win_x64 RELEASE_REPORT_JSON_PATH: C:\.tmp\runner\od-beta\win_x64\release-report\win_x64\report.json RELEASE_REPORT_SUMMARY_PATH: C:\.tmp\runner\od-beta\win_x64\release-report\win_x64\summary.md RELEASE_SMOKE_MODE: ${{ inputs.win_x64_smoke_mode }} RELEASE_TARGET: win_x64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} REPORT_TITLE: self-hosted win_x64 betas build run: '& "C:\Users\runner\.cargo\bin\fnm.exe" exec --using=24 -- pnpm.cmd exec tools-release write-report' - name: Publish win_x64 report summary if: ${{ always() }} shell: pwsh run: Get-Content "C:\.tmp\runner\od-beta\win_x64\release-report\win_x64\summary.md" | Add-Content $env:GITHUB_STEP_SUMMARY - name: Prepare win_x64 assets if: ${{ inputs.publish }} shell: pwsh run: | tools\release\scripts\prepare-platform-assets.ps1 ` -ReleaseTarget win_x64 ` -ReleaseAssetsDir "C:\.tmp\runner\od-beta\win_x64\release-assets" ` -BuildJsonPath "C:\.tmp\runner\od-beta\win_x64\build\build.json" ` -ReleaseNamespace release-betas-win ` -ReleaseVersion "${{ needs.metadata.outputs.release_version }}" ` -ReleaseAssetSuffix "${{ inputs.win_x64_sign_mode == 'on' && '.signed' || '.unsigned' }}" ` -ReleaseChannel betas ` -ReleasePublicOrigin "${{ inputs.release_public_origin }}" ` -IncludeZip $${{ inputs.win_x64_target == 'all' || inputs.win_x64_target == 'zip' }} - name: Publish win_x64 platform if: ${{ inputs.publish }} env: RELEASE_ASSET_SUFFIX: ${{ inputs.win_x64_sign_mode == 'on' && '.signed' || '.unsigned' }} RELEASE_ASSETS_DIR: C:\.tmp\runner\od-beta\win_x64\release-assets RELEASE_CHANNEL: betas RELEASE_MANIFEST_DIR: C:\.tmp\runner\od-beta\win_x64\release-platform-manifests RELEASE_OUTPUTS_PATH: C:\.tmp\runner\od-beta\win_x64\release-platform-outputs\win_x64.json RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin }} RELEASE_REPORT_DIR: C:\.tmp\runner\od-beta\win_x64\release-report\win_x64 WIN_INCLUDE_ZIP: ${{ inputs.win_x64_target == 'all' || inputs.win_x64_target == 'zip' }} RELEASE_SIGNED: ${{ inputs.win_x64_sign_mode == 'on' && 'true' || 'false' }} RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_TARGET: win_x64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} RELEASE_VERSION_LOCK_KEY: ${{ needs.metadata.outputs.version_lock_key }} RELEASE_VERSION_LOCK_REQUIRED: "true" shell: pwsh run: '& "C:\Users\runner\.cargo\bin\fnm.exe" exec --using=24 -- pnpm.cmd exec tools-release publish-platform' - name: Upload win_x64 publish manifest fallback if: ${{ inputs.publish && success() }} uses: actions/upload-artifact@v7 continue-on-error: true with: name: open-design-betas-win-x64-publish-manifest path: C:\.tmp\runner\od-beta\win_x64\release-platform-manifests\win_x64.json if-no-files-found: warn publish: name: Publish betas metadata to Nexu S3 needs: - metadata - unsupported_mac_x64 - unsupported_linux_x64 - build_mac_arm64 - build_win_x64 if: >- ${{ always() && !cancelled() && inputs.publish && needs.metadata.result == 'success' && (inputs.enable_mac_arm64 || inputs.enable_win_x64) && !inputs.enable_mac_x64 && !inputs.enable_linux_x64 && (!inputs.enable_mac_arm64 || needs.build_mac_arm64.result == 'success') && (!inputs.enable_win_x64 || needs.build_win_x64.result == 'success') }} runs-on: [self-hosted, macOS, ARM64, nexu-mac, release-beta] timeout-minutes: 10 env: GITHUB_SHA: ${{ needs.metadata.outputs.commit }} RELEASE_COMMIT: ${{ needs.metadata.outputs.commit }} outputs: release_state: ${{ steps.outputs.outputs.release_state }} version_metadata_url: ${{ steps.outputs.outputs.version_metadata_url }} mac_arm64_url: ${{ steps.outputs.outputs.mac_arm64_dmg_url }} win_x64_url: ${{ steps.outputs.outputs.win_x64_installer_url }} mac_x64_url: ${{ steps.outputs.outputs.mac_x64_dmg_url }} linux_x64_url: ${{ steps.outputs.outputs.linux_x64_appImage_url }} steps: - name: Checkout release scripts uses: actions/checkout@v6.0.2 with: clean: true fetch-depth: 1 lfs: false path: _release-scripts ref: ${{ needs.metadata.outputs.commit }} - name: Install release metadata toolchain working-directory: _release-scripts run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm install --frozen-lockfile --prefer-offline - name: Download mac_arm64 publish manifest fallback if: ${{ inputs.enable_mac_arm64 && needs.build_mac_arm64.result == 'success' }} uses: actions/download-artifact@v8 continue-on-error: true with: name: open-design-betas-mac-arm64-publish-manifest path: ${{ runner.temp }}/release-platform-manifest-fallbacks/mac_arm64 - name: Download mac_arm64 platform manifest if: ${{ inputs.enable_mac_arm64 && needs.build_mac_arm64.result == 'success' }} env: RELEASE_ASSET_SUFFIX: ${{ (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && '.signed' || '.unsigned' }} RELEASE_CHANNEL: betas RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_TARGET: mac_arm64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} working-directory: _release-scripts run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release download-platform-manifest - name: Download win_x64 publish manifest fallback if: ${{ inputs.enable_win_x64 && needs.build_win_x64.result == 'success' }} uses: actions/download-artifact@v8 continue-on-error: true with: name: open-design-betas-win-x64-publish-manifest path: ${{ runner.temp }}/release-platform-manifest-fallbacks/win_x64 - name: Download win_x64 platform manifest if: ${{ inputs.enable_win_x64 && needs.build_win_x64.result == 'success' }} env: RELEASE_ASSET_SUFFIX: ${{ inputs.win_x64_sign_mode == 'on' && '.signed' || '.unsigned' }} RELEASE_CHANNEL: betas RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_TARGET: win_x64 RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} working-directory: _release-scripts run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release download-platform-manifest - name: Publish betas metadata env: BASE_VERSION: ${{ needs.metadata.outputs.base_version }} ENABLE_LINUX_X64: "false" ENABLE_MAC_ARM64: ${{ inputs.enable_mac_arm64 }} ENABLE_MAC_X64: "false" ENABLE_WIN_X64: ${{ inputs.enable_win_x64 }} LINUX_X64_RESULT: skipped MAC_ARM64_RESULT: ${{ needs.build_mac_arm64.result }} MAC_X64_RESULT: skipped RELEASE_LATEST_CAS_REQUIRED: "true" RELEASE_ASSET_SUFFIX: auto RELEASE_CHANNEL: betas RELEASE_MANIFEST_DIR: ${{ runner.temp }}/release-platform-manifests RELEASE_METADATA_DIR: ${{ runner.temp }}/release-metadata RELEASE_OUTPUTS_PATH: ${{ runner.temp }}/release-metadata/outputs.json RELEASE_PUBLIC_ORIGIN: ${{ inputs.release_public_origin }} RELEASE_SIGNED: ${{ inputs.enable_mac_arm64 && (inputs.mac_arm64_delivery_mode == 'internal-updater' || inputs.mac_arm64_sign_mode != 'no') && 'true' || 'false' }} RELEASE_STORAGE_ACCESS_KEY_ID: ${{ secrets.NEXU_S3_ACCESS_KEY_ID }} RELEASE_STORAGE_BUCKET: ${{ secrets.NEXU_S3_BUCKET }} RELEASE_STORAGE_ENDPOINT: ${{ secrets.NEXU_S3_ENDPOINT }} RELEASE_STORAGE_REGION: ${{ secrets.NEXU_S3_REGION }} RELEASE_STORAGE_SECRET_ACCESS_KEY: ${{ secrets.NEXU_S3_SECRET_ACCESS_KEY }} RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} RELEASE_VERSION_LOCK_KEY: ${{ needs.metadata.outputs.version_lock_key }} RELEASE_VERSION_LOCK_REQUIRED: "true" STATE_SOURCE: ${{ needs.metadata.outputs.state_source }} WIN_X64_RESULT: ${{ needs.build_win_x64.result }} working-directory: _release-scripts run: | set -euo pipefail if ! command -v rehash >/dev/null 2>&1; then rehash() { hash -r; } fi # shellcheck disable=SC1090 source "$OPEN_DESIGN_RELEASE_PROFILE" fnm exec --using=24 -- pnpm exec tools-release publish-metadata - name: Read metadata outputs id: outputs uses: actions/github-script@v8 with: script: | const fs = require("fs"); const outputs = JSON.parse(fs.readFileSync(`${process.env.RUNNER_TEMP}/release-metadata/outputs.json`, "utf8")); for (const [key, value] of Object.entries(outputs)) core.setOutput(key, String(value)); - name: Write betas metadata summary env: RELEASE_STATE: ${{ steps.outputs.outputs.release_state }} RELEASE_METADATA_URL: ${{ steps.outputs.outputs.version_metadata_url }} RELEASE_SUMMARY_PATH: ${{ runner.temp }}/release-metadata/summary.md RELEASE_VERSION: ${{ needs.metadata.outputs.release_version }} working-directory: _release-scripts run: | set -euo pipefail { echo "## Betas release metadata" echo echo "- version: \`$RELEASE_VERSION\`" echo "- state: \`$RELEASE_STATE\`" echo "- metadata: $RELEASE_METADATA_URL" echo echo "release-beta-s publishes to an internal S3 namespace; public metadata fetch verification is intentionally skipped." } > "$RELEASE_SUMMARY_PATH" - name: Publish summary run: cat "${{ runner.temp }}/release-metadata/summary.md" >> "$GITHUB_STEP_SUMMARY"