Files
vdm/.github/workflows/ci.yml
T
samiandClaude Sonnet 5 8f45815059 pkg: add CI workflow and branch-protection policy
.github/workflows/ci.yml: fast lint jobs (clang-format, testserver
selftest, bootstrap.sh --check) that need no compiler; a gcc/clcang build
matrix and an ASan/UBSan + TSan sanitizer matrix that bootstrap via
tools/bootstrap.sh and run `ctest --preset {ci,dev,tsan}`; advisory
clang-tidy on changed files; and extension-lint + conformance jobs that
short-circuit to a passing "skipped" step until their lane lands, so they
can be marked required now. CMakePresets.json gains matching `tsan` and
`ci` test presets. .github/BRANCH_PROTECTION.md records the intended
required-checks policy (conformance required = the M0 exit gate).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
2026-09-09 19:22:36 +04:00

167 lines
5.8 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
run: |
if [ -f extension/package.json ]; then echo "present=true" >> "$GITHUB_OUTPUT"
else echo "present=false" >> "$GITHUB_OUTPUT"; fi
- uses: actions/setup-node@v4
if: steps.check.outputs.present == 'true'
with:
node-version: '20'
- name: web-ext lint
if: steps.check.outputs.present == 'true'
working-directory: extension
run: |
npm ci
npx web-ext lint --source-dir .
- name: skipped
if: steps.check.outputs.present == 'false'
run: echo "extension/ has not landed yet — skipping web-ext lint"
# --- 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:
# Required check on every PR once tests/conformance/ lands (branch protection is
# configured in the repo settings, not here — see .github/BRANCH_PROTECTION.md).
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- id: check
run: |
if [ -f tests/conformance/CMakeLists.txt ] || [ -f tests/conformance/package.json ]; 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: Run conformance suite
if: steps.check.outputs.present == 'true'
run: |
cmake --preset dev
ctest --preset dev --output-on-failure -L conformance
- name: skipped
if: steps.check.outputs.present == 'false'
run: echo "tests/conformance/ has not landed yet — skipping"