Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions .github/workflows/_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,15 @@ jobs:
- name: Archive standard binary
shell: msys2 {0}
run: |
BIN=build/c/codebase-memory-mcp
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
cp "$BIN" codebase-memory-mcp.exe
make -f Makefile.cbm build/c/codebase-memory-mcp-launcher.exe CC=clang CXX=clang++
PAYLOAD=build/c/codebase-memory-mcp
[ -f "${PAYLOAD}.exe" ] && PAYLOAD="${PAYLOAD}.exe"
cp build/c/codebase-memory-mcp-launcher.exe codebase-memory-mcp.exe
cp "$PAYLOAD" codebase-memory-mcp.payload.exe
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-windows-amd64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-windows-amd64.zip \
codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md

- name: Attest standard binary provenance
if: ${{ inputs.attest }}
Expand All @@ -196,11 +200,15 @@ jobs:
- name: Archive UI binary
shell: msys2 {0}
run: |
BIN=build/c/codebase-memory-mcp
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
cp "$BIN" codebase-memory-mcp.exe
make -f Makefile.cbm build/c/codebase-memory-mcp-launcher.exe CC=clang CXX=clang++
PAYLOAD=build/c/codebase-memory-mcp
[ -f "${PAYLOAD}.exe" ] && PAYLOAD="${PAYLOAD}.exe"
cp build/c/codebase-memory-mcp-launcher.exe codebase-memory-mcp.exe
cp "$PAYLOAD" codebase-memory-mcp.payload.exe
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-ui-windows-amd64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-ui-windows-amd64.zip \
codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md

- name: Attest UI binary provenance
if: ${{ inputs.attest }}
Expand Down Expand Up @@ -251,11 +259,15 @@ jobs:
- name: Archive standard binary
shell: msys2 {0}
run: |
BIN=build/c/codebase-memory-mcp
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
cp "$BIN" codebase-memory-mcp.exe
make -f Makefile.cbm build/c/codebase-memory-mcp-launcher.exe CC=clang CXX=clang++
PAYLOAD=build/c/codebase-memory-mcp
[ -f "${PAYLOAD}.exe" ] && PAYLOAD="${PAYLOAD}.exe"
cp build/c/codebase-memory-mcp-launcher.exe codebase-memory-mcp.exe
cp "$PAYLOAD" codebase-memory-mcp.payload.exe
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-windows-arm64.zip \
codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md

- name: Attest standard binary provenance
if: ${{ inputs.attest }}
Expand All @@ -277,11 +289,15 @@ jobs:
- name: Archive UI binary
shell: msys2 {0}
run: |
BIN=build/c/codebase-memory-mcp
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
cp "$BIN" codebase-memory-mcp.exe
make -f Makefile.cbm build/c/codebase-memory-mcp-launcher.exe CC=clang CXX=clang++
PAYLOAD=build/c/codebase-memory-mcp
[ -f "${PAYLOAD}.exe" ] && PAYLOAD="${PAYLOAD}.exe"
cp build/c/codebase-memory-mcp-launcher.exe codebase-memory-mcp.exe
cp "$PAYLOAD" codebase-memory-mcp.payload.exe
scripts/gen-third-party-notices.sh THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-ui-windows-arm64.zip codebase-memory-mcp.exe LICENSE install.ps1 THIRD_PARTY_NOTICES.md
zip codebase-memory-mcp-ui-windows-arm64.zip \
codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md

- name: Attest UI binary provenance
if: ${{ inputs.attest }}
Expand Down
65 changes: 46 additions & 19 deletions .github/workflows/_smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ jobs:
run: scripts/smoke-test.sh ./codebase-memory-mcp
env:
SMOKE_DOWNLOAD_URL: http://localhost:18080
SMOKE_UPDATE_FIXTURE_DIR: /tmp/smoke-server

- name: Security audits
run: |
Expand Down Expand Up @@ -210,17 +211,27 @@ jobs:
SUFFIX=${{ matrix.variant == 'ui' && '-ui' || '' }}
ARCH=${{ matrix.arch }}
unzip -o "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip"
[ -n "$SUFFIX" ] && cp "codebase-memory-mcp${SUFFIX}.exe" codebase-memory-mcp.exe || true
test -s codebase-memory-mcp.exe
test -s codebase-memory-mcp.payload.exe
PROFILE_ROOT="$(cygpath -u "$USERPROFILE")"
LAUNCH_DIR="$(mktemp -d "$PROFILE_ROOT/cbm-release-version.XXXXXX")"
trap 'rm -rf "$LAUNCH_DIR"' EXIT
cp codebase-memory-mcp.exe codebase-memory-mcp.payload.exe "$LAUNCH_DIR/"
"$LAUNCH_DIR/codebase-memory-mcp.payload.exe" --version
"$LAUNCH_DIR/codebase-memory-mcp.exe" --version

- name: Start artifact server
shell: msys2 {0}
run: |
mkdir -p /tmp/smoke-server
cp codebase-memory-mcp.exe /tmp/smoke-server/
cp codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md /tmp/smoke-server/
SUFFIX=${{ matrix.variant == 'ui' && '-ui' || '' }}
ARCH=${{ matrix.arch }}
cd /tmp/smoke-server
zip -q "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip" codebase-memory-mcp.exe
zip -q "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip" \
codebase-memory-mcp.exe codebase-memory-mcp.payload.exe \
LICENSE install.ps1 THIRD_PARTY_NOTICES.md
if [ -n "$SUFFIX" ]; then
cp "codebase-memory-mcp${SUFFIX}-windows-${ARCH}.zip" "codebase-memory-mcp-windows-${ARCH}.zip"
fi
Expand All @@ -232,35 +243,51 @@ jobs:

- name: Smoke test
shell: msys2 {0}
run: scripts/smoke-test.sh ./codebase-memory-mcp.exe
run: |
PROFILE_ROOT="$(cygpath -u "$USERPROFILE")"
SMOKE_DIR="$(mktemp -d "$PROFILE_ROOT/cbm-release-smoke.XXXXXX")"
trap 'rm -rf "$SMOKE_DIR"' EXIT
cp codebase-memory-mcp.exe codebase-memory-mcp.payload.exe "$SMOKE_DIR/"
CBM_CACHE_DIR="$(cygpath -m "$SMOKE_DIR/cache")" \
SMOKE_TEMP_ROOT="$SMOKE_DIR" \
scripts/smoke-test.sh "$SMOKE_DIR/codebase-memory-mcp.exe"
env:
SMOKE_DOWNLOAD_URL: http://127.0.0.1:18080
SMOKE_UPDATE_FIXTURE_DIR: /tmp/smoke-server
SMOKE_ARCH: ${{ matrix.arch }}

- name: Security audits
shell: msys2 {0}
run: |
scripts/security-strings.sh ./codebase-memory-mcp.exe
scripts/security-install.sh ./codebase-memory-mcp.exe
scripts/security-strings.sh ./codebase-memory-mcp.payload.exe
PROFILE_ROOT="$(cygpath -u "$USERPROFILE")"
SECURITY_DIR="$(mktemp -d "$PROFILE_ROOT/cbm-release-security.XXXXXX")"
trap 'rm -rf "$SECURITY_DIR"' EXIT
cp codebase-memory-mcp.exe codebase-memory-mcp.payload.exe "$SECURITY_DIR/"
TMPDIR="$SECURITY_DIR" \
scripts/security-install.sh "$SECURITY_DIR/codebase-memory-mcp.exe"

- name: Windows Defender scan
shell: pwsh
run: |
& "C:\Program Files\Windows Defender\MpCmdRun.exe" -SignatureUpdate 2>$null
$result = & "C:\Program Files\Windows Defender\MpCmdRun.exe" -Scan -ScanType 3 -File "$PWD\codebase-memory-mcp.exe" -DisableRemediation
$code = $LASTEXITCODE
Write-Host $result
# MpCmdRun -Scan exit codes: 0 = clean, 2 = threat found. Any OTHER non-zero
# means the scan engine could not run at all (e.g. hr=0x800106ba: the Defender
# antimalware service is unavailable on the runner) — that is NOT a detection.
# Fail soft on an engine failure so a transient runner-side AV outage can't
# false-fail a release; only a real detection (exit 2) hard-blocks.
if ($code -eq 2) {
Write-Host "BLOCKED: Windows Defender flagged binary!"; exit 1
} elseif ($code -ne 0) {
Write-Host "::warning::Windows Defender scan could not run (exit $code) - skipping AV gate on this runner"
} else {
Write-Host "=== Windows Defender: clean ==="
foreach ($binary in @("codebase-memory-mcp.exe", "codebase-memory-mcp.payload.exe")) {
$result = & "C:\Program Files\Windows Defender\MpCmdRun.exe" -Scan -ScanType 3 -File "$PWD\$binary" -DisableRemediation
$code = $LASTEXITCODE
Write-Host $result
# MpCmdRun -Scan exit codes: 0 = clean, 2 = threat found. Any OTHER non-zero
# means the scan engine could not run at all (e.g. hr=0x800106ba: the Defender
# antimalware service is unavailable on the runner) — that is NOT a detection.
# Fail soft on an engine failure so a transient runner-side AV outage can't
# false-fail a release; only a real detection (exit 2) hard-blocks.
if ($code -eq 2) {
Write-Host "BLOCKED: Windows Defender flagged $binary!"; exit 1
} elseif ($code -ne 0) {
Write-Host "::warning::Windows Defender scan could not run for $binary (exit $code) - skipping AV gate on this runner"
} else {
Write-Host "=== Windows Defender: $binary clean ==="
}
}

smoke-linux-portable:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ jobs:
with:
node-version: "22"

- name: Test npm wrapper failure handling
working-directory: pkg/npm
run: npm test

- name: Build product binary with embedded UI
shell: msys2 {0}
# --with-ui builds the frontend (npm) and embeds it, so the drive-picker
Expand Down
16 changes: 13 additions & 3 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,19 @@ jobs:
shell: msys2 {0}
run: |
scripts/build.sh CC=clang CXX=clang++
BIN="$(pwd)/build/c/codebase-memory-mcp"
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
scripts/smoke-test.sh "$BIN"
# MSYS2 /tmp is intentionally shared. The launcher correctly rejects
# a bundle below that writable ancestor. RUNNER_TEMP is also below
# the shared D:\a tree, so stage in the runner account's profile.
PROFILE_ROOT="$(cygpath -u "$USERPROFILE")"
SMOKE_DIR="$(mktemp -d "$PROFILE_ROOT/cbm-pr-smoke.XXXXXX")"
trap 'rm -rf "$SMOKE_DIR"' EXIT
cp build/c/codebase-memory-mcp-launcher.exe \
"$SMOKE_DIR/codebase-memory-mcp.exe"
cp build/c/codebase-memory-mcp.exe \
"$SMOKE_DIR/codebase-memory-mcp.payload.exe"
CBM_CACHE_DIR="$(cygpath -m "$SMOKE_DIR/cache")" \
SMOKE_TEMP_ROOT="$SMOKE_DIR" \
scripts/smoke-test.sh "$SMOKE_DIR/codebase-memory-mcp.exe"
ci-ok:
# The one required context (besides dco) — fails unless every PR stage
Expand Down
Loading