diff --git a/.gitattributes b/.gitattributes index 46f9462..1db0eec 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ * text=auto *.ps1 text eol=crlf +*.sh text eol=lf *.exe binary *.dll binary *.obj binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4497633 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: ci +on: + pull_request: + branches: [develop] + push: + branches: [develop] + +jobs: + # Linux gate: the same container image and script as tools/ck-asan-docker.sh. + linux-asan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build and test under ASan+UBSan + run: | + docker build -q -t http-cpp-asan -f tools/Dockerfile.asan tools + docker run --rm -v "$GITHUB_WORKSPACE:/src" -w /src http-cpp-asan \ + bash tools/asan-inside.sh + + # Windows native gate: MinGW gcc, warnings-as-errors, ctest. + windows-native: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Locate MinGW + shell: pwsh + run: | + foreach ($dir in @("C:\msys64\mingw64\bin", "C:\mingw64\bin")) { + if ((Test-Path "$dir\g++.exe") -and (Test-Path "$dir\gcc.exe")) { + "MINGW_BIN=$dir" >> $env:GITHUB_ENV + exit 0 + } + } + Write-Error "no MinGW g++ found on runner" + exit 1 + - name: Configure + shell: pwsh + run: | + $gen = if (Get-Command ninja -ErrorAction SilentlyContinue) { "Ninja" } else { "MinGW Makefiles" } + cmake -S . -B build-ci -G $gen -DCMAKE_BUILD_TYPE=Debug ` + -DCMAKE_C_COMPILER="$env:MINGW_BIN\gcc.exe" ` + -DCMAKE_CXX_COMPILER="$env:MINGW_BIN\g++.exe" ` + -DCMAKE_EXE_LINKER_FLAGS=-static + if ($LASTEXITCODE) { exit $LASTEXITCODE } + - name: Build + shell: pwsh + run: cmake --build build-ci + - name: Test + shell: pwsh + run: ctest --test-dir build-ci --output-on-failure diff --git a/tools/asan-inside.sh b/tools/asan-inside.sh new file mode 100644 index 0000000..7ff9ff0 --- /dev/null +++ b/tools/asan-inside.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Runs inside the sanitizer container: full-tree ASan/UBSan build + ctest. +# Used by tools/ck-asan-docker.sh locally and by the ci linux job. +set -euo pipefail +cmake -S . -B /tmp/asan -G Ninja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DHTTP_SERVER_ENABLE_SANITIZERS=ON +cmake --build /tmp/asan -j +export ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 +ctest --test-dir /tmp/asan --output-on-failure diff --git a/tools/ck-asan-docker.sh b/tools/ck-asan-docker.sh index dbab370..31fa84d 100644 --- a/tools/ck-asan-docker.sh +++ b/tools/ck-asan-docker.sh @@ -1,14 +1,13 @@ #!/usr/bin/env bash -# ASan+UBSan gate for the platform-neutral code (http layer) on Linux. -# Docker Desktop must be running. Native MinGW lacks sanitizer runtimes. +# Local Linux gate: builds the container image and runs the full sanitizer +# suite inside it (the same commands the ci linux job runs). +# Run from git-bash. The build happens in a container copy, not your tree. set -euo pipefail -cd "$(dirname "$0")/.." -docker build -q -t http-cpp-asan -f tools/Dockerfile.asan tools >/dev/null -# MSYS guards: stop git-bash from rewriting the container-side /src paths. -MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' docker run --rm -v "$PWD:/src" -w /src http-cpp-asan bash -c ' - set -euo pipefail - cmake -S . -B /tmp/asan -G Ninja \ - -DCMAKE_BUILD_TYPE=Debug -DHTTP_SERVER_ENABLE_SANITIZERS=ON - cmake --build /tmp/asan -j - ASAN_OPTIONS=detect_leaks=1 /tmp/asan/unit_tests | tail -3 -' +cd "$(git rev-parse --show-toplevel)" +case "$(uname -s)" in MINGW*|MSYS*|CYGWIN*) docker_bin=docker.exe;; *) docker_bin=docker;; esac +command -v "$docker_bin" >/dev/null 2>&1 || { echo "docker not found" >&2; exit 127; } +"$docker_bin" build -q -t http-cpp-asan -f tools/Dockerfile.asan tools >/dev/null +# git-bash mangles POSIX-looking docker args; give docker a Windows source path +# and disable conversion for the container-side /src. +if [ -n "${MSYSTEM:-}" ]; then src="$(pwd -W)"; else src="$PWD"; fi +MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' "$docker_bin" run --rm -v "$src:/src" -w /src http-cpp-asan bash tools/asan-inside.sh