88 - synchronize
99 - ready_for_review
1010 - labeled
11+ - unlabeled
1112 merge_group : {}
1213 push :
1314 branches :
@@ -152,9 +153,11 @@ concurrency:
152153 cancel-in-progress : >-
153154 ${{
154155 github.event_name != 'pull_request' ||
155- github.event.action != 'labeled' ||
156+ ( github.event.action != 'labeled' && github.event.action != 'unlabeled') ||
156157 github.event.label.name == 'force-build' ||
157- github.event.label.name == 'clean-build'
158+ github.event.label.name == 'clean-build' ||
159+ github.event.label.name == 'windows-only' ||
160+ github.event.label.name == 'macos-only'
158161 }}
159162
160163jobs :
@@ -183,8 +186,13 @@ jobs:
183186 ) ||
184187 github.event.action == 'ready_for_review' ||
185188 (
186- github.event.action == 'labeled' &&
187- (github.event.label.name == 'force-build' || github.event.label.name == 'clean-build')
189+ (github.event.action == 'labeled' || github.event.action == 'unlabeled') &&
190+ (
191+ github.event.label.name == 'force-build' ||
192+ github.event.label.name == 'clean-build' ||
193+ github.event.label.name == 'windows-only' ||
194+ github.event.label.name == 'macos-only'
195+ )
188196 )
189197 )
190198 )
@@ -200,6 +208,7 @@ jobs:
200208 clean_build : ${{ steps.set_defaults.outputs.clean_build }}
201209 cache_strategy : ${{ steps.set_defaults.outputs.cache_strategy }}
202210 install_source : ${{ steps.set_defaults.outputs.install_source }}
211+ targets : ${{ steps.get_targets.outputs.targets }}
203212 steps :
204213 - name : Checkout code
205214 uses : actions/checkout@v4
@@ -407,6 +416,37 @@ jobs:
407416 IFS=,
408417 echo "options=${options[*]}" | tee -a "$GITHUB_OUTPUT"
409418
419+ - name : Determine build targets
420+ if : steps.decide.outputs.should_build == 'true'
421+ id : get_targets
422+ shell : bash
423+ run : |
424+ set -euo pipefail
425+
426+ labels="${{ join(github.event.pull_request.labels.*.name, ' ') }}"
427+ echo "Labels: '$labels'"
428+
429+ has_windows_only=false
430+ has_macos_only=false
431+ if echo "$labels" | grep -qw 'windows-only'; then has_windows_only=true; fi
432+ if echo "$labels" | grep -qw 'macos-only'; then has_macos_only=true; fi
433+
434+ if [ "$has_windows_only" = "true" ] && [ "$has_macos_only" = "true" ]; then
435+ echo "::error::Both 'windows-only' and 'macos-only' labels are applied. Remove one — they are mutually exclusive."
436+ exit 1
437+ fi
438+
439+ if [ "$has_windows_only" = "true" ]; then
440+ targets='["windows64"]'
441+ elif [ "$has_macos_only" = "true" ]; then
442+ targets='["macos"]'
443+ else
444+ targets='["windows64","macos"]'
445+ fi
446+
447+ echo "Targets: $targets"
448+ echo "targets=$targets" >> "$GITHUB_OUTPUT"
449+
410450 build :
411451 name : Build
412452 runs-on : ubuntu-latest
@@ -416,7 +456,7 @@ jobs:
416456 strategy :
417457 fail-fast : false
418458 matrix :
419- target : ['windows64', 'macos']
459+ target : ${{ fromJSON(needs.prebuild.outputs.targets) }}
420460 steps :
421461 - name : Checkout code
422462 uses : actions/checkout@v4
@@ -801,4 +841,43 @@ jobs:
801841 ORG_ID : ${{ secrets.UNITY_CLOUD_ORG_ID }}
802842 PROJECT_ID : ${{ secrets.UNITY_CLOUD_PROJECT_ID }}
803843 run : python -u scripts/cloudbuild/build.py --cancel
844+
845+ build-gate :
846+ name : Build Gate (Windows + macOS)
847+ runs-on : ubuntu-latest
848+ needs : [prebuild, build]
849+ if : always() && github.event_name == 'pull_request'
850+ steps :
851+ - name : Verify both targets built and passed
852+ shell : bash
853+ run : |
854+ set -euo pipefail
855+
856+ should_build='${{ needs.prebuild.outputs.should_build }}'
857+ prebuild_result='${{ needs.prebuild.result }}'
858+
859+ # No Explorer/ changes, draft without override, or perf_test path — gate is not applicable.
860+ if [ "$prebuild_result" != "success" ] || [ "$should_build" != "true" ]; then
861+ echo "Gate not applicable (prebuild=$prebuild_result, should_build='$should_build'). Passing."
862+ exit 0
863+ fi
864+
865+ targets='${{ needs.prebuild.outputs.targets }}'
866+ echo "Targets that ran: $targets"
867+
868+ has_windows=$(echo "$targets" | jq 'any(. == "windows64")')
869+ has_macos=$(echo "$targets" | jq 'any(. == "macos")')
870+ if [ "$has_windows" != "true" ] || [ "$has_macos" != "true" ]; then
871+ echo "::error::Build Gate requires both Windows and macOS builds. This run was filtered to: $targets"
872+ echo "::error::Remove the 'windows-only' or 'macos-only' label so both targets build, then push or re-trigger."
873+ exit 1
874+ fi
875+
876+ build_result='${{ needs.build.result }}'
877+ if [ "$build_result" != "success" ]; then
878+ echo "::error::Build matrix did not succeed (result: $build_result)"
879+ exit 1
880+ fi
881+
882+ echo "Both Windows and macOS builds passed."
804883# Test change
0 commit comments