mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-05 08:23:53 +08:00
Combines the ccache steps with this branch's Windows hardening: the protected temp root and profile staging keep their roles, the cache steps slot alongside them, and the strictly per-ref keys apply unchanged. The daemon branch's own CI legs warm from the second push on. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
293 lines
13 KiB
YAML
293 lines
13 KiB
YAML
# Reusable: unit + integration tests on all platforms
|
|
name: Test
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
skip_perf:
|
|
description: 'Skip incremental perf tests (phases 2-7)'
|
|
type: boolean
|
|
default: true
|
|
broad_platforms:
|
|
description: 'Test the broad platform matrix (older glibc + extra OS versions) instead of the core set'
|
|
type: boolean
|
|
default: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# Emit the platform matrices as JSON. The CORE set is the default (fast,
|
|
# unchanged); the BROAD set adds extra free runners (older glibc /
|
|
# additional OS versions) for a wider "does it build everywhere" picture.
|
|
setup-matrix:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
outputs:
|
|
unix: ${{ steps.set.outputs.unix }}
|
|
windows: ${{ steps.set.outputs.windows }}
|
|
steps:
|
|
- name: Compute matrices
|
|
id: set
|
|
env:
|
|
BROAD: ${{ inputs.broad_platforms }}
|
|
run: |
|
|
CORE_UNIX='[
|
|
{"os":"ubuntu-latest","cc":"gcc","cxx":"g++"},
|
|
{"os":"ubuntu-24.04-arm","cc":"gcc","cxx":"g++"},
|
|
{"os":"macos-14","cc":"cc","cxx":"c++"},
|
|
{"os":"macos-15-intel","cc":"cc","cxx":"c++"}
|
|
]'
|
|
# Broad matrix legs are REQUIRED gates (no optional/continue-on-error
|
|
# escape hatches): the release dry run must be all-green, every platform.
|
|
BROAD_UNIX='[
|
|
{"os":"ubuntu-22.04","cc":"gcc","cxx":"g++"},
|
|
{"os":"ubuntu-22.04-arm","cc":"gcc","cxx":"g++"},
|
|
{"os":"macos-15","cc":"cc","cxx":"c++"}
|
|
]'
|
|
# Each Windows leg pins the msys2 environment + package arch to the
|
|
# RUNNER architecture so the build is native, never emulated:
|
|
# x86-64 runners -> CLANG64 (mingw-w64-clang-x86_64-*)
|
|
# ARM64 runner -> CLANGARM64 (mingw-w64-clang-aarch64-*)
|
|
# windows-11-arm previously used the x86-64 CLANG64 toolchain, so its
|
|
# binary ran under Windows-on-ARM x86-64 emulation and ASan's function
|
|
# interception crashed (interception_win: unhandled instruction). With
|
|
# the native ARM64 toolchain ASan instruments native ARM64 code, so it
|
|
# is a real (non-optional) gate, not a tolerated emulated-flake.
|
|
CORE_WIN='[{"os":"windows-latest","msystem":"CLANG64","pkg":"x86_64"}]'
|
|
BROAD_WIN='[{"os":"windows-2025","msystem":"CLANG64","pkg":"x86_64"},{"os":"windows-11-arm","msystem":"CLANGARM64","pkg":"aarch64"}]'
|
|
if [ "$BROAD" = "true" ]; then
|
|
UNIX=$(jq -cn --argjson a "$CORE_UNIX" --argjson b "$BROAD_UNIX" '$a + $b')
|
|
WIN=$(jq -cn --argjson a "$CORE_WIN" --argjson b "$BROAD_WIN" '$a + $b')
|
|
else
|
|
UNIX=$(jq -cn --argjson a "$CORE_UNIX" '$a')
|
|
WIN=$(jq -cn --argjson a "$CORE_WIN" '$a')
|
|
fi
|
|
echo "unix={\"include\":$UNIX}" >> "$GITHUB_OUTPUT"
|
|
echo "windows={\"include\":$WIN}" >> "$GITHUB_OUTPUT"
|
|
|
|
test-unix:
|
|
needs: setup-matrix
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.setup-matrix.outputs.unix) }}
|
|
runs-on: ${{ matrix.os }}
|
|
# Broad-only legs (extra OS versions) are informational: visible but
|
|
# non-blocking, so a flaky/less-common runner can't block a release.
|
|
continue-on-error: ${{ matrix.optional == true }}
|
|
timeout-minutes: 240
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- name: Install deps (Ubuntu)
|
|
if: startsWith(matrix.os, 'ubuntu')
|
|
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev ccache
|
|
|
|
- name: Install ccache (macOS)
|
|
if: startsWith(matrix.os, 'macos')
|
|
run: command -v ccache >/dev/null 2>&1 || brew install ccache
|
|
|
|
# Verified compiler cache: CCACHE_COMPILERCHECK=content keys every entry
|
|
# on the compiler-binary CONTENT plus the fully preprocessed input, so a
|
|
# hit is provably the identical compilation — a stale or foreign cache
|
|
# can only miss, never return wrong output (see scripts/env.sh).
|
|
# Keys embed github.ref on top of GitHub's own branch scoping: caches are
|
|
# STRICTLY per-ref by policy — no base-branch fallback, a new PR builds
|
|
# cold once and only its own pushes warm it.
|
|
- name: Compiler cache (content-verified)
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ github.workspace }}/.ccache
|
|
key: ccache-test-${{ matrix.os }}-${{ matrix.cc }}-${{ github.ref }}-${{ github.sha }}
|
|
restore-keys: |
|
|
ccache-test-${{ matrix.os }}-${{ matrix.cc }}-${{ github.ref }}-
|
|
|
|
- name: Test
|
|
run: scripts/test.sh CC=${{ matrix.cc }} CXX=${{ matrix.cxx }}
|
|
env:
|
|
CBM_SKIP_PERF: ${{ inputs.skip_perf && '1' || '' }}
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
CCACHE_MAXSIZE: 1500M
|
|
|
|
- name: ccache stats
|
|
if: always()
|
|
run: ccache -s || true
|
|
env:
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
|
|
test-tsan:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 120
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- name: Install deps (Ubuntu)
|
|
run: sudo apt-get update && sudo apt-get install -y clang zlib1g-dev ccache
|
|
|
|
- name: Compiler cache (content-verified)
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ github.workspace }}/.ccache
|
|
key: ccache-tsan-${{ github.ref }}-${{ github.sha }}
|
|
restore-keys: |
|
|
ccache-tsan-${{ github.ref }}-
|
|
|
|
- name: ThreadSanitizer tests
|
|
# This job calls make directly (no env.sh), so route the compilers
|
|
# through ccache's Debian masquerade dir; update-ccache-symlinks in the
|
|
# ccache postinst has already linked the clang installed above.
|
|
run: |
|
|
export PATH=/usr/lib/ccache:$PATH
|
|
export CCACHE_COMPILERCHECK=content
|
|
make -f Makefile.cbm test-tsan CC=clang CXX=clang++
|
|
env:
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
CCACHE_MAXSIZE: 1500M
|
|
|
|
- name: ccache stats
|
|
if: always()
|
|
run: ccache -s || true
|
|
env:
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
|
|
test-windows:
|
|
needs: setup-matrix
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJSON(needs.setup-matrix.outputs.windows) }}
|
|
runs-on: ${{ matrix.os }}
|
|
continue-on-error: ${{ matrix.optional == true }}
|
|
timeout-minutes: 240
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
|
with:
|
|
msystem: ${{ matrix.msystem }}
|
|
path-type: inherit
|
|
install: >-
|
|
mingw-w64-clang-${{ matrix.pkg }}-clang
|
|
mingw-w64-clang-${{ matrix.pkg }}-compiler-rt
|
|
mingw-w64-clang-${{ matrix.pkg }}-zlib
|
|
mingw-w64-clang-${{ matrix.pkg }}-ccache
|
|
make
|
|
git
|
|
|
|
- name: Create protected per-user temp root
|
|
# The daemon suites fail closed on the MSYS-shared /tmp and on the
|
|
# runner's inherited LocalAppData\Temp ACLs. Give the whole harness a
|
|
# per-user root under the profile with an owner-stamped, protected
|
|
# current-SID DACL, matching the launcher/daemon trust policy.
|
|
shell: pwsh
|
|
run: |
|
|
$root = Join-Path $env:USERPROFILE ("cbm-ci-tmp-" + [guid]::NewGuid().ToString("N"))
|
|
New-Item -ItemType Directory -Path $root | Out-Null
|
|
$sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
$acl = [System.Security.AccessControl.DirectorySecurity]::new()
|
|
$acl.SetOwner($sid)
|
|
$acl.SetAccessRuleProtection($true, $false)
|
|
$rule = [System.Security.AccessControl.FileSystemAccessRule]::new(
|
|
$sid,
|
|
[System.Security.AccessControl.FileSystemRights]::FullControl,
|
|
([System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor
|
|
[System.Security.AccessControl.InheritanceFlags]::ObjectInherit),
|
|
[System.Security.AccessControl.PropagationFlags]::None,
|
|
[System.Security.AccessControl.AccessControlType]::Allow)
|
|
$acl.AddAccessRule($rule) | Out-Null
|
|
Set-Acl -LiteralPath $root -AclObject $acl
|
|
"CBM_CI_TEMP_ROOT=$root" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
|
|
|
- name: Compiler cache (content-verified)
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ github.workspace }}/.ccache
|
|
key: ccache-test-${{ matrix.os }}-${{ matrix.msystem }}-${{ github.ref }}-${{ github.sha }}
|
|
restore-keys: |
|
|
ccache-test-${{ matrix.os }}-${{ matrix.msystem }}-${{ github.ref }}-
|
|
|
|
- name: Test
|
|
shell: msys2 {0}
|
|
# AddressSanitizer is unavailable on native ARM64 Windows (LLVM ships no
|
|
# libclang_rt.asan for aarch64-w64-windows-gnu) and cannot intercept the
|
|
# system DLLs under x86-64 emulation either, so windows-11-arm runs the
|
|
# native ARM64 build with SANITIZE= (no sanitizer) — still a real
|
|
# functional gate. ASan/UBSan coverage comes from the other 9 legs,
|
|
# including native-ARM Linux/macOS. x86-64 Windows keeps full sanitizers.
|
|
run: |
|
|
# Native tests resolve temp via TEMP/TMP (cbm_tmpdir); shell tools use
|
|
# TMPDIR. Route both through the protected root created above so no
|
|
# fixture lands under a shared or ACL-inherited ancestry.
|
|
export TEMP="$(cygpath -m "$CBM_CI_TEMP_ROOT")"
|
|
export TMP="$TEMP"
|
|
export TMPDIR="$(cygpath -u "$CBM_CI_TEMP_ROOT")"
|
|
scripts/test.sh CC=clang CXX=clang++ ${{ matrix.os == 'windows-11-arm' && 'SANITIZE=' || '' }}
|
|
env:
|
|
CBM_SKIP_PERF: ${{ inputs.skip_perf && '1' || '' }}
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
CCACHE_MAXSIZE: 1500M
|
|
|
|
- name: ccache stats
|
|
if: always()
|
|
shell: msys2 {0}
|
|
run: ccache -s || true
|
|
env:
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
|
|
# Windows product-surface regression guards. Distinct from test-windows above
|
|
# (the sanitizer C suite): these drive a real product binary + embedded HTTP UI
|
|
# over stdio / CLI / HTTP and fail if a Windows bug already fixed on main comes
|
|
# back -- non-ASCII repo paths dropping definitions (#636/#357, fixed by #700),
|
|
# the PreToolUse hook augmenter no-op on drive-letter cwd (#618, fixed by #619),
|
|
# the UI directory picker not enumerating drives (#548, roots field), and non-ASCII
|
|
# CLI arguments being mangled by the narrow-argv main() (#423/#20, fixed by the
|
|
# wide-argv entrypoint that reads GetCommandLineW).
|
|
test-windows-guards:
|
|
runs-on: windows-latest
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
|
with:
|
|
msystem: CLANG64
|
|
path-type: inherit
|
|
install: >-
|
|
mingw-w64-clang-x86_64-clang
|
|
mingw-w64-clang-x86_64-zlib
|
|
mingw-w64-clang-x86_64-ccache
|
|
make
|
|
git
|
|
|
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version: "22"
|
|
|
|
- name: Test npm wrapper failure handling
|
|
working-directory: pkg/npm
|
|
run: npm test
|
|
|
|
- name: Compiler cache (content-verified)
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: ${{ github.workspace }}/.ccache
|
|
key: ccache-guards-${{ github.ref }}-${{ github.sha }}
|
|
restore-keys: |
|
|
ccache-guards-${{ github.ref }}-
|
|
|
|
- name: Build product binary with embedded UI
|
|
shell: msys2 {0}
|
|
# --with-ui builds the frontend (npm) and embeds it, so the drive-picker
|
|
# guard's HTTP UI is available. Functional gate only (no sanitizers).
|
|
run: scripts/build.sh --with-ui CC=clang CXX=clang++
|
|
env:
|
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
CCACHE_MAXSIZE: 1500M
|
|
|
|
- name: Windows regression guards (#636/#357, #618, #548, #423/#20)
|
|
shell: pwsh
|
|
# -GuardsOnly runs the four green guards and gates on them. The runner sets
|
|
# CBM_INDEX_SUPERVISOR=0 for determinism, but the non-ASCII CLI guard drops that
|
|
# override so it exercises the real supervisor->worker spawn (where #423/#20's
|
|
# second half lives); the other guards test path/hook/drive fixes in-process.
|
|
run: ./scripts/test-windows.ps1 -GuardsOnly -Binary build/c/codebase-memory-mcp.exe
|