1616 description : ' VirusTotal-scan both candidates before tuple-local selection (release must keep true)'
1717 type : boolean
1818 default : true
19+ platforms :
20+ description : " Platform set: 'all' (default, eight targets) or 'linux' (linux-amd64, linux-arm64 and both portable targets only)"
21+ type : string
22+ default : ' all'
1923 secrets :
2024 VIRUS_TOTAL_SCANNER_API_KEY :
2125 description : ' VirusTotal API key used for candidate selection'
2933 build-unix :
3034 strategy :
3135 fail-fast : false
36+ # platforms=linux drops the darwin legs; the default keeps all four.
3237 matrix :
33- include :
34- - os : ubuntu-latest
35- goos : linux
36- goarch : amd64
37- cc : gcc
38- cxx : g++
39- - os : ubuntu-24.04-arm
40- goos : linux
41- goarch : arm64
42- cc : gcc
43- cxx : g++
44- - os : macos-14
45- goos : darwin
46- goarch : arm64
47- cc : cc
48- cxx : c++
49- - os : macos-15-intel
50- goos : darwin
51- goarch : amd64
52- cc : cc
53- cxx : c++
38+ include : ${{ fromJSON(inputs.platforms == 'linux' && '[{"os":"ubuntu-latest","goos":"linux","goarch":"amd64","cc":"gcc","cxx":"g++"},{"os":"ubuntu-24.04-arm","goos":"linux","goarch":"arm64","cc":"gcc","cxx":"g++"}]' || '[{"os":"ubuntu-latest","goos":"linux","goarch":"amd64","cc":"gcc","cxx":"g++"},{"os":"ubuntu-24.04-arm","goos":"linux","goarch":"arm64","cc":"gcc","cxx":"g++"},{"os":"macos-14","goos":"darwin","goarch":"arm64","cc":"cc","cxx":"c++"},{"os":"macos-15-intel","goos":"darwin","goarch":"amd64","cc":"cc","cxx":"c++"}]') }}
5439 runs-on : ${{ matrix.os }}
5540 # Every leg is BLOCKING — no continue-on-error. The darwin-amd64 binary
5641 # built on macos-15-intel must ship with every release; if that runner is
11297 if-no-files-found : error
11398
11499 build-windows :
100+ if : ${{ inputs.platforms != 'linux' }}
115101 runs-on : windows-latest
116102 timeout-minutes : 240
117103 steps :
@@ -170,6 +156,7 @@ jobs:
170156 if-no-files-found : error
171157
172158 build-windows-arm64 :
159+ if : ${{ inputs.platforms != 'linux' }}
173160 # Native ARM64 Windows binary via the CLANGARM64 toolchain on the
174161 # windows-11-arm runner (the same toolchain the test suite already
175162 # exercises). Without it, ARM-Windows users fall back to the x86_64
@@ -299,10 +286,31 @@ jobs:
299286 # equivalent candidates (unstripped/debug-stripped/stripped); the selector may
300287 # only choose within that tuple. A hard result on ANY sibling blocks
301288 # the all-target release rather than selecting around a real detection.
289+ #
290+ # platforms=linux narrows the tuple set to the four Linux targets. The two
291+ # Windows build jobs are then skipped by design, so the join states each
292+ # needed result explicitly: a skipped Windows build is accepted ONLY for the
293+ # linux set, and every other needed job must have succeeded.
302294 select-package :
303295 needs : [build-unix, build-windows, build-windows-arm64, build-linux-portable]
296+ if : >-
297+ ${{ !cancelled()
298+ && needs.build-unix.result == 'success'
299+ && needs.build-linux-portable.result == 'success'
300+ && ((inputs.platforms == 'linux'
301+ && needs.build-windows.result == 'skipped'
302+ && needs.build-windows-arm64.result == 'skipped')
303+ || (inputs.platforms != 'linux'
304+ && needs.build-windows.result == 'success'
305+ && needs.build-windows-arm64.result == 'success')) }}
304306 runs-on : ubuntu-latest
305307 timeout-minutes : 330
308+ env :
309+ # Canonical-order target set, its size, and its candidate count. The
310+ # scripts re-validate these; they are passed explicitly, never inferred.
311+ RELEASE_TARGETS : ${{ inputs.platforms == 'linux' && 'linux-amd64,linux-arm64,linux-amd64-portable,linux-arm64-portable' || 'linux-amd64,linux-arm64,linux-amd64-portable,linux-arm64-portable,darwin-amd64,darwin-arm64,windows-amd64,windows-arm64' }}
312+ EXPECT_TARGETS : ${{ inputs.platforms == 'linux' && '4' || '8' }}
313+ EXPECT_CANDIDATES : ${{ inputs.platforms == 'linux' && '12' || '24' }}
306314 permissions :
307315 contents : read
308316 id-token : write
@@ -323,15 +331,16 @@ jobs:
323331 python3 scripts/ci/stage-release-candidates.py \
324332 "$RUNNER_TEMP/release-candidate-artifacts" \
325333 release-candidate-scan \
326- --expect-targets 8 \
327- --expect-candidates 24
334+ --targets "$RELEASE_TARGETS" \
335+ --expect-targets "$EXPECT_TARGETS" \
336+ --expect-candidates "$EXPECT_CANDIDATES"
328337 # Staging copied and re-hashed every byte into the immutable object
329338 # set. Drop the redundant artifact-download tree before the VT wait.
330339 test -n "$RUNNER_TEMP"
331340 rm -rf -- "$RUNNER_TEMP/release-candidate-artifacts"
332341 test ! -e "$RUNNER_TEMP/release-candidate-artifacts"
333342
334- - name : Submit all 24 candidates to VirusTotal
343+ - name : Submit every candidate (24, or 12 for platforms=linux) to VirusTotal
335344 if : ${{ inputs.scan_candidates }}
336345 uses : crazy-max/ghaction-virustotal@936d8c5c00afe97d3d9a1af26d017cfdf26800a2 # v5.0.0
337346 id : virustotal-candidates
@@ -362,6 +371,7 @@ jobs:
362371 --candidates release-candidate-scan/candidates.tsv \
363372 --objects-dir release-candidate-scan/objects \
364373 --results release-candidate-scan/vt-results.tsv \
374+ --targets "$RELEASE_TARGETS" \
365375 --out-dir release-selection
366376
367377 # This is intentionally reachable only from dry-run.yml's explicit
@@ -374,6 +384,7 @@ jobs:
374384 --candidates release-candidate-scan/candidates.tsv \
375385 --objects-dir release-candidate-scan/objects \
376386 --default-stripped \
387+ --targets "$RELEASE_TARGETS" \
377388 --out-dir release-selection
378389
379390 - name : Reclaim rejected and redundant candidate bytes
@@ -388,11 +399,7 @@ jobs:
388399 env :
389400 VERSION : ${{ inputs.version }}
390401 run : |
391- for target in \
392- linux-amd64 linux-arm64 \
393- linux-amd64-portable linux-arm64-portable \
394- darwin-amd64 darwin-arm64 \
395- windows-amd64 windows-arm64; do
402+ for target in ${RELEASE_TARGETS//,/ }; do
396403 goos="${target%%-*}"
397404 goarch="${target#*-}"
398405 selected_name=codebase-memory-cli
@@ -417,6 +424,7 @@ jobs:
417424 run : |
418425 python3 scripts/ci/verify-release-selection.py \
419426 --selection release-selection/release-selection.tsv \
427+ --targets "$RELEASE_TARGETS" \
420428 --archive-dir release-containers
421429
422430 - name : Prepare durable candidate-selection evidence
@@ -478,27 +486,31 @@ jobs:
478486 if-no-files-found : error
479487
480488 - name : Upload darwin-amd64 containers
489+ if : ${{ inputs.platforms != 'linux' }}
481490 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
482491 with :
483492 name : binaries-darwin-amd64
484493 path : release-containers/darwin-amd64/*
485494 if-no-files-found : error
486495
487496 - name : Upload darwin-arm64 containers
497+ if : ${{ inputs.platforms != 'linux' }}
488498 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
489499 with :
490500 name : binaries-darwin-arm64
491501 path : release-containers/darwin-arm64/*
492502 if-no-files-found : error
493503
494504 - name : Upload windows-amd64 containers
505+ if : ${{ inputs.platforms != 'linux' }}
495506 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
496507 with :
497508 name : binaries-windows-amd64
498509 path : release-containers/windows-amd64/*
499510 if-no-files-found : error
500511
501512 - name : Upload windows-arm64 containers
513+ if : ${{ inputs.platforms != 'linux' }}
502514 uses : actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
503515 with :
504516 name : binaries-windows-arm64
0 commit comments