Skip to content

Commit 646ca0d

Browse files
authored
chore: split queue and build timeouts, reattach on retry (#8780)
* ci(cloudbuild): split queue and build timeouts, reattach on retry Unity Cloud Build concurrency settings now leave builds in the queue for much longer before a builder picks them up. The previous single GLOBAL_TIMEOUT counted queue + active build time together, so a long queue could kill an otherwise healthy build, and nick-fields/retry created a brand-new build that went to the back of the queue. Changes: - Replace GLOBAL_TIMEOUT with QUEUE_TIMEOUT (4h) and BUILD_TIMEOUT (3h). The build clock resets on the queue -> started transition so a long queue never eats into the active build window. - Exit 99 on either timeout so nick-fields/retry kicks in (the previous sys.exit(1) was not retryable). - On retry, reattach to the persisted build_info.json build if it is still in queue/active, instead of POSTing a fresh build. - Adaptive polling: bump cadence to 120s after the status has been unchanged for 10 minutes, to reduce API noise while queued. - Log queuedReason on each status change and append a phase-breakdown table to \$GITHUB_STEP_SUMMARY for visibility on queue pressure. - Make cancel_build idempotent so the post-failure cancel step does not fail if Unity already finalised the build. - Raise the wrapping nick-fields/retry timeout_minutes to 450 and the job timeout-minutes to 510 so the inner Python budgets are always the ones that fire first. - Cancel Unity build also on step failure() so an outer step timeout no longer leaves a Unity-side build holding a slot. * chore: preserve queue position on retry and trim verbose comments Don't cancel on inner QUEUE_TIMEOUT — exit 99 to yield the runner while the build keeps its Unity Cloud queue slot, so the next nick-fields/retry attempt reattaches via try_resume_build instead of POSTing a fresh build that goes to the back of the queue. BUILD_TIMEOUT still cancels. Seed build_start from Unity's totalTimeInSeconds on reattach so the 3h BUILD_TIMEOUT measures real wall-clock rather than restarting per attempt. Add the missing sys.exit(0) after the --cancel branch so the cancel step no longer falls through into the polling loop. Trim per-line env comments and section banners from build.py and build-unitycloud.yml per the project's "no comments by default" rule. * chore: clean up build_info.json on terminal paths Explicitly delete build_info.json when: - run_poll_loop returns a terminal status (success/failure/canceled/unknown) - BUILD_TIMEOUT cancels the build before exit 99 - --cancel mode finishes cancelling Only the queue_timeout exit keeps the file, so the next retry attempt can reattach to the still-queued build. Also fix utils.delete_build_info to actually be idempotent: it was printing the "ignoring delete" message and then still calling os.remove on the missing file, which raises FileNotFoundError. Per-attempt QUEUE_TIMEOUT (effective global cap = QUEUE_TIMEOUT * max_attempts) is left as-is — that's the retry-as-patience-extension design intent.
1 parent 20e5256 commit 646ca0d

3 files changed

Lines changed: 266 additions & 72 deletions

File tree

.github/workflows/build-unitycloud.yml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ jobs:
412412
runs-on: ubuntu-latest
413413
needs: prebuild
414414
if: needs.prebuild.outputs.should_build == 'true'
415-
timeout-minutes: 360
415+
# Safety ceiling around the 450m retry budget + surrounding steps.
416+
timeout-minutes: 510
416417
strategy:
417418
fail-fast: false
418419
matrix:
@@ -437,21 +438,25 @@ jobs:
437438
- name: Execute Unity Cloud build
438439
uses: nick-fields/retry@v3
439440
with:
440-
timeout_minutes: 180 # matches your GLOBAL_TIMEOUT = 10800s
441+
# Wraps QUEUE_TIMEOUT (240m) + BUILD_TIMEOUT (180m) + buffer.
442+
timeout_minutes: 450
441443
max_attempts: 2
442444
retry_on_exit_code: 99
443445
retry_wait_seconds: 30
444446
on_retry_command: |
445-
echo "::warning::🔁 Unity Cloud Build retry triggered at $(date '+%Y-%m-%d %H:%M:%S')"
447+
echo "::warning::🔁 Unity Cloud Build retry triggered at $(date '+%Y-%m-%d %H:%M:%S'). The next attempt will reattach to the persisted build if it is still in flight."
446448
command: |
447449
echo "🔧 Starting Unity Cloud Build attempt at $(date '+%Y-%m-%d %H:%M:%S')"
448450
python -u scripts/cloudbuild/build.py
449451
env:
450452
API_KEY: ${{ secrets.UNITY_CLOUD_API_KEY }}
451453
ORG_ID: ${{ secrets.UNITY_CLOUD_ORG_ID }}
452454
PROJECT_ID: ${{ secrets.UNITY_CLOUD_PROJECT_ID }}
453-
POLL_TIME: 60 # Set the polling time in seconds
454-
GLOBAL_TIMEOUT: 10800 # Set the global timeout in seconds (e.g., 3 hours)
455+
POLL_TIME: 60
456+
QUEUE_POLL_TIME: 120
457+
STALE_POLL_THRESHOLD: 600
458+
QUEUE_TIMEOUT: 14400
459+
BUILD_TIMEOUT: 10800
455460
TARGET: t_${{ matrix.target }}
456461
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
457462
COMMIT_SHA: ${{ needs.prebuild.outputs.commit_sha }}
@@ -793,12 +798,12 @@ jobs:
793798
path: shader_compilation_report.log
794799
if-no-files-found: warn
795800

796-
# Will run on cancel or timeout only
801+
# Also runs on failure() so an outer-step timeout doesn't leave a Unity-side build holding a slot.
797802
- name: Cancel Unity Cloud build
798-
if: ${{ cancelled() }}
803+
if: ${{ cancelled() || failure() }}
799804
env:
800805
API_KEY: ${{ secrets.UNITY_CLOUD_API_KEY }}
801806
ORG_ID: ${{ secrets.UNITY_CLOUD_ORG_ID }}
802807
PROJECT_ID: ${{ secrets.UNITY_CLOUD_PROJECT_ID }}
803-
run: python -u scripts/cloudbuild/build.py --cancel
808+
run: python -u scripts/cloudbuild/build.py --cancel || true
804809
# Test change

0 commit comments

Comments
 (0)