Skip to content

Commit 4fac943

Browse files
committed
ci: green the dry-run smoke gate + ship native windows-arm64
Two release-blockers surfaced once #882 made every smoke leg a required gate (continue-on-error previously masked them): - smoke-unix ran the *dynamic* linux binary on ubuntu-22.04 / 22.04-arm, where it cannot start (it links glibc 2.38+) -> Phase 1 died. Older-glibc coverage is the -portable (static) binary's job and is green via the smoke-linux-portable broad legs, so drop the impossible dynamic broad legs (keep macOS). - the ClamAV scan died on every linux leg: apt auto-starts the clamav-freshclam daemon which holds the freshclam log lock, so the manual freshclam failed with "Failed to lock the log file ... Resource temporarily unavailable". Stop the daemon first. Also add native ARM64 Windows as a first-class release target -- the one platform we test (windows-11-arm) but never shipped: - build-windows-arm64 job (CLANGARM64) producing codebase-memory-mcp[-ui]-windows-arm64.zip - smoke-windows is now arch-aware: windows-11-arm smokes the NATIVE arm64 binary instead of the x86_64 binary under emulation - a native soak-quick-windows-arm64 leg (no sanitizer -- ASan is unavailable on native ARM64 Windows) - arm64 detection in install.ps1 release.yml already publishes windows-arm64 (asset filter + merge-multiple) and build_update_url/detect_arch already resolve it; npm/pip/install.sh compute arm64 already. scoop/winget/chocolatey per-version manifests are updated at release time. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
1 parent 1dae94f commit 4fac943

4 files changed

Lines changed: 158 additions & 17 deletions

File tree

.github/workflows/_build.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,75 @@ jobs:
183183
name: binaries-windows-amd64
184184
path: "*.zip"
185185

186+
build-windows-arm64:
187+
# Native ARM64 Windows binary via the CLANGARM64 toolchain on the
188+
# windows-11-arm runner (the same toolchain the test suite already
189+
# exercises). Without it, ARM-Windows users fall back to the x86_64
190+
# binary under emulation, and npm/pip on native-ARM Node/Python 404.
191+
runs-on: windows-11-arm
192+
timeout-minutes: 240
193+
steps:
194+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
195+
196+
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
197+
with:
198+
msystem: CLANGARM64
199+
path-type: inherit
200+
install: >-
201+
mingw-w64-clang-aarch64-clang
202+
mingw-w64-clang-aarch64-zlib
203+
make
204+
zip
205+
206+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
207+
with:
208+
node-version: "22"
209+
210+
- name: Build standard binary
211+
shell: msys2 {0}
212+
env:
213+
VERSION: ${{ inputs.version }}
214+
run: |
215+
if [ -n "$VERSION" ]; then
216+
scripts/build.sh --version "$VERSION" CC=clang CXX=clang++
217+
else
218+
scripts/build.sh CC=clang CXX=clang++
219+
fi
220+
221+
- name: Archive standard binary
222+
shell: msys2 {0}
223+
run: |
224+
BIN=build/c/codebase-memory-mcp
225+
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
226+
cp "$BIN" codebase-memory-mcp.exe
227+
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
228+
zip codebase-memory-mcp-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
229+
230+
- name: Build UI binary
231+
shell: msys2 {0}
232+
env:
233+
VERSION: ${{ inputs.version }}
234+
run: |
235+
if [ -n "$VERSION" ]; then
236+
scripts/build.sh --with-ui --version "$VERSION" CC=clang CXX=clang++
237+
else
238+
scripts/build.sh --with-ui CC=clang CXX=clang++
239+
fi
240+
241+
- name: Archive UI binary
242+
shell: msys2 {0}
243+
run: |
244+
BIN=build/c/codebase-memory-mcp
245+
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
246+
cp "$BIN" codebase-memory-mcp.exe
247+
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
248+
zip codebase-memory-mcp-ui-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
249+
250+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
251+
with:
252+
name: binaries-windows-arm64
253+
path: "*.zip"
254+
186255
build-linux-portable:
187256
# Fully static Linux binaries (gcc -static on Ubuntu).
188257
# Runs on any Linux distro without shared library dependencies.

.github/workflows/_smoke.yml

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,24 @@ jobs:
3737
{"os":"macos-14","goos":"darwin","goarch":"arm64"},
3838
{"os":"macos-15-intel","goos":"darwin","goarch":"amd64"}
3939
]'
40-
# Broad legs reuse existing goos/goarch artifacts on newer/older OS
41-
# versions (e.g. ubuntu-22.04 = older glibc) to widen the run-anywhere
42-
# signal without building new targets.
40+
# Broad legs reuse existing goos/goarch artifacts on additional OS
41+
# versions to widen the run-anywhere signal without building new targets.
4342
# Broad legs are REQUIRED gates (no optional / continue-on-error):
4443
# every smoke leg must pass. No `optional` flags anywhere.
44+
#
45+
# NOTE: the *dynamic* linux binary links glibc 2.38+ and cannot run on
46+
# older distros by design — older-glibc coverage is the -portable (static)
47+
# binary's job, exercised green by the smoke-linux-portable broad legs
48+
# (ubuntu-22.04 / 22.04-arm). So the dynamic broad legs stay on
49+
# forward-compatible OSes only (macOS); running the dynamic binary on
50+
# ubuntu-22.04 would fail Phase 1 (glibc too old), not a real regression.
4551
BROAD_UNIX='[
46-
{"os":"ubuntu-22.04","goos":"linux","goarch":"amd64"},
47-
{"os":"ubuntu-22.04-arm","goos":"linux","goarch":"arm64"},
4852
{"os":"macos-15","goos":"darwin","goarch":"arm64"}
4953
]'
50-
CORE_WIN='[{"os":"windows-latest"}]'
51-
# windows-11-arm runs the shipped x86_64 binary under emulation —
52-
# verifies the Windows artifact still launches on ARM hardware.
53-
BROAD_WIN='[{"os":"windows-2025"},{"os":"windows-11-arm"}]'
54+
CORE_WIN='[{"os":"windows-latest","arch":"amd64"}]'
55+
# windows-11-arm now runs the NATIVE arm64 binary (build-windows-arm64),
56+
# not the x86_64 binary under emulation — we smoke the artifact we ship.
57+
BROAD_WIN='[{"os":"windows-2025","arch":"amd64"},{"os":"windows-11-arm","arch":"arm64"}]'
5458
CORE_PORTABLE='[
5559
{"arch":"amd64","runner":"ubuntu-latest"},
5660
{"arch":"arm64","runner":"ubuntu-24.04-arm"}
@@ -152,6 +156,10 @@ jobs:
152156
if: startsWith(matrix.os, 'ubuntu')
153157
run: |
154158
sudo apt-get update -qq && sudo apt-get install -y -qq clamav > /dev/null 2>&1
159+
# apt auto-starts the clamav-freshclam daemon, which holds a lock on
160+
# freshclam's log/db; stop it so the manual freshclam below can run
161+
# (else: "Failed to lock the log file ... Resource temporarily unavailable").
162+
sudo systemctl stop clamav-freshclam 2>/dev/null || true
155163
sudo sed -i 's/^Example/#Example/' /etc/clamav/freshclam.conf 2>/dev/null || true
156164
grep -q "DatabaseMirror" /etc/clamav/freshclam.conf 2>/dev/null || \
157165
echo "DatabaseMirror database.clamav.net" | sudo tee -a /etc/clamav/freshclam.conf > /dev/null
@@ -183,23 +191,24 @@ jobs:
183191

184192
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
185193
with:
186-
msystem: CLANG64
194+
msystem: ${{ matrix.arch == 'arm64' && 'CLANGARM64' || 'CLANG64' }}
187195
path-type: inherit
188196
install: >-
189-
mingw-w64-clang-x86_64-python3
197+
mingw-w64-clang-${{ matrix.arch == 'arm64' && 'aarch64' || 'x86_64' }}-python3
190198
unzip
191199
zip
192200
coreutils
193201
194202
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
195203
with:
196-
name: binaries-windows-amd64
204+
name: binaries-windows-${{ matrix.arch }}
197205

198206
- name: Extract binary
199207
shell: msys2 {0}
200208
run: |
201209
SUFFIX=${{ matrix.variant == 'ui' && '-ui' || '' }}
202-
unzip -o "codebase-memory-mcp${SUFFIX}-windows-amd64.zip"
210+
ARCH=${{ matrix.arch }}
211+
unzip -o "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip"
203212
[ -n "$SUFFIX" ] && cp "codebase-memory-mcp${SUFFIX}.exe" codebase-memory-mcp.exe || true
204213
205214
- name: Start artifact server
@@ -208,10 +217,11 @@ jobs:
208217
mkdir -p /tmp/smoke-server
209218
cp codebase-memory-mcp.exe /tmp/smoke-server/
210219
SUFFIX=${{ matrix.variant == 'ui' && '-ui' || '' }}
220+
ARCH=${{ matrix.arch }}
211221
cd /tmp/smoke-server
212-
zip -q "codebase-memory-mcp${SUFFIX}-windows-amd64.zip" codebase-memory-mcp.exe
222+
zip -q "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip" codebase-memory-mcp.exe
213223
if [ -n "$SUFFIX" ]; then
214-
cp "codebase-memory-mcp${SUFFIX}-windows-amd64.zip" "codebase-memory-mcp-windows-amd64.zip"
224+
cp "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip" "codebase-memory-mcp-windows-${ARCH}.zip"
215225
fi
216226
sha256sum *.zip > checksums.txt
217227
python3 -m http.server 18080 -d /tmp/smoke-server &

.github/workflows/_soak.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,58 @@ jobs:
137137
path: soak-results-query-leak/
138138
retention-days: 14
139139

140+
soak-quick-windows-arm64:
141+
# Native ARM64 Windows soak (CLANGARM64, no sanitizer — ASan is unavailable
142+
# on native ARM64 Windows). Builds from source like soak-quick-windows.
143+
runs-on: windows-11-arm
144+
timeout-minutes: 300
145+
steps:
146+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
147+
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
148+
with:
149+
msystem: CLANGARM64
150+
path-type: inherit
151+
install: >-
152+
mingw-w64-clang-aarch64-clang
153+
mingw-w64-clang-aarch64-zlib
154+
mingw-w64-clang-aarch64-python3
155+
make
156+
git
157+
coreutils
158+
- name: Build
159+
shell: msys2 {0}
160+
run: scripts/build.sh ${{ inputs.version && format('--version {0}', inputs.version) || '' }} CC=clang CXX=clang++
161+
- name: Soak (${{ inputs.duration_minutes }} min)
162+
shell: msys2 {0}
163+
run: |
164+
BIN=build/c/codebase-memory-mcp
165+
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
166+
scripts/soak-test.sh "$BIN" ${{ inputs.duration_minutes }}
167+
# #581 guard on Windows — the platform the bug is reported on.
168+
- name: Query-leak soak (#581, read-only)
169+
shell: msys2 {0}
170+
env:
171+
CBM_SOAK_MODE: query-leak
172+
RESULTS_DIR: soak-results-query-leak
173+
run: |
174+
BIN=build/c/codebase-memory-mcp
175+
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
176+
scripts/soak-test.sh "$BIN" ${{ inputs.duration_minutes }} --skip-crash-test
177+
- name: Upload metrics
178+
if: always()
179+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
180+
with:
181+
name: soak-quick-windows-arm64
182+
path: soak-results/
183+
retention-days: 14
184+
- name: Upload query-leak metrics
185+
if: always()
186+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
187+
with:
188+
name: soak-query-leak-windows-arm64
189+
path: soak-results-query-leak/
190+
retention-days: 14
191+
140192
soak-asan:
141193
if: ${{ inputs.run_asan }}
142194
strategy:

install.ps1

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,26 @@ foreach ($arg in $args) {
3131
if ($arg -like "--dir=*") { $InstallDir = $arg.Substring(6) }
3232
}
3333

34+
# Detect architecture (ARM64 vs x64). PROCESSOR_ARCHITEW6432 is set to ARM64
35+
# when an x86/x64 process runs under emulation on ARM hardware, so check both to
36+
# resolve ARM64 even from an emulated shell; anything else falls back to amd64.
37+
if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64" -or $env:PROCESSOR_ARCHITEW6432 -eq "ARM64") {
38+
$Arch = "arm64"
39+
} else {
40+
$Arch = "amd64"
41+
}
42+
3443
Write-Host "codebase-memory-mcp installer (Windows)"
3544
Write-Host " variant: $Variant"
45+
Write-Host " arch: $Arch"
3646
Write-Host " target: $InstallDir\$BinName"
3747
Write-Host ""
3848

3949
# Build download URL
4050
if ($Variant -eq "ui") {
41-
$Archive = "codebase-memory-mcp-ui-windows-amd64.zip"
51+
$Archive = "codebase-memory-mcp-ui-windows-$Arch.zip"
4252
} else {
43-
$Archive = "codebase-memory-mcp-windows-amd64.zip"
53+
$Archive = "codebase-memory-mcp-windows-$Arch.zip"
4454
}
4555
$Url = "$BaseUrl/$Archive"
4656

0 commit comments

Comments
 (0)