CI #303
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # libdb continuous integration. | |
| # | |
| # Builds the living fork (master) and PRs across as many of the platforms, | |
| # compilers, and configure options that Berkeley DB and GitHub-hosted runners | |
| # both support. Experimental/best-effort jobs are marked continue-on-error so | |
| # they inform without gating. | |
| name: CI | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| schedule: | |
| # Nightly (03:17 UTC) exercises the full TCL suite via the tcl-tests job | |
| # below; the heavy scheduled-only jobs live in ci-extended.yml. | |
| - cron: '17 3 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| full_tcl: | |
| description: 'Run the full TCL regression suite (long)' | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| # ---------------------------------------------------------------------------- | |
| # POSIX builds: Linux + macOS, gcc + clang, across configure variants. | |
| # ---------------------------------------------------------------------------- | |
| posix: | |
| name: ${{ matrix.os }} ${{ matrix.cc }} ${{ matrix.config }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, ubuntu-22.04, macos-latest, macos-14] | |
| cc: [gcc, clang] | |
| config: [default, debug, cxx, sql, no-crypto, smallbuild] | |
| exclude: | |
| # Reduce fan-out: only exercise the full config set on ubuntu-latest. | |
| - { os: ubuntu-22.04, config: cxx } | |
| - { os: ubuntu-22.04, config: sql } | |
| - { os: ubuntu-22.04, config: no-crypto } | |
| - { os: ubuntu-22.04, config: smallbuild } | |
| - { os: macos-14, config: cxx } | |
| - { os: macos-14, config: sql } | |
| - { os: macos-14, config: no-crypto } | |
| - { os: macos-14, config: smallbuild } | |
| # BDB's C++ headers don't compile against Xcode's libc++ <atomic>. | |
| - { os: macos-latest, config: cxx } | |
| env: | |
| CC: ${{ matrix.cc }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Map config to configure flags | |
| id: cfg | |
| run: | | |
| case "${{ matrix.config }}" in | |
| default) flags="" ;; | |
| debug) flags="--enable-debug --enable-diagnostic" ;; | |
| cxx) flags="--enable-cxx" ;; | |
| sql) flags="--enable-sql" ;; | |
| no-crypto) flags="--disable-cryptography" ;; | |
| smallbuild) flags="--enable-smallbuild" ;; | |
| esac | |
| echo "flags=$flags" >> "$GITHUB_OUTPUT" | |
| - name: Configure | |
| working-directory: build_unix | |
| run: ../dist/configure ${{ steps.cfg.outputs.flags }} | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) | |
| - name: Smoke test (C API) | |
| working-directory: build_unix | |
| run: | | |
| # ex_access exercises open/put/get/cursor on a btree. | |
| make ex_access 2>/dev/null || true | |
| ls -l libdb-*.a 2>/dev/null || ls -l .libs/libdb-*.* 2>/dev/null || true | |
| # ---------------------------------------------------------------------------- | |
| # 32-bit build on Linux (pointer-size / portability coverage). | |
| # ---------------------------------------------------------------------------- | |
| linux-32bit: | |
| name: ubuntu 32-bit | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install 32-bit toolchain | |
| run: | | |
| sudo dpkg --add-architecture i386 | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-multilib g++-multilib | |
| - name: Configure (32-bit) | |
| working-directory: build_unix | |
| run: ../dist/configure --build=i686-pc-linux-gnu --with-mutex=POSIX/pthreads "CFLAGS=-m32" "LDFLAGS=-m32" | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(nproc) | |
| # ---------------------------------------------------------------------------- | |
| # AddressSanitizer / UBSan build + smoke (catches memory/UB regressions). | |
| # ---------------------------------------------------------------------------- | |
| sanitizers: | |
| name: clang asan+ubsan | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| env: | |
| CC: clang | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Configure (sanitizers) | |
| working-directory: build_unix | |
| run: ../dist/configure --enable-debug "CFLAGS=-fsanitize=address,undefined -fno-omit-frame-pointer -g" | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(nproc) | |
| # ---------------------------------------------------------------------------- | |
| # ThreadSanitizer build + concurrency SMOKE (SSI / lock / mutex TCL subset). | |
| # Critical for the ongoing SSI/MVCC/atomics work; best-effort so it informs | |
| # without gating. NOT the full suite -- TSan slowdown would time out. | |
| # ---------------------------------------------------------------------------- | |
| tsan: | |
| name: clang tsan (concurrency smoke) | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| env: | |
| CC: clang | |
| # halt_on_error keeps a clean failure signal; second_deadlock_stack aids | |
| # triage of any lock-order report from the SSI paths. | |
| TSAN_OPTIONS: halt_on_error=1:second_deadlock_stack=1 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Tcl | |
| run: sudo apt-get update && sudo apt-get install -y tcl-dev tcl | |
| - name: Configure (tsan + test + tcl) | |
| working-directory: build_unix | |
| run: > | |
| ../dist/configure --enable-debug --enable-test --with-tcl=/usr/lib/tcl8.6 | |
| "CFLAGS=-fsanitize=thread -fno-omit-frame-pointer -g" | |
| "LDFLAGS=-fsanitize=thread" | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(nproc) | |
| - name: Concurrency smoke subset | |
| working-directory: build_unix | |
| run: | | |
| cat > /tmp/tsan.tcl <<'TCL' | |
| source ../test/tcl/test.tcl | |
| foreach t {mut001 lock001 lock002 ssi001 ssi002 ssi009} { | |
| source ../test/tcl/$t.tcl | |
| if {[catch {eval $t} res]} { puts "FAIL $t: $res"; exit 1 } | |
| puts "PASS $t" | |
| } | |
| TCL | |
| # Generous per-test slowdown under TSan, but bounded so a hang fails | |
| # loudly instead of eating the whole runner budget. | |
| timeout 1800 tclsh /tmp/tsan.tcl 2>&1 | tee /tmp/tsan.out | |
| ! grep -qE "^FAIL|data race|WARNING: ThreadSanitizer" /tmp/tsan.out | |
| # ---------------------------------------------------------------------------- | |
| # Compiler-warnings gate: -Wall -Wextra with gcc + clang. Advisory | |
| # (continue-on-error) and NOT -Werror -- this is pre-2000 K&R-era C and the | |
| # autoconf build already suppresses two whole warning classes | |
| # (-Wno-deprecated-non-prototype / -Wno-knr-promoted-parameter). We surface | |
| # the count so new warnings in touched code are visible without blocking PRs. | |
| # ---------------------------------------------------------------------------- | |
| warnings: | |
| name: warnings gate ${{ matrix.cc }} | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| cc: [gcc, clang] | |
| env: | |
| CC: ${{ matrix.cc }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Configure (-Wall -Wextra) | |
| working-directory: build_unix | |
| run: ../dist/configure --enable-debug "CFLAGS=-Wall -Wextra -g -O1" | |
| - name: Build and count warnings | |
| working-directory: build_unix | |
| run: | | |
| set -o pipefail | |
| make -j$(nproc) 2>&1 | tee /tmp/build.log | |
| n=$(grep -c 'warning:' /tmp/build.log || true) | |
| echo "::notice title=Compiler warnings (${{ matrix.cc }})::$n warning line(s)" | |
| echo "Top warning kinds:" | |
| grep 'warning:' /tmp/build.log \ | |
| | grep -oE '\-W[a-z0-9-]+' | sort | uniq -c | sort -rn | head -20 || true | |
| # ---------------------------------------------------------------------------- | |
| # Mutex backend variants (Linux only). --with-mutex overrides autodetection, | |
| # so each entry forces a genuinely different mutex implementation: | |
| # POSIX/pthreads -> HAVE_MUTEX_PTHREADS (blocking pthread mutexes) | |
| # POSIX/pthreads/library -> same, linked explicitly against -lpthread | |
| # x86_64/gcc-assembly -> HAVE_MUTEX_X86_64_GCC_ASSEMBLY (test-and-set) | |
| # posix-forced uses --enable-posixmutexes (intra-process pthread fast path). | |
| # All names verified against dist/aclocal/mutex.m4 + a local configure run. | |
| # ---------------------------------------------------------------------------- | |
| mutex-backends: | |
| name: mutex ${{ matrix.name }} | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { name: pthreads, flags: '--with-mutex=POSIX/pthreads' } | |
| - { name: pthreads-library, flags: '--with-mutex=POSIX/pthreads/library' } | |
| - { name: tas-x86_64, flags: '--with-mutex=x86_64/gcc-assembly' } | |
| - { name: posix-forced, flags: '--enable-posixmutexes' } | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Configure (${{ matrix.name }}) | |
| working-directory: build_unix | |
| run: ../dist/configure --enable-debug ${{ matrix.flags }} | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(nproc) | |
| - name: Smoke (build ex_access) | |
| working-directory: build_unix | |
| run: make ex_access 2>/dev/null || true | |
| # ---------------------------------------------------------------------------- | |
| # TCL test suite: targeted subset on every push/PR (fast PR signal); the full | |
| # run is manual (workflow_dispatch full_tcl=true). The generous nightly full | |
| # suite lives in ci-extended.yml so it never gates PRs. | |
| # ---------------------------------------------------------------------------- | |
| tcl-tests: | |
| name: tcl tests (${{ github.event.inputs.full_tcl == 'true' && 'full' || 'targeted' }}) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Tcl | |
| run: sudo apt-get update && sudo apt-get install -y tcl-dev tcl | |
| - name: Configure (test + tcl) | |
| working-directory: build_unix | |
| run: ../dist/configure --enable-debug --enable-test --with-tcl=/usr/lib/tcl8.6 | |
| - name: Build | |
| working-directory: build_unix | |
| run: make -j$(nproc) | |
| - name: Run tests | |
| working-directory: build_unix | |
| run: | | |
| if [ "${{ github.event.inputs.full_tcl }}" = "true" ]; then | |
| cat > /tmp/run.tcl <<'TCL' | |
| source ../test/tcl/test.tcl | |
| run_std | |
| TCL | |
| else | |
| cat > /tmp/run.tcl <<'TCL' | |
| source ../test/tcl/test.tcl | |
| foreach t {lock001 txn001 test001 ssi001 ssi002} { | |
| source ../test/tcl/$t.tcl | |
| set a {} | |
| if {$t eq "test001"} { set a btree } | |
| if {[catch {eval $t $a} res]} { puts "FAIL $t: $res"; exit 1 } | |
| puts "PASS $t" | |
| } | |
| TCL | |
| fi | |
| timeout 3600 tclsh /tmp/run.tcl 2>&1 | tee /tmp/out.txt | |
| ! grep -qE "^FAIL|FAIL:" /tmp/out.txt | |
| # ---------------------------------------------------------------------------- | |
| # Deterministic Simulation Testing (DST): build --enable-dst, run one capstone | |
| # per fault class + the multi-process failchk pilot, and enforce the | |
| # zero-overhead-when-off gate (an --enable-dst-off build must contain 0 | |
| # __db_sim_* symbols). The full 41-scenario sweep + planted-bug harness is a | |
| # local/nightly concern; this is the fast per-push regression signal that the | |
| # DST layer still builds, runs, and stays compiled-out in production builds. | |
| # ---------------------------------------------------------------------------- | |
| dst: | |
| name: dst (fault-class smoke + off-build gate) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Off-build zero-symbol gate | |
| working-directory: build_unix | |
| run: | | |
| # A normal (--enable-dst absent) debug build must compile the DST | |
| # hooks and every planted-bug/buggify site out entirely. | |
| ../dist/configure --enable-debug | |
| make -j$(nproc) libdb.a | |
| n=$(nm .libs/*.o 2>/dev/null | grep -c '__db_sim_' || true) | |
| echo "OFF-build __db_sim_* symbols: $n" | |
| test "$n" -eq 0 || { echo 'FAIL: DST symbols leaked into a non-DST build'; exit 1; } | |
| make realclean >/dev/null 2>&1 || make clean >/dev/null 2>&1 | |
| - name: Configure + build (--enable-dst) | |
| working-directory: build_unix | |
| run: | | |
| ../dist/configure --enable-debug --enable-dst | |
| make -j$(nproc) | |
| - name: Fault-class smoke (one capstone per class) | |
| working-directory: build_unix | |
| run: | | |
| set -e | |
| for t in test_sim_crash_recover test_sim_crash_in_recovery \ | |
| test_sim_clockskew_backward test_sim_buggify \ | |
| test_sim_torn test_sim_stale test_sim_enospc; do | |
| make "$t" | |
| echo "--- $t ---" | |
| timeout 240 "./$t" | |
| done | |
| # The multi-process failchk pilot spawns + kill -9's real processes | |
| # sharing a real region. That is inherently timing-sensitive on shared | |
| # CI runners (a survivor can stall waiting on a dead peer's slot), so it | |
| # is best-effort here -- the authoritative sweep runs locally/nightly. | |
| # We still BUILD it every push (a compile break is a hard signal) and | |
| # smoke ONE seed with a tight timeout so a hang informs without gating. | |
| - name: Multi-process failchk pilot (build + 1-seed smoke, best-effort) | |
| continue-on-error: true | |
| working-directory: build_unix | |
| run: | | |
| make mp_failchk_pilot | |
| SEEDS=0x1 timeout 90 bash ../test/sim/mp-failchk.sh || \ | |
| echo '::warning title=mp-failchk::pilot smoke did not pass cleanly on this runner (best-effort; run locally for the authoritative sweep)' | |
| # ---------------------------------------------------------------------------- | |
| # Windows build via the bundled Visual Studio solution (best-effort). | |
| # ---------------------------------------------------------------------------- | |
| windows: | |
| name: windows msbuild | |
| runs-on: windows-latest | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: microsoft/setup-msbuild@v2 | |
| - name: Build Berkeley DB library | |
| shell: cmd | |
| working-directory: build_windows | |
| # Use the VS2010 (.vcxproj) solution -- the legacy Berkeley_DB.sln uses | |
| # VS2008 .vcproj files MSBuild can no longer load (MSB4025). Build only | |
| # the `db` library project and retarget to the runner's toolset/SDK. | |
| run: msbuild Berkeley_DB_vs2010.sln /m /t:db /p:Configuration=Release /p:Platform=x64 /p:PlatformToolset=v143 /p:WindowsTargetPlatformVersion=10.0 | |
| # ---------------------------------------------------------------------------- | |
| # Meson/Ninja build of the core library (parallel build system). | |
| # ---------------------------------------------------------------------------- | |
| meson: | |
| name: meson/ninja ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install Meson + Ninja | |
| run: python -m pip install --upgrade meson ninja | |
| - name: Configure (Ninja backend) | |
| run: meson setup build-meson | |
| - name: Build | |
| run: ninja -C build-meson | |
| - name: Smoke test (link + db_version) | |
| run: | | |
| cat > /tmp/smoke.c <<'EOF' | |
| #include <stdio.h> | |
| #include "db.h" | |
| int main(void){int a,b,c;char *s=db_version(&a,&b,&c); | |
| printf("libdb %s (%d.%d.%d)\n",s,a,b,c);return 0;} | |
| EOF | |
| cc /tmp/smoke.c -Ibuild-meson/dist -Lbuild-meson/dist -ldb -o /tmp/smoke | |
| if [ "$RUNNER_OS" = "macOS" ]; then export DYLD_LIBRARY_PATH=build-meson/dist; else export LD_LIBRARY_PATH=build-meson/dist; fi | |
| /tmp/smoke | |
| # ---------------------------------------------------------------------------- | |
| # Nix flake: build the default package via `nix build`. | |
| # ---------------------------------------------------------------------------- | |
| nix-flake: | |
| name: nix flake build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Nix (flakes enabled) | |
| uses: cachix/install-nix-action@v27 | |
| with: | |
| extra_nix_config: | | |
| experimental-features = nix-command flakes | |
| - name: Build the flake's default package | |
| run: nix build .#libdb-meson --print-build-logs | |
| - name: Show result | |
| run: ls -l result/lib |