The conformance job was a required check that ran nothing. Two bugs:
1. Its guard tested for tests/conformance/CMakeLists.txt or package.json.
The suite ships as tests/conformance/run.sh; neither file exists, so the
guard was always false and the job took the "skipped" (success) branch.
2. Even forced true, it ran `ctest --preset dev -L conformance` — no test
carries that label, so ctest reported "Total Tests: 0" and exited 0.
Replace the job body with PROTO's intended wiring from
tests/conformance/README.md: bootstrap the toolchain, pin Node 22 (apt ships
< 20; the TS replay runner needs >= 20), and run ./tests/conformance/run.sh
directly. The suite starts its own mockd and builds its own C++ runner, so no
cmake configure is needed. Verified it goes red: an enum-invalid fixture makes
run.sh exit 1; reverting it returns to green.
check_contract.py imports jsonschema and referencing, which bootstrap.sh did
not install. Add python3-jsonschema / python3-referencing to the apt set and
to --check, so one command still provisions the whole suite.
Guards now fail loudly instead of passing quietly:
- conformance has no skip branch any more. run.sh has landed; the job runs
it unconditionally and errors if the entrypoint is missing.
- extension-lint keyed "has EXT landed?" to extension/package.json — the
same single-filename trap. Key it to a manifest instead, and once a
manifest exists, treat a missing package.json as a hard failure rather
than a green skip.
Mark conformance required now in BRANCH_PROTECTION.md — it is the M0 exit gate.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0143aKiohmDiyefJBwHDJJqw
188 lines
7.0 KiB
YAML
188 lines
7.0 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
# GitHub-hosted runners are Ubuntu 24.04; the project targets 26.04. bootstrap.sh warns
|
|
# but proceeds. Revisit when 26.04 runners exist.
|
|
DEBIAN_FRONTEND: noninteractive
|
|
|
|
jobs:
|
|
# --- fast lint jobs: no compiler, no heavy deps -------------------------------------
|
|
clang-format:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Install clang-format
|
|
run: sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends clang-format
|
|
- name: Check formatting
|
|
run: |
|
|
shopt -s globstar nullglob
|
|
files=(core/**/*.{cpp,hpp} daemon/**/*.{cpp,hpp} cli/**/*.{cpp,hpp} nmhost/**/*.{cpp,hpp})
|
|
if [ ${#files[@]} -eq 0 ]; then echo "no C++ sources yet — skipping"; exit 0; fi
|
|
printf '%s\n' "${files[@]}"
|
|
clang-format --dry-run --Werror "${files[@]}"
|
|
|
|
testserver:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
- name: testserver self-test
|
|
run: python3 tools/testserver/selftest.py
|
|
|
|
bootstrap-script:
|
|
# Keeps tools/bootstrap.sh honest: it must run clean and its --check must pass.
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- run: sudo ./tools/bootstrap.sh --with-clang
|
|
- run: ./tools/bootstrap.sh --check
|
|
|
|
extension-lint:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- id: check
|
|
# "Has EXT landed?" is answered by a manifest, not by extension/package.json:
|
|
# a guard keyed to one filename passes vacuously the day EXT ships the lane
|
|
# under any other name. Skip only when the lane genuinely is not here; once a
|
|
# manifest exists, a missing lint entrypoint is a hard failure, not a skip.
|
|
run: |
|
|
manifest=""
|
|
for m in extension/manifest.json extension/src/manifest.json extension/public/manifest.json; do
|
|
if [ -f "$m" ]; then manifest="$m"; break; fi
|
|
done
|
|
if [ -z "$manifest" ]; then
|
|
echo "extension/ has not landed yet (no manifest.json) — skipping web-ext lint."
|
|
echo "present=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
echo "EXT has landed: $manifest"
|
|
echo "present=true" >> "$GITHUB_OUTPUT"
|
|
if [ ! -f extension/package.json ]; then
|
|
echo "::error::$manifest exists but extension/package.json does not — this job" \
|
|
"cannot lint the extension. Wire web-ext lint in here; do not let the check" \
|
|
"pass green over an unlinted lane."
|
|
exit 1
|
|
fi
|
|
- uses: actions/setup-node@v4
|
|
if: steps.check.outputs.present == 'true'
|
|
with:
|
|
node-version: '22'
|
|
- name: web-ext lint
|
|
if: steps.check.outputs.present == 'true'
|
|
working-directory: extension
|
|
run: |
|
|
npm ci
|
|
npx web-ext lint --source-dir .
|
|
|
|
# --- build + test matrix ----------------------------------------------------------
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
compiler: [gcc, clang]
|
|
env:
|
|
CC: ${{ matrix.compiler == 'gcc' && 'gcc' || 'clang' }}
|
|
CXX: ${{ matrix.compiler == 'gcc' && 'g++' || 'clang++' }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Bootstrap toolchain
|
|
run: sudo ./tools/bootstrap.sh --with-clang
|
|
- name: Configure
|
|
run: cmake --preset ci
|
|
- name: Build
|
|
run: cmake --build --preset ci
|
|
- name: Test
|
|
run: ctest --preset ci --output-on-failure
|
|
|
|
sanitizers:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
preset: [dev, tsan] # dev = ASan + UBSan
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Bootstrap toolchain
|
|
run: sudo ./tools/bootstrap.sh --with-clang
|
|
- name: Configure
|
|
run: cmake --preset ${{ matrix.preset }}
|
|
- name: Build
|
|
run: cmake --build --preset ${{ matrix.preset }}
|
|
- name: Test
|
|
run: ctest --preset ${{ matrix.preset }} --output-on-failure
|
|
env:
|
|
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
|
|
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
|
TSAN_OPTIONS: halt_on_error=1
|
|
|
|
clang-tidy:
|
|
# Advisory through M1 (see .clang-tidy WarningsAsErrors: ''); becomes required at M2.
|
|
runs-on: ubuntu-latest
|
|
continue-on-error: true
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- id: check
|
|
run: |
|
|
if ls core/CMakeLists.txt daemon/CMakeLists.txt >/dev/null 2>&1; then
|
|
echo "present=true" >> "$GITHUB_OUTPUT"
|
|
else echo "present=false" >> "$GITHUB_OUTPUT"; fi
|
|
- name: Bootstrap toolchain
|
|
if: steps.check.outputs.present == 'true'
|
|
run: sudo ./tools/bootstrap.sh
|
|
- name: Configure (for compile_commands.json)
|
|
if: steps.check.outputs.present == 'true'
|
|
run: cmake --preset dev
|
|
- name: Run clang-tidy on changed files
|
|
if: steps.check.outputs.present == 'true'
|
|
run: |
|
|
mapfile -t files < <(git diff --name-only --diff-filter=ACM \
|
|
"${{ github.event.pull_request.base.sha || 'HEAD~1' }}" HEAD \
|
|
-- '*.cpp' '*.hpp' || true)
|
|
[ ${#files[@]} -eq 0 ] && { echo "no C++ changes"; exit 0; }
|
|
printf '%s\n' "${files[@]}"
|
|
clang-tidy -p build/dev "${files[@]}"
|
|
- name: skipped
|
|
if: steps.check.outputs.present == 'false'
|
|
run: echo "no C++ lane has landed a CMakeLists yet — skipping clang-tidy"
|
|
|
|
conformance:
|
|
# The M0 exit gate. Proves the generated C++ daemon surface and the generated TS
|
|
# extension surface agree with contracts/fixtures without either side having run
|
|
# against the other. Required on every PR — branch protection is a repo setting,
|
|
# recorded in .github/BRANCH_PROTECTION.md.
|
|
#
|
|
# The suite ships as tests/conformance/run.sh (its own mockd, its own C++ build).
|
|
# There is no CMakeLists or package.json to guard on, and no ctest label to select;
|
|
# the earlier guard for those was always false, so this job passed running nothing.
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Guard — the suite must be present
|
|
run: |
|
|
if [ ! -x tests/conformance/run.sh ]; then
|
|
echo "::error::tests/conformance/run.sh is missing or not executable. The" \
|
|
"conformance suite is the M0 exit gate and this check must not pass" \
|
|
"without running it. If PROTO moved the entrypoint, update this job."
|
|
exit 1
|
|
fi
|
|
- name: Bootstrap toolchain
|
|
run: sudo ./tools/bootstrap.sh
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22' # apt ships < 20; run.sh's TS runner needs >= 20
|
|
- name: Run conformance suite
|
|
run: ./tests/conformance/run.sh
|