Skip to content

Commit f7f425d

Browse files
authored
Merge pull request #14 from ngallodev/release-tooling
fix: gate releases and integrate upstream daemon/cache/parser fixes
2 parents bbabc07 + ea4335f commit f7f425d

68 files changed

Lines changed: 4630 additions & 382 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.coderabbit.yaml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Keep CodeRabbit automatic reviews enabled; Claude workflows are disabled.
2+
reviews:
3+
auto_review:
4+
enabled: true

‎.github/workflows/_build.yml‎

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ on:
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'
@@ -29,28 +33,9 @@ jobs:
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
@@ -112,6 +97,7 @@ jobs:
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

‎.github/workflows/_smoke.yml‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
description: 'Smoke the shipped binaries on the broad platform matrix (extra OS versions) instead of the core set'
99
type: boolean
1010
default: false
11+
platforms:
12+
description: "Platform set: 'all' (default) or 'linux' (skip darwin and windows legs)"
13+
type: string
14+
default: 'all'
1115
permissions:
1216
contents: read
1317

@@ -29,6 +33,7 @@ jobs:
2933
id: set
3034
env:
3135
BROAD: ${{ inputs.broad_platforms }}
36+
PLATFORMS: ${{ inputs.platforms }}
3237
run: |
3338
CORE_UNIX='[
3439
{"os":"ubuntu-latest","goos":"linux","goarch":"amd64"},
@@ -71,6 +76,16 @@ jobs:
7176
WIN=$(jq -cn --argjson a "$CORE_WIN" '$a')
7277
PORTABLE=$(jq -cn --argjson a "$CORE_PORTABLE" '$a')
7378
fi
79+
case "$PLATFORMS" in
80+
all) ;;
81+
linux)
82+
# Linux-only release: drop darwin legs; the windows job is
83+
# skipped by its job-level `if`, so its matrix is never used.
84+
UNIX=$(jq -c 'map(select(.goos == "linux"))' <<<"$UNIX")
85+
WIN='[{"os":"windows-latest","arch":"amd64"}]'
86+
;;
87+
*) echo "::error::unknown platforms input: $PLATFORMS"; exit 1 ;;
88+
esac
7489
# One composition ships; the wrappers assert the embedded UI themselves
7590
# (SMOKE_REQUIRE_UI in scripts/ci/smoke-artifact.sh and below).
7691
UNIX_M=$(jq -cn --argjson a "$UNIX" '{include:$a}')
@@ -161,6 +176,7 @@ jobs:
161176
clamscan --no-summary "$RUNNER_TEMP/cbm-artifact/codebase-memory-cli"
162177
163178
smoke-windows:
179+
if: ${{ inputs.platforms != 'linux' }}
164180
needs: setup-matrix
165181
strategy:
166182
fail-fast: false

‎.github/workflows/_soak.yml‎

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,35 @@ on:
2424
description: 'Soak the already selected binaries-* artifacts instead of rebuilding quick-lane binaries'
2525
type: boolean
2626
default: false
27+
platforms:
28+
description: "Platform set: 'all' (default) or 'linux' (skip darwin and windows legs)"
29+
type: string
30+
default: 'all'
2731

2832
permissions:
2933
contents: read
3034

3135
jobs:
36+
# Emit the unix (linux + darwin) matrix as JSON so platforms=linux can drop
37+
# the darwin legs. The default 'all' keeps the four historical legs.
38+
setup-matrix:
39+
runs-on: ubuntu-latest
40+
timeout-minutes: 5
41+
outputs:
42+
unix: ${{ steps.set.outputs.unix }}
43+
steps:
44+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
45+
- name: Compute matrices
46+
id: set
47+
env:
48+
PLATFORMS: ${{ inputs.platforms }}
49+
run: bash scripts/ci/soak-matrix.sh
50+
3251
soak-quick:
52+
needs: setup-matrix
3353
strategy:
3454
fail-fast: false
35-
matrix:
36-
include:
37-
- os: ubuntu-latest
38-
goos: linux
39-
goarch: amd64
40-
cc: gcc
41-
cxx: g++
42-
- os: ubuntu-24.04-arm
43-
goos: linux
44-
goarch: arm64
45-
cc: gcc
46-
cxx: g++
47-
- os: macos-14
48-
goos: darwin
49-
goarch: arm64
50-
cc: cc
51-
cxx: c++
52-
- os: macos-15-intel
53-
goos: darwin
54-
goarch: amd64
55-
cc: cc
56-
cxx: c++
55+
matrix: ${{ fromJSON(needs.setup-matrix.outputs.unix) }}
5756
runs-on: ${{ matrix.os }}
5857
# Budget doctrine (this line has been silently violated TWICE): the job
5958
# timeout must exceed the WORST-CASE run length, and duration_minutes is
@@ -111,6 +110,7 @@ jobs:
111110
retention-days: 14
112111

113112
soak-quick-windows:
113+
if: ${{ inputs.platforms != 'linux' }}
114114
runs-on: windows-latest
115115
# Budget doctrine (see soak-quick): duration_minutes is per LEG, so two
116116
# 240-min legs need ~480 min + build; 300 silently killed the second leg.
@@ -188,6 +188,7 @@ jobs:
188188
retention-days: 14
189189

190190
soak-quick-windows-arm64:
191+
if: ${{ inputs.platforms != 'linux' }}
191192
# Native ARM64 Windows soak (CLANGARM64, no sanitizer — ASan is unavailable
192193
# on native ARM64 Windows). Builds from source like soak-quick-windows.
193194
runs-on: windows-11-arm
@@ -317,34 +318,14 @@ jobs:
317318
retention-days: 14
318319

319320
soak-asan:
321+
needs: setup-matrix
320322
# Supplemental source-built instrumentation. This can find memory bugs but
321323
# is not evidence that the selected release bytes were soaked; the quick
322324
# jobs above own that release gate when use_release_artifacts=true.
323325
if: ${{ inputs.run_asan }}
324326
strategy:
325327
fail-fast: false
326-
matrix:
327-
include:
328-
- os: ubuntu-latest
329-
goos: linux
330-
goarch: amd64
331-
cc: gcc
332-
cxx: g++
333-
- os: ubuntu-24.04-arm
334-
goos: linux
335-
goarch: arm64
336-
cc: gcc
337-
cxx: g++
338-
- os: macos-14
339-
goos: darwin
340-
goarch: arm64
341-
cc: cc
342-
cxx: c++
343-
- os: macos-15-intel
344-
goos: darwin
345-
goarch: amd64
346-
cc: cc
347-
cxx: c++
328+
matrix: ${{ fromJSON(needs.setup-matrix.outputs.unix) }}
348329
runs-on: ${{ matrix.os }}
349330
# ASan soak runs a FIXED 15-min soak (hard-coded below, NOT driven by
350331
# inputs.duration_minutes), but the ASan-instrumented build is slow and
@@ -377,7 +358,7 @@ jobs:
377358
retention-days: 14
378359

379360
soak-asan-windows:
380-
if: ${{ inputs.run_asan }}
361+
if: ${{ inputs.run_asan && inputs.platforms != 'linux' }}
381362
runs-on: windows-latest
382363
# FIXED 15-min soak (hard-coded below). MSYS2/Wine + ASan build is the
383364
# slowest path; 60 keeps the budget well above the run length so it is

0 commit comments

Comments
 (0)