Windows workflow fixup #18
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
| name: CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| release: | |
| types: [ published ] | |
| env: | |
| CONAN_USER_HOME: "${{ github.workspace }}/conan-cache" | |
| jobs: | |
| # ============================================================================ | |
| # Linux x64 - GCC 13 | |
| # ============================================================================ | |
| linux-gcc: | |
| name: "Linux GCC 13 (x64)" | |
| runs-on: ubuntu-22.04 | |
| strategy: | |
| matrix: | |
| build_type: [Debug, Release] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt update | |
| sudo apt install -y build-essential cmake python3-pip git clang-format | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip3 install --user conan | |
| echo "$HOME/.local/bin" >> $GITHUB_PATH | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Update to use the correct GCC version and C++23 | |
| if command -v gcc-13 >/dev/null 2>&1; then | |
| GCC_VERSION=$(gcc-13 --version | head -n1 | sed -n 's/.*[^0-9]\([0-9]\+\)\.[0-9]\+\.[0-9]\+.*/\1/p') | |
| else | |
| GCC_VERSION=$(gcc --version | head -n1 | sed -n 's/.*[^0-9]\([0-9]\+\)\.[0-9]\+\.[0-9]\+.*/\1/p') | |
| fi | |
| echo "Detected GCC version: $GCC_VERSION" | |
| if [ -n "$GCC_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$GCC_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect GCC version, using Conan default" | |
| fi | |
| sed -i 's/compiler.cppstd=gnu17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/os=.*/os=Linux/' ~/.conan2/profiles/default | |
| echo "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-linux-gcc-${{ matrix.build_type }}-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-linux-gcc-${{ matrix.build_type }}- | |
| conan-linux-gcc- | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Linux -s build_type=${{ matrix.build_type }} --output-folder=build --build=missing -o with_gperftools=True | |
| - name: Configure CMake | |
| run: | | |
| export CC=gcc | |
| export CXX=g++ | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cmake --preset conan-debug | |
| else | |
| cmake --preset conan-release | |
| fi | |
| - name: Build | |
| run: | | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cmake --build --preset conan-debug --parallel | |
| else | |
| cmake --build --preset conan-release --parallel | |
| fi | |
| - name: Test | |
| run: | | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cd build/Debug | |
| ./utf_strings-tests --gtest_output=xml:test_results_gcc_debug.xml | |
| else | |
| cd build/build | |
| ./utf_strings-tests --gtest_output=xml:test_results_gcc_release.xml | |
| fi | |
| - name: Benchmark (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: | | |
| cd build/build | |
| ./utf_strings-bench --benchmark_min_time=0.1s --benchmark_format=json --benchmark_out=benchmark_results_gcc.json | |
| - name: Check code formatting (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: cmake --build --preset conan-release --target format-check | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-results-linux-gcc-${{ matrix.build_type }} | |
| path: | | |
| build/Debug/test_results_gcc_debug.xml | |
| build/build/test_results_gcc_release.xml | |
| build/build/benchmark_results_gcc.json | |
| # ============================================================================ | |
| # Linux x64 - Clang 18 | |
| # ============================================================================ | |
| linux-clang: | |
| name: "Linux Clang 18 (x64)" | |
| runs-on: ubuntu-22.04 | |
| strategy: | |
| matrix: | |
| build_type: [Debug, Release] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| timeout-minutes: 15 | |
| run: | | |
| set -e # Exit on any error | |
| # Update package list first | |
| sudo apt update | |
| # Install basic dependencies first (these are fast and reliable) | |
| sudo apt install -y cmake python3-pip git wget curl | |
| # Install Clang 18 with timeout and retry logic | |
| echo "Installing Clang 18..." | |
| for i in {1..3}; do | |
| if timeout 10m bash -c " | |
| wget -q https://apt.llvm.org/llvm.sh && | |
| chmod +x llvm.sh && | |
| sudo ./llvm.sh 18 | |
| "; then | |
| echo "LLVM installation successful on attempt $i" | |
| break | |
| else | |
| echo "LLVM installation attempt $i failed, retrying..." | |
| rm -f llvm.sh | |
| if [ $i -eq 3 ]; then | |
| echo "All LLVM installation attempts failed" | |
| exit 1 | |
| fi | |
| sleep 30 | |
| fi | |
| done | |
| # Install additional tools | |
| sudo apt install -y clang-format-18 || { | |
| echo "clang-format-18 not available, trying alternatives..." | |
| sudo apt install -y clang-format || echo "clang-format installation failed" | |
| } | |
| # Set up symlinks | |
| sudo ln -sf /usr/bin/clang-18 /usr/bin/clang | |
| sudo ln -sf /usr/bin/clang++-18 /usr/bin/clang++ | |
| if command -v clang-format-18 >/dev/null 2>&1; then | |
| sudo ln -sf /usr/bin/clang-format-18 /usr/bin/clang-format | |
| fi | |
| # Verify installation | |
| clang --version | |
| clang++ --version | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip3 install --user conan | |
| echo "$HOME/.local/bin" >> $GITHUB_PATH | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Update to use the correct Clang version and C++23 | |
| if command -v clang-18 >/dev/null 2>&1; then | |
| CLANG_VERSION=$(clang-18 --version | head -n1 | sed -n 's/.*clang version \([0-9]\+\).*/\1/p') | |
| else | |
| CLANG_VERSION=$(clang --version | head -n1 | sed -n 's/.*clang version \([0-9]\+\).*/\1/p') | |
| fi | |
| echo "Detected Clang version: $CLANG_VERSION" | |
| sed -i 's/compiler=gcc/compiler=clang/' ~/.conan2/profiles/default | |
| if [ -n "$CLANG_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$CLANG_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect Clang version, using Conan default" | |
| fi | |
| sed -i 's/compiler.libcxx=libstdc++11/compiler.libcxx=libstdc++11/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=gnu17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/os=.*/os=Linux/' ~/.conan2/profiles/default | |
| echo "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-linux-clang-${{ matrix.build_type }}-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-linux-clang-${{ matrix.build_type }}- | |
| conan-linux-clang- | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Linux -s build_type=${{ matrix.build_type }} --output-folder=build --build=missing -o with_gperftools=True | |
| - name: Configure CMake | |
| run: | | |
| export CC=clang | |
| export CXX=clang++ | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cmake --preset conan-debug | |
| else | |
| cmake --preset conan-release | |
| fi | |
| - name: Build | |
| run: | | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cmake --build --preset conan-debug --parallel | |
| else | |
| cmake --build --preset conan-release --parallel | |
| fi | |
| - name: Test | |
| run: | | |
| if [[ "${{ matrix.build_type }}" == "Debug" ]]; then | |
| cd build/Debug | |
| ./utf_strings-tests --gtest_output=xml:test_results_clang_debug.xml | |
| else | |
| cd build/build | |
| ./utf_strings-tests --gtest_output=xml:test_results_clang_release.xml | |
| fi | |
| - name: Benchmark (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: | | |
| cd build/build | |
| ./utf_strings-bench --benchmark_min_time=0.1s --benchmark_format=json --benchmark_out=benchmark_results_clang.json | |
| - name: Check code formatting (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: cmake --build --preset conan-release --target format-check | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-results-linux-clang-${{ matrix.build_type }} | |
| path: | | |
| build/Debug/test_results_clang_debug.xml | |
| build/build/test_results_clang_release.xml | |
| build/build/benchmark_results_clang.json | |
| # ============================================================================ | |
| # Linux x64 - Clang with Fuzz Testing | |
| # ============================================================================ | |
| linux-clang-fuzz: | |
| name: "Linux Clang Fuzz Testing (x64)" | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| timeout-minutes: 15 | |
| run: | | |
| set -e # Exit on any error | |
| # Update package list first | |
| sudo apt update | |
| # Install basic dependencies first (these are fast and reliable) | |
| sudo apt install -y cmake python3-pip git wget curl | |
| # Install Clang 18 with timeout and retry logic | |
| echo "Installing Clang 18..." | |
| for i in {1..3}; do | |
| if timeout 10m bash -c " | |
| wget -q https://apt.llvm.org/llvm.sh && | |
| chmod +x llvm.sh && | |
| sudo ./llvm.sh 18 | |
| "; then | |
| echo "LLVM installation successful on attempt $i" | |
| break | |
| else | |
| echo "LLVM installation attempt $i failed, retrying..." | |
| rm -f llvm.sh | |
| if [ $i -eq 3 ]; then | |
| echo "All LLVM installation attempts failed" | |
| exit 1 | |
| fi | |
| sleep 30 | |
| fi | |
| done | |
| # Install additional tools | |
| sudo apt install -y clang-format-18 || { | |
| echo "clang-format-18 not available, trying alternatives..." | |
| sudo apt install -y clang-format || echo "clang-format installation failed" | |
| } | |
| # Set up symlinks | |
| sudo ln -sf /usr/bin/clang-18 /usr/bin/clang | |
| sudo ln -sf /usr/bin/clang++-18 /usr/bin/clang++ | |
| if command -v clang-format-18 >/dev/null 2>&1; then | |
| sudo ln -sf /usr/bin/clang-format-18 /usr/bin/clang-format | |
| fi | |
| # Verify installation | |
| clang --version | |
| clang++ --version | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip3 install --user conan | |
| echo "$HOME/.local/bin" >> $GITHUB_PATH | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Determine compiler and version | |
| if command -v gcc-13 >/dev/null 2>&1; then | |
| GCC_VERSION=$(gcc-13 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using GCC-13 version: $GCC_VERSION" | |
| if [ -n "$GCC_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$GCC_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect GCC version, using Conan default" | |
| fi | |
| elif command -v clang-18 >/dev/null 2>&1; then | |
| CLANG_VERSION=$(clang-18 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using Clang-18 version: $CLANG_VERSION" | |
| sed -i 's/compiler=gcc/compiler=clang/' ~/.conan2/profiles/default | |
| if [ -n "$CLANG_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$CLANG_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect Clang version, using Conan default" | |
| fi | |
| sed -i 's/compiler.libcxx=libstdc++11/compiler.libcxx=libstdc++11/' ~/.conan2/profiles/default | |
| else | |
| COMPILER_VERSION=$(gcc --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1 || clang --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using default compiler version: $COMPILER_VERSION" | |
| if [ -n "$COMPILER_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$COMPILER_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect compiler version, using Conan default" | |
| fi | |
| fi | |
| sed -i 's/os=.*/os=Linux/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=gnu17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| echo "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-linux-clang-fuzz-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-linux-clang-fuzz- | |
| conan-linux-clang- | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Linux -s build_type=Debug --output-folder=build --build=missing -o with_gperftools=True | |
| - name: Configure CMake with Fuzz Testing | |
| run: | | |
| export CC=clang | |
| export CXX=clang++ | |
| cmake -S . -B build/Fuzz \ | |
| -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \ | |
| -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DUTF_STRINGS_BUILD_TESTS=OFF \ | |
| -DUTF_STRINGS_BUILD_BENCHMARKS=OFF \ | |
| -DUTF_STRINGS_BUILD_FUZZ_TESTS=ON \ | |
| -DUTF_STRINGS_WITH_GPERFTOOLS=OFF | |
| - name: Build Fuzz Targets | |
| run: cmake --build build/Fuzz --parallel | |
| - name: Run Fuzz Tests (Short Duration for CI) | |
| run: | | |
| cd build/Fuzz | |
| echo "Running UTF-8 fuzz tests..." | |
| timeout 60s ./fuzz_utf8 -max_total_time=30 -print_final_stats=1 || true | |
| echo "Running UTF-16 BE fuzz tests..." | |
| timeout 60s ./fuzz_utf16_be -max_total_time=30 -print_final_stats=1 || true | |
| echo "Running UTF-16 LE fuzz tests..." | |
| timeout 60s ./fuzz_utf16_le -max_total_time=30 -print_final_stats=1 || true | |
| echo "Running UTF-32 BE fuzz tests..." | |
| timeout 60s ./fuzz_utf32_be -max_total_time=30 -print_final_stats=1 || true | |
| echo "Running UTF-32 LE fuzz tests..." | |
| timeout 60s ./fuzz_utf32_le -max_total_time=30 -print_final_stats=1 || true | |
| - name: Upload fuzz artifacts | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: fuzz-results-linux-clang | |
| path: | | |
| build/Fuzz/*.log | |
| build/Fuzz/crash-* | |
| build/Fuzz/leak-* | |
| build/Fuzz/timeout-* | |
| # ============================================================================ | |
| # Linux x64 - Sanitizer Testing (GCC & Clang) | |
| # ============================================================================ | |
| linux-sanitizers: | |
| name: "Linux Sanitizer Testing (x64)" | |
| runs-on: ubuntu-22.04 | |
| strategy: | |
| matrix: | |
| sanitizer: [asan, tsan] | |
| compiler: [gcc, clang] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| timeout-minutes: 15 | |
| run: | | |
| set -e # Exit on any error | |
| # Update package list first | |
| sudo apt update | |
| # Install basic dependencies first | |
| sudo apt install -y build-essential cmake python3-pip git wget curl | |
| # Install Clang 18 if needed, with retry logic | |
| if [ "${{ matrix.compiler }}" = "clang" ]; then | |
| echo "Installing Clang 18..." | |
| for i in {1..3}; do | |
| if timeout 10m bash -c " | |
| wget -q https://apt.llvm.org/llvm.sh && | |
| chmod +x llvm.sh && | |
| sudo ./llvm.sh 18 | |
| "; then | |
| echo "LLVM installation successful on attempt $i" | |
| sudo ln -sf /usr/bin/clang-18 /usr/bin/clang | |
| sudo ln -sf /usr/bin/clang++-18 /usr/bin/clang++ | |
| break | |
| else | |
| echo "LLVM installation attempt $i failed, retrying..." | |
| rm -f llvm.sh | |
| if [ $i -eq 3 ]; then | |
| echo "All LLVM installation attempts failed" | |
| exit 1 | |
| fi | |
| sleep 30 | |
| fi | |
| done | |
| # Verify Clang installation | |
| clang --version | |
| clang++ --version | |
| fi | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip3 install --user conan | |
| echo "$HOME/.local/bin" >> $GITHUB_PATH | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Determine compiler and version | |
| if command -v gcc-13 >/dev/null 2>&1; then | |
| GCC_VERSION=$(gcc-13 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using GCC-13 version: $GCC_VERSION" | |
| if [ -n "$GCC_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$GCC_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect GCC version, using Conan default" | |
| fi | |
| elif command -v clang-18 >/dev/null 2>&1; then | |
| CLANG_VERSION=$(clang-18 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using Clang-18 version: $CLANG_VERSION" | |
| sed -i 's/compiler=gcc/compiler=clang/' ~/.conan2/profiles/default | |
| if [ -n "$CLANG_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$CLANG_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect Clang version, using Conan default" | |
| fi | |
| sed -i 's/compiler.libcxx=libstdc++11/compiler.libcxx=libstdc++11/' ~/.conan2/profiles/default | |
| else | |
| COMPILER_VERSION=$(gcc --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1 || clang --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using default compiler version: $COMPILER_VERSION" | |
| if [ -n "$COMPILER_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$COMPILER_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect compiler version, using Conan default" | |
| fi | |
| fi | |
| sed -i 's/os=.*/os=Linux/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=gnu17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| echo "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-linux-${{ matrix.compiler }}-${{ matrix.sanitizer }}-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-linux-${{ matrix.compiler }}-${{ matrix.sanitizer }}- | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Linux -s build_type=Debug --output-folder=build --build=missing -o with_gperftools=True | |
| - name: Configure CMake with Sanitizers | |
| run: | | |
| if [ "${{ matrix.compiler }}" = "clang" ]; then | |
| export CC=clang | |
| export CXX=clang++ | |
| else | |
| export CC=gcc | |
| export CXX=g++ | |
| fi | |
| if [ "${{ matrix.sanitizer }}" = "asan" ]; then | |
| cmake --preset conan-debug -DUTF_STRINGS_ENABLE_SANITIZERS=ON | |
| else | |
| cmake --preset conan-debug -DUTF_STRINGS_ENABLE_THREAD_SANITIZER=ON | |
| fi | |
| - name: Build with Sanitizers | |
| run: cmake --build --preset conan-debug --parallel | |
| - name: Test with Sanitizers | |
| run: | | |
| cd build/Debug | |
| ./utf_strings-tests --gtest_output=xml:test_results_${{ matrix.compiler }}_${{ matrix.sanitizer }}.xml | |
| - name: Upload sanitizer results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: sanitizer-results-${{ matrix.compiler }}-${{ matrix.sanitizer }} | |
| path: build/Debug/test_results_${{ matrix.compiler }}_${{ matrix.sanitizer }}.xml | |
| # ============================================================================ | |
| # Windows x64 - MSVC 2022 | |
| # ============================================================================ | |
| windows-msvc: | |
| name: "Windows MSVC 2022 (x64)" | |
| runs-on: windows-2022 | |
| strategy: | |
| matrix: | |
| build_type: [Debug, Release] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip install conan | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Configure for Windows MSVC and C++23 | |
| # Update C++ standard and OS for Windows | |
| $profile = "$env:USERPROFILE\.conan2\profiles\default" | |
| (Get-Content $profile) -replace 'compiler\.cppstd=.*', 'compiler.cppstd=23' | Set-Content $profile | |
| (Get-Content $profile) -replace 'os=.*', 'os=Windows' | Set-Content $profile | |
| Write-Host "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| shell: pwsh | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-windows-msvc-${{ matrix.build_type }}-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-windows-msvc-${{ matrix.build_type }}- | |
| conan-windows-msvc- | |
| - name: Install LLVM (for clang-format) | |
| run: | | |
| choco install llvm -y | |
| - name: Setup MSVC environment | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Windows -s build_type=${{ matrix.build_type }} --output-folder=build --build=missing -o with_gperftools=False | |
| - name: Configure CMake | |
| run: | | |
| if ("${{ matrix.build_type }}" -eq "Debug") { | |
| cmake --preset conan-debug -DCMAKE_GENERATOR_PLATFORM=x64 | |
| } else { | |
| cmake --preset conan-release -DCMAKE_GENERATOR_PLATFORM=x64 | |
| } | |
| - name: Build | |
| run: | | |
| if ("${{ matrix.build_type }}" -eq "Debug") { | |
| cmake --build --preset conan-debug --parallel | |
| } else { | |
| cmake --build --preset conan-release --parallel | |
| } | |
| - name: Test | |
| run: | | |
| if ("${{ matrix.build_type }}" -eq "Debug") { | |
| cd build\Debug | |
| .\utf_strings-tests.exe --gtest_output=xml:test_results_msvc_debug.xml | |
| } else { | |
| cd build\build | |
| .\utf_strings-tests.exe --gtest_output=xml:test_results_msvc_release.xml | |
| } | |
| - name: Benchmark (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: | | |
| cd build\build | |
| .\utf_strings-bench.exe --benchmark_min_time=0.1s --benchmark_format=json --benchmark_out=benchmark_results_msvc.json | |
| - name: Check code formatting (Release only) | |
| if: matrix.build_type == 'Release' | |
| run: | | |
| $env:PATH = "C:\Program Files\LLVM\bin;$env:PATH" | |
| cmake --build --preset conan-release --target format-check | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-results-windows-msvc-${{ matrix.build_type }} | |
| path: | | |
| build\Debug\test_results_msvc_debug.xml | |
| build\build\test_results_msvc_release.xml | |
| build\build\benchmark_results_msvc.json | |
| # ============================================================================ | |
| # Windows - MSVC with AddressSanitizer | |
| # ============================================================================ | |
| windows-msvc-sanitizer: | |
| name: "Windows MSVC AddressSanitizer (x64)" | |
| runs-on: windows-2022 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip install conan | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Configure for Windows MSVC and C++23 | |
| # Update C++ standard and OS for Windows | |
| $profile = "$env:USERPROFILE\.conan2\profiles\default" | |
| (Get-Content $profile) -replace 'compiler\.cppstd=.*', 'compiler.cppstd=23' | Set-Content $profile | |
| (Get-Content $profile) -replace 'os=.*', 'os=Windows' | Set-Content $profile | |
| Write-Host "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| shell: pwsh | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-windows-msvc-asan-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-windows-msvc-asan- | |
| conan-windows-msvc- | |
| - name: Setup MSVC environment | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Windows -s build_type=Debug --output-folder=build --build=missing -o with_gperftools=False | |
| - name: Configure CMake with AddressSanitizer | |
| run: | | |
| cmake --preset conan-debug -DCMAKE_GENERATOR_PLATFORM=x64 -DUTF_STRINGS_ENABLE_SANITIZERS=ON | |
| - name: Build with AddressSanitizer | |
| run: cmake --build --preset conan-debug --parallel | |
| - name: Test with AddressSanitizer | |
| run: | | |
| cd build\Debug | |
| .\utf_strings-tests.exe --gtest_output=xml:test_results_msvc_asan.xml | |
| - name: Upload sanitizer results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: sanitizer-results-windows-msvc-asan | |
| path: build\Debug\test_results_msvc_asan.xml | |
| # ============================================================================ | |
| # Performance Baseline Tracking | |
| # ============================================================================ | |
| performance-tracking: | |
| name: "Performance Baseline Tracking" | |
| runs-on: ubuntu-22.04 | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt update | |
| sudo apt install -y build-essential cmake python3-pip git | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Conan | |
| run: | | |
| pip3 install --user conan | |
| echo "$HOME/.local/bin" >> $GITHUB_PATH | |
| - name: Setup Conan profile | |
| run: | | |
| conan profile detect --force | |
| # Determine compiler and version | |
| if command -v gcc-13 >/dev/null 2>&1; then | |
| GCC_VERSION=$(gcc-13 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using GCC-13 version: $GCC_VERSION" | |
| if [ -n "$GCC_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$GCC_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect GCC version, using Conan default" | |
| fi | |
| elif command -v clang-18 >/dev/null 2>&1; then | |
| CLANG_VERSION=$(clang-18 --version | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using Clang-18 version: $CLANG_VERSION" | |
| sed -i 's/compiler=gcc/compiler=clang/' ~/.conan2/profiles/default | |
| if [ -n "$CLANG_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$CLANG_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect Clang version, using Conan default" | |
| fi | |
| sed -i 's/compiler.libcxx=libstdc++11/compiler.libcxx=libstdc++11/' ~/.conan2/profiles/default | |
| else | |
| COMPILER_VERSION=$(gcc --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1 || clang --version 2>/dev/null | head -n1 | grep -o '[0-9]\+' | head -n1) | |
| echo "Using default compiler version: $COMPILER_VERSION" | |
| if [ -n "$COMPILER_VERSION" ]; then | |
| sed -i "s/compiler.version=.*/compiler.version=$COMPILER_VERSION/" ~/.conan2/profiles/default | |
| else | |
| echo "Warning: Could not detect compiler version, using Conan default" | |
| fi | |
| fi | |
| sed -i 's/os=.*/os=Linux/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=gnu17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| sed -i 's/compiler.cppstd=17/compiler.cppstd=23/' ~/.conan2/profiles/default | |
| echo "=== Final Conan Profile ===" | |
| conan profile show --profile:host=default | |
| - name: Cache Conan packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.conan2 | |
| key: conan-performance-baseline-${{ hashFiles('conanfile.py') }} | |
| restore-keys: | | |
| conan-performance-baseline- | |
| - name: Install dependencies | |
| run: | | |
| conan install . -s os=Linux -s build_type=Release --output-folder=build --build=missing -o with_gperftools=True | |
| - name: Configure and Build (Release) | |
| run: | | |
| export CC=gcc | |
| export CXX=g++ | |
| cmake --preset conan-release | |
| cmake --build --preset conan-release --parallel | |
| - name: Run Performance Benchmarks | |
| run: | | |
| cd build/build | |
| ./utf_strings-bench --benchmark_min_time=1.0s --benchmark_format=json --benchmark_out=performance_baseline.json | |
| - name: Store Performance Results | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| with: | |
| tool: 'googlecpp' | |
| output-file-path: build/build/performance_baseline.json | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| auto-push: true | |
| alert-threshold: '150%' | |
| comment-on-alert: true | |
| fail-on-alert: true | |
| # ============================================================================ | |
| # Publish Test Results | |
| # ============================================================================ | |
| publish-test-results: | |
| name: "Publish Test Results" | |
| runs-on: ubuntu-latest | |
| needs: [linux-gcc, linux-clang, windows-msvc, linux-sanitizers, windows-msvc-sanitizer] | |
| if: always() | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| - name: Publish Unit Test Results | |
| uses: EnricoMi/publish-unit-test-result-action@v2 | |
| if: always() | |
| with: | |
| files: "**/*.xml" | |
| comment_mode: create new | |
| check_name: "Unit Test Results" | |
| report_individual_runs: true | |
| deduplicate_classes_by_file_name: false |