mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 10:08:13 +00:00
Hosted macos-15 fails afterPack's packaged x64 terminal host boot check (hourly run 40608643418: timed out waiting for the PTY), so no latest-mac.yml is published. Windows, template qualification and routing jobs stay on hosted runners. Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
469 lines
22 KiB
YAML
469 lines
22 KiB
YAML
name: Daily macOS Dev Build
|
||
|
||
# Publish daily main builds to orca-daily, separate from hourly and stable/RC feeds. Sign/notarize for update-preserved macOS TCC grants; PR/release pipelines own blocking validation, with E2E detached after publish. Cron 18:15 UTC means 10:15 PST/11:15 PDT, offset from hourly. Use the shared hourly App with write access to orca-daily (setup-hourly-release-token.sh/setup-daily-release-repo.sh). Mint tokens again after build and upload because 2×45min retry can exceed their 1h life. Keep releases draft until manifests verify; drafts retain build numbers.
|
||
|
||
on:
|
||
schedule:
|
||
# Once a day, late morning Pacific. Single cron — no DST twin, no clock gate.
|
||
- cron: '15 18 * * *'
|
||
workflow_dispatch:
|
||
inputs:
|
||
force:
|
||
description: Build even if main has not moved since the last daily
|
||
required: false
|
||
default: false
|
||
type: boolean
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
concurrency:
|
||
group: daily-mac-build
|
||
cancel-in-progress: false
|
||
|
||
env:
|
||
DAILY_REPO: stablyai/orca-daily
|
||
# Keep ~30 days so a regression can be bisected without holding a full year.
|
||
DAILY_RETAIN_COUNT: 30
|
||
|
||
jobs:
|
||
# Why: the app and the orcad template it ships must come from one commit, so resolve main once.
|
||
resolve-main:
|
||
if: github.repository == 'stablyai/orca'
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 5
|
||
outputs:
|
||
head_sha: ${{ steps.resolve.outputs.head_sha }}
|
||
steps:
|
||
- name: Resolve main
|
||
id: resolve
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
run: |
|
||
set -euo pipefail
|
||
head_sha="$(gh api "repos/$GITHUB_REPOSITORY/commits/main" --jq .sha)"
|
||
[[ "$head_sha" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Could not resolve main"; exit 1; }
|
||
echo "head_sha=$head_sha" >>"$GITHUB_OUTPUT"
|
||
|
||
# As release-cut does: every SSH host runs orcad, deployed from the template this build ships.
|
||
orcad-template:
|
||
needs: resolve-main
|
||
permissions:
|
||
contents: read
|
||
actions: read
|
||
uses: ./.github/workflows/node-server-tests.yml
|
||
with:
|
||
ref: ${{ needs.resolve-main.outputs.head_sha }}
|
||
build_template: true
|
||
fast_runners: false
|
||
|
||
build-daily-mac:
|
||
needs:
|
||
- resolve-main
|
||
- orcad-template
|
||
if: github.repository == 'stablyai/orca'
|
||
outputs:
|
||
tag: ${{ steps.release.outputs.tag }}
|
||
version: ${{ steps.daily.outputs.version }}
|
||
head_sha: ${{ steps.freshness.outputs.head_sha }}
|
||
published: ${{ steps.publish_live.outcome == 'success' && 'true' || 'false' }}
|
||
# Hosted macos-15 cannot boot the packaged x64 terminal host that afterPack verifies.
|
||
runs-on: blacksmith-6vcpu-macos-15
|
||
# Allow 150min for install 3×10 + publish 2×45 + ~25 setup/build/verify, so outer timeout cannot strand cleanup mid-retry.
|
||
timeout-minutes: 150
|
||
env:
|
||
NODE_OPTIONS: --max-old-space-size=4096
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v6
|
||
with:
|
||
ref: ${{ needs.resolve-main.outputs.head_sha }}
|
||
# Version helpers only read HEAD; published versions come from git tags.
|
||
fetch-depth: 1
|
||
# Read this repo without persisted credentials; write orca-daily through env-passed App token (zizmor: artipacked).
|
||
persist-credentials: false
|
||
|
||
- name: Mint daily repo token
|
||
id: app_token
|
||
uses: actions/create-github-app-token@v2
|
||
with:
|
||
app-id: ${{ secrets.HOURLY_RELEASE_APP_ID }}
|
||
private-key: ${{ secrets.HOURLY_RELEASE_APP_PRIVATE_KEY }}
|
||
owner: stablyai
|
||
repositories: orca-daily
|
||
|
||
# Skip unchanged main to avoid duplicate builds/tags and runner cost.
|
||
- name: Check whether main moved since the last daily
|
||
id: freshness
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token.outputs.token }}
|
||
FORCED: ${{ github.event_name == 'workflow_dispatch' && inputs.force }}
|
||
run: |
|
||
set -euo pipefail
|
||
head_sha="$(git rev-parse HEAD)"
|
||
echo "head_sha=$head_sha" >>"$GITHUB_OUTPUT"
|
||
if [[ "$FORCED" == "true" ]]; then
|
||
echo "should_build=true" >>"$GITHUB_OUTPUT"
|
||
echo "Forced dispatch; building $head_sha."
|
||
exit 0
|
||
fi
|
||
# Drafts never shipped; exclude them when comparing the previous daily’s source commit.
|
||
last_body="$(gh release list --repo "$DAILY_REPO" --limit 20 --json tagName,isDraft \
|
||
--jq 'map(select(.isDraft | not)) | .[0].tagName // empty' 2>/dev/null || true)"
|
||
if [[ -z "$last_body" ]]; then
|
||
echo "should_build=true" >>"$GITHUB_OUTPUT"
|
||
echo "No prior daily release found; building $head_sha."
|
||
exit 0
|
||
fi
|
||
last_sha="$(gh release view "$last_body" --repo "$DAILY_REPO" --json body \
|
||
--jq '.body | capture("commit `(?<sha>[0-9a-f]{7,40})`") | .sha' 2>/dev/null || true)"
|
||
if [[ -n "$last_sha" && "$head_sha" == "$last_sha"* ]]; then
|
||
echo "should_build=false" >>"$GITHUB_OUTPUT"
|
||
echo "main is unchanged since $last_body ($last_sha); skipping."
|
||
else
|
||
echo "should_build=true" >>"$GITHUB_OUTPUT"
|
||
echo "main moved to $head_sha (last daily built $last_sha); building."
|
||
fi
|
||
|
||
- name: Setup pnpm
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: pnpm/setup@v2
|
||
with:
|
||
install: false
|
||
|
||
- name: Setup Node.js
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/setup-node@v6
|
||
with:
|
||
node-version-file: package.json
|
||
check-latest: true
|
||
cache: pnpm
|
||
cache-dependency-path: |
|
||
pnpm-lock.yaml
|
||
mobile/pnpm-lock.yaml
|
||
|
||
# Cache bundled host Node by exact pin without restore keys.
|
||
- name: Locate the pinned Node runtime cache
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
shell: bash
|
||
run: echo "ORCA_NODE_RUNTIME_CACHE_DIR=$HOME/Library/Caches/orca-node-runtime" >>"$GITHUB_ENV"
|
||
|
||
- name: Cache the pinned Node runtime
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/cache@v5
|
||
with:
|
||
path: ~/Library/Caches/orca-node-runtime
|
||
key: orca-node-runtime-mac-${{ hashFiles('src/shared/node-runtime-pin.ts') }}
|
||
|
||
- name: Cache electron-builder downloads
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/cache@v5
|
||
with:
|
||
path: |
|
||
~/Library/Caches/electron
|
||
~/Library/Caches/electron-builder
|
||
key: electron-builder-mac-${{ hashFiles('pnpm-lock.yaml') }}
|
||
restore-keys: |
|
||
electron-builder-mac-
|
||
|
||
# Install x64 and arm64 optional natives for both packaged macOS targets.
|
||
- name: Install dependencies
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: nick-fields/retry@v4
|
||
with:
|
||
timeout_minutes: 10
|
||
max_attempts: 3
|
||
retry_wait_seconds: 30
|
||
command: pnpm install --frozen-lockfile --cpu=current,x64,arm64
|
||
|
||
# Build required out/mobile-web using mobile’s React Native/Expo install.
|
||
- uses: ./.github/actions/install-mobile-dependencies
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
|
||
# Why: signing is what makes a daily installable over an existing Orca, so
|
||
# a missing cert must fail here rather than after a 20-minute build.
|
||
- name: Verify macOS signing environment
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
run: node config/scripts/verify-macos-release-env.mjs
|
||
env:
|
||
CSC_LINK: ${{ secrets.MAC_CERTS }}
|
||
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }}
|
||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||
|
||
- name: Compute daily version
|
||
id: daily
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token.outputs.token }}
|
||
MAIN_REPO_TOKEN: ${{ github.token }}
|
||
run: |
|
||
set -euo pipefail
|
||
# The script continues numbering for its resolved base version; stranded drafts still reserve numbers,
|
||
# although freshness checks exclude them because they never shipped.
|
||
names="$(gh release list --repo "$DAILY_REPO" --limit 200 --json name \
|
||
--jq '.[].name // empty')"
|
||
# Tags survive release deletion, preventing updater version regression. Use a separate token because
|
||
# GH_TOKEN’s App grant is scoped to the channel repo; lookup failure falls back to package.json.
|
||
main_tags="$(GH_TOKEN="$MAIN_REPO_TOKEN" gh api \
|
||
"repos/$GITHUB_REPOSITORY/git/matching-refs/tags/v" \
|
||
--jq '.[].ref | sub("^refs/tags/"; "")' || true)"
|
||
# Already-shipped channel tags are a second floor so unpublishing a
|
||
# buggy main release cannot drag this series below a daily already out.
|
||
channel_tags="$(gh release list --repo "$DAILY_REPO" --limit 200 --json tagName \
|
||
--jq '.[].tagName' || true)"
|
||
published="$main_tags"$'\n'"$channel_tags"
|
||
echo "Published version sources: $(grep -c . <<<"$main_tags" || true) main tags, $(grep -c . <<<"$channel_tags" || true) channel tags"
|
||
ORCA_PUBLISHED_VERSIONS="$published" ORCA_DAILY_RELEASE_NAMES="$names" \
|
||
node config/scripts/daily-build-version.mjs \
|
||
>"$RUNNER_TEMP/daily-identity.txt"
|
||
grep -E '^(version|build_number)=' "$RUNNER_TEMP/daily-identity.txt"
|
||
# Dispatch YAML can be newer than the pinned source’s version script; reject missing output before publishing an untitled release.
|
||
if ! grep -q '^name=' "$RUNNER_TEMP/daily-identity.txt"; then
|
||
echo "::error::daily-build-version.mjs emitted no release name; this workflow and main's copy of the script are out of sync."
|
||
exit 1
|
||
fi
|
||
cat "$RUNNER_TEMP/daily-identity.txt" >>"$GITHUB_OUTPUT"
|
||
|
||
- name: Build app
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
run: pnpm build:release
|
||
env:
|
||
NODE_OPTIONS: --max-old-space-size=4096
|
||
# Leave dev identity unset so official-only stable/rc telemetry stays silent.
|
||
ORCA_DIAGNOSTICS_TOKEN_URL: https://www.onorca.dev/diagnostics/token
|
||
|
||
# After the app build so nothing that cleans out/ can drop it; electron-builder ships it.
|
||
- name: Download the orcad deployment template
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/download-artifact@v8
|
||
with:
|
||
name: orcad-template
|
||
path: out/orcad-template
|
||
|
||
# Refresh the one-hour token after read-only install/build, before long publish/notary work.
|
||
- name: Re-mint daily repo token for publish
|
||
id: app_token_publish
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/create-github-app-token@v2
|
||
with:
|
||
app-id: ${{ secrets.HOURLY_RELEASE_APP_ID }}
|
||
private-key: ${{ secrets.HOURLY_RELEASE_APP_PRIVATE_KEY }}
|
||
owner: stablyai
|
||
repositories: orca-daily
|
||
|
||
- name: Create daily release
|
||
id: release
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token_publish.outputs.token }}
|
||
TAG: v${{ steps.daily.outputs.version }}
|
||
NAME: ${{ steps.daily.outputs.name }}
|
||
SHA: ${{ steps.freshness.outputs.head_sha }}
|
||
run: |
|
||
set -euo pipefail
|
||
# Freshness parses the 12-character source SHA from the body even though titles show seven.
|
||
short_sha="${SHA:0:12}"
|
||
# Write one body file for creation and reassertion; freshness parsing requires exact agreement.
|
||
notes_file="$RUNNER_TEMP/daily-release-notes.md"
|
||
cat >"$notes_file" <<EOF
|
||
Automated daily macOS and Windows dev build from commit \`$short_sha\`.
|
||
|
||
Built from [\`stablyai/orca@$short_sha\`](https://github.com/stablyai/orca/commit/$SHA).
|
||
|
||
**Unvetted.** No tests ran. The macOS build is signed and notarized like a
|
||
release, so it installs through Orca's in-app updater and opens from a manual
|
||
download without a Gatekeeper prompt — but nothing here has been reviewed.
|
||
|
||
**Windows builds are unsigned.** They install and update normally once you
|
||
are on one, but a signed Stable or RC build cannot install one through the
|
||
in-app updater — download \`orca-windows-setup.exe\` below and run it once
|
||
(SmartScreen will warn about an unknown publisher). Every later switch,
|
||
including back to Stable, works in-app from there.
|
||
EOF
|
||
# Precreate a known tag as draft so builder cannot infer it from package.json.
|
||
# Keep incomplete assets invisible until manifest verification, even if timeout kills the job without cleanup.
|
||
gh release create "$TAG" \
|
||
--repo "$DAILY_REPO" \
|
||
--title "$NAME" \
|
||
--draft \
|
||
--notes-file "$notes_file"
|
||
echo "tag=$TAG" >>"$GITHUB_OUTPUT"
|
||
echo "notes_file=$notes_file" >>"$GITHUB_OUTPUT"
|
||
|
||
- name: Publish daily macOS artifacts
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
uses: nick-fields/retry@v4
|
||
with:
|
||
# Allow two 45min pack/notarize/upload attempts; a third costs more runner time than a missed daily.
|
||
timeout_minutes: 45
|
||
max_attempts: 2
|
||
retry_wait_seconds: 30
|
||
command: node --disable-warning=MODULE_TYPELESS_PACKAGE_JSON config/scripts/pinned-node-downloads.mjs darwin-arm64 darwin-x64 && node config/scripts/ensure-native-runtime.mjs --runtime=electron && if [ -f config/scripts/build-mac-notarization-overlap.mjs ]; then ORCA_MAC_DAILY=1 node config/scripts/build-mac-notarization-overlap.mjs --publish always; else ORCA_MAC_DAILY=1 pnpm exec electron-builder --config config/electron-builder.config.cjs --mac --publish always; fi
|
||
env:
|
||
# Give the publisher App write access to its configured orca-daily target.
|
||
GH_TOKEN: ${{ steps.app_token_publish.outputs.token }}
|
||
ORCA_DAILY_BUILD_VERSION: ${{ steps.daily.outputs.version }}
|
||
ORCA_BUILD_COMMIT: ${{ steps.daily.outputs.commit }}
|
||
# beforePack and afterPack fail the package when the template is absent.
|
||
ORCA_REQUIRE_ORCAD_TEMPLATE: '1'
|
||
CSC_LINK: ${{ secrets.MAC_CERTS }}
|
||
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }}
|
||
# Require Apple id/app-specific password/team for notary authentication, separate from signing cert.
|
||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||
|
||
# Always refresh after upload: 2×45min can outlive the earlier token, including failed/cancelled uploads needing draft cleanup.
|
||
- name: Re-mint daily repo token for verify and cleanup
|
||
id: app_token_final
|
||
if: always() && steps.freshness.outputs.should_build == 'true'
|
||
uses: actions/create-github-app-token@v2
|
||
with:
|
||
app-id: ${{ secrets.HOURLY_RELEASE_APP_ID }}
|
||
private-key: ${{ secrets.HOURLY_RELEASE_APP_PRIVATE_KEY }}
|
||
owner: stablyai
|
||
repositories: orca-daily
|
||
|
||
# Verify latest-mac.yml before exposing its release to prevent picker downloads returning 404.
|
||
- name: Verify update manifest published
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token_final.outputs.token }}
|
||
TAG: ${{ steps.release.outputs.tag }}
|
||
run: |
|
||
set -euo pipefail
|
||
assets="$(gh release view "$TAG" --repo "$DAILY_REPO" --json assets --jq '.assets[].name')"
|
||
echo "Published assets:"
|
||
echo "$assets"
|
||
# Drafts are already invisible; let failure cleanup delete them so set -e cannot mask this explicit failure.
|
||
for required in latest-mac.yml; do
|
||
if ! grep -qx "$required" <<<"$assets"; then
|
||
echo "::error::Daily draft $TAG is missing $required; the updater could not install it."
|
||
exit 1
|
||
fi
|
||
done
|
||
if ! grep -q '\.zip$' <<<"$assets"; then
|
||
echo "::error::Daily draft $TAG has no ZIP artifact for the updater to download."
|
||
exit 1
|
||
fi
|
||
|
||
# Publish only after manifest validation so the picker cannot offer incomplete assets.
|
||
- name: Publish the verified release
|
||
id: publish_live
|
||
if: steps.freshness.outputs.should_build == 'true'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token_final.outputs.token }}
|
||
TAG: ${{ steps.release.outputs.tag }}
|
||
NAME: ${{ steps.daily.outputs.name }}
|
||
NOTES_FILE: ${{ steps.release.outputs.notes_file }}
|
||
run: |
|
||
set -euo pipefail
|
||
# Builder may rewrite title/body on upload; reassert both so the picker name and next run’s source-SHA freshness check stay correct.
|
||
gh release edit "$TAG" --repo "$DAILY_REPO" --draft=false --prerelease \
|
||
--title "$NAME" --notes-file "$NOTES_FILE"
|
||
echo "Published $TAG as \"$NAME\""
|
||
|
||
# Remove failed/cancelled stranded drafts, never releases already published by publish_live, including after prune failure. Outer timeout skips cleanup, so retain draft status until verified.
|
||
- name: Discard the draft release on failure
|
||
if: >-
|
||
(failure() || cancelled()) && steps.release.outputs.tag != '' &&
|
||
steps.publish_live.outcome != 'success'
|
||
shell: bash
|
||
env:
|
||
# If token refresh fails, let cleanup try the older token while it may still be valid.
|
||
GH_TOKEN: ${{ steps.app_token_final.outputs.token || steps.app_token_publish.outputs.token }}
|
||
TAG: ${{ steps.release.outputs.tag }}
|
||
run: |
|
||
set -uo pipefail
|
||
# No --cleanup-tag: an unpublished draft never created a git tag.
|
||
echo "Run failed before publish; discarding draft $TAG"
|
||
gh release delete "$TAG" --repo "$DAILY_REPO" --yes ||
|
||
echo "::warning::Could not discard draft $TAG; remove it manually."
|
||
|
||
- name: Prune old daily releases
|
||
# Prune only after publication; failed runs leave draft disposal to cleanup.
|
||
if: steps.publish_live.outcome == 'success'
|
||
shell: bash
|
||
env:
|
||
GH_TOKEN: ${{ steps.app_token_final.outputs.token }}
|
||
# Never prune this run’s just-published tag at the retention cap.
|
||
TAG: ${{ steps.release.outputs.tag }}
|
||
run: |
|
||
set -euo pipefail
|
||
# Delete pruned tags too; exclude drafts owned by failure cleanup. Rank by publishedAt/tagName:
|
||
# createdAt ties (bulk import/recreation) can evict the just-published release. Partition $TAG to
|
||
# the front before slicing so it owns exactly one retained seat without under-pruning or keeping retain+1.
|
||
jq_filter='map(select(.isDraft | not)) | sort_by(.publishedAt // "", .tagName) | reverse'
|
||
if [[ -n "${TAG:-}" ]]; then
|
||
jq_filter+=" | (map(select(.tagName == \"${TAG//\"/\\\"}\")) + map(select(.tagName != \"${TAG//\"/\\\"}\")))"
|
||
fi
|
||
jq_filter+=" | .[${DAILY_RETAIN_COUNT}:] | .[].tagName"
|
||
stale="$(gh release list --repo "$DAILY_REPO" --limit 200 --json tagName,publishedAt,isDraft \
|
||
--jq "$jq_filter")"
|
||
if [[ -z "$stale" ]]; then
|
||
echo "Nothing to prune; at or under $DAILY_RETAIN_COUNT retained builds."
|
||
exit 0
|
||
fi
|
||
while read -r tag; do
|
||
[[ -n "$tag" ]] || continue
|
||
# Belt-and-suspenders: partition above should already exclude $TAG.
|
||
if [[ -n "${TAG:-}" && "$tag" == "$TAG" ]]; then
|
||
echo "::warning::Prune list still included just-published $tag after protect; skipping delete."
|
||
continue
|
||
fi
|
||
echo "Pruning $tag"
|
||
gh release delete "$tag" --repo "$DAILY_REPO" --yes --cleanup-tag || \
|
||
echo "::warning::Could not prune $tag"
|
||
done <<<"$stale"
|
||
|
||
# Dispatch E2E separately so main’s red full suite cannot fail an already-published daily. Use main’s workflow plus exact built SHA because daily tags live in another repo.
|
||
post-daily-e2e:
|
||
needs: build-daily-mac
|
||
if: ${{ needs.build-daily-mac.outputs.published == 'true' && needs.build-daily-mac.outputs.head_sha != '' }}
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
actions: write
|
||
steps:
|
||
- name: Dispatch cut-scoped E2E
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
SHA: ${{ needs.build-daily-mac.outputs.head_sha }}
|
||
run: |
|
||
for attempt in 1 2 3; do
|
||
if gh workflow run e2e.yml \
|
||
--repo "$GITHUB_REPOSITORY" \
|
||
--ref main \
|
||
--raw-field "ref=$SHA"; then
|
||
echo "Dispatched post-daily E2E for $SHA."
|
||
exit 0
|
||
fi
|
||
[[ "$attempt" -eq 3 ]] || sleep "$((attempt * 5))"
|
||
done
|
||
echo "::warning::Failed to dispatch post-daily E2E for $SHA after 3 attempts."
|
||
|
||
# Wait for mac release identity before Windows uploads; local ./ workflow follows the dispatch ref consistently.
|
||
build-daily-win:
|
||
needs: build-daily-mac
|
||
# Start Windows publication only after the mac release is live; its workflow refuses to create a missing release.
|
||
if: needs.build-daily-mac.outputs.published == 'true'
|
||
permissions:
|
||
contents: read
|
||
actions: read
|
||
uses: ./.github/workflows/dev-channel-win-build.yml
|
||
secrets: inherit
|
||
with:
|
||
channel: daily
|
||
tag: ${{ needs.build-daily-mac.outputs.tag }}
|
||
ref: ${{ needs.build-daily-mac.outputs.head_sha }}
|
||
version: ${{ needs.build-daily-mac.outputs.version }}
|
||
orcad_template: true
|
||
fast_release: false
|