fix(test): apply NETWORK_COVERAGE_TIMEOUT_MULTIPLIER at explicit wait… #1600
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: Code Quality | |
| on: | |
| push: | |
| branches: [ main, develop, 'phase*' ] | |
| pull_request: | |
| branches: [ main ] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| checks: write | |
| security-events: write | |
| jobs: | |
| static-analysis: | |
| if: github.ref != 'refs/heads/gh-pages' | |
| name: Static Code Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Analysis Tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cppcheck clang-tidy clang-format python3-pip cmake ninja-build libasio-dev libfmt-dev | |
| pip3 install cpplint | |
| - name: Run cppcheck | |
| run: | | |
| cppcheck --enable=all \ | |
| --suppress=missingIncludeSystem \ | |
| --suppress=unusedFunction \ | |
| --suppress=unmatchedSuppression \ | |
| --inline-suppr \ | |
| --xml \ | |
| --output-file=cppcheck-report.xml \ | |
| include/ src/ | |
| continue-on-error: true | |
| - name: Run clang-tidy | |
| run: | | |
| # First configure the project to generate compile_commands.json | |
| cmake -B build -G Ninja \ | |
| -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ | |
| -DBUILD_TESTS=OFF \ | |
| -DBUILD_EXAMPLES=OFF \ | |
| -DBUILD_WITH_COMMON_SYSTEM=OFF \ | |
| -DBUILD_WITH_LOGGER_SYSTEM=OFF \ | |
| -DBUILD_WITH_THREAD_SYSTEM=OFF \ | |
| -DBUILD_WITH_CONTAINER_SYSTEM=OFF \ | |
| -DBUILD_MESSAGING_BRIDGE=OFF | |
| find src include -name '*.cpp' -o -name '*.h' | \ | |
| xargs clang-tidy -p=build \ | |
| -checks='-*,modernize-*,performance-*,bugprone-*' \ | |
| --warnings-as-errors='' || true | |
| continue-on-error: true | |
| - name: Check Code Formatting | |
| run: | | |
| echo "Checking code formatting..." | |
| find src include -name '*.cpp' -o -name '*.h' 2>/dev/null | \ | |
| xargs clang-format -style=file -dry-run 2>&1 | tee format-check.log || true | |
| if [ -s format-check.log ]; then | |
| echo "⚠️ Code formatting issues found (see format-check.log)" | |
| else | |
| echo "✅ Code formatting is correct" | |
| fi | |
| continue-on-error: true | |
| - name: Run cpplint | |
| run: | | |
| find src include -name '*.cpp' -o -name '*.h' | \ | |
| xargs cpplint --filter=-legal/copyright,-build/include_subdir | |
| continue-on-error: true | |
| - name: Upload Analysis Reports | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| continue-on-error: true | |
| with: | |
| name: analysis-reports | |
| path: | | |
| cppcheck-report.xml | |
| clang-tidy-report.txt | |
| retention-days: 30 | |
| security-scan: | |
| name: Security Vulnerability Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Run Trivy Security Scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| - name: Upload Trivy Results | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| code-coverage: | |
| name: Code Coverage Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Checkout common_system | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: kcenon/common_system | |
| path: common_system | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Environment | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cmake ninja-build libasio-dev libfmt-dev lcov gcovr | |
| - name: Install common_system headers | |
| run: | | |
| if [ -d "common_system" ]; then | |
| echo "Installing common_system headers..." | |
| cd common_system | |
| cmake -B build -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DBUILD_TESTS=OFF \ | |
| -DBUILD_EXAMPLES=OFF \ | |
| -DBUILD_EXAMPLES=OFF | |
| cmake --build build | |
| sudo cmake --install build --prefix /usr/local | |
| cd .. | |
| fi | |
| - name: Configure with Coverage | |
| run: | | |
| cmake -B build -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Debug \ | |
| -DCMAKE_CXX_FLAGS="--coverage -fprofile-arcs -ftest-coverage" \ | |
| -DCMAKE_C_FLAGS="--coverage -fprofile-arcs -ftest-coverage" \ | |
| -DBUILD_TESTS=ON \ | |
| -DBUILD_EXAMPLES=OFF \ | |
| -DBUILD_WITH_COMMON_SYSTEM=ON \ | |
| -DBUILD_WITH_LOGGER_SYSTEM=OFF \ | |
| -DBUILD_WITH_THREAD_SYSTEM=OFF \ | |
| -DBUILD_WITH_CONTAINER_SYSTEM=OFF \ | |
| -DBUILD_MESSAGING_BRIDGE=OFF | |
| - name: Build | |
| run: cmake --build build | |
| - name: Run Tests | |
| run: | | |
| cd build | |
| ./verify_build || true | |
| ./test_integration || true | |
| ./test_compatibility || true | |
| ./test_e2e || true | |
| - name: Generate Coverage Report | |
| run: | | |
| cd build | |
| # Generate coverage data with gcov bug workaround | |
| gcovr -r .. \ | |
| --gcov-ignore-parse-errors=negative_hits.warn_once_per_file \ | |
| --exclude='.*test.*' \ | |
| --exclude='.*sample.*' \ | |
| --exclude='.*build.*' \ | |
| --html --html-details \ | |
| -o coverage-report.html || true | |
| # Generate summary with error handling | |
| gcovr -r .. \ | |
| --gcov-ignore-parse-errors=negative_hits.warn_once_per_file \ | |
| --exclude='.*test.*' \ | |
| --exclude='.*sample.*' \ | |
| --exclude='.*build.*' \ | |
| --print-summary || echo "Coverage summary generation failed" | |
| - name: Check Coverage Threshold | |
| run: | | |
| cd build | |
| # Fix for gcovr issues with certain GCC versions | |
| export GCOV_ERROR_FILE=/dev/null | |
| # Get coverage with error handling and gcov bug workaround | |
| coverage=$(gcovr -r .. \ | |
| --gcov-ignore-parse-errors=negative_hits.warn_once_per_file \ | |
| --exclude='.*test.*' \ | |
| --exclude='.*sample.*' \ | |
| --print-summary 2>/dev/null | grep "TOTAL" | awk '{print $4}' | sed 's/%//' || echo "0") | |
| # Default to 0 if parsing fails | |
| if [ -z "$coverage" ]; then | |
| coverage=0 | |
| fi | |
| threshold=50 | |
| # Use arithmetic comparison instead of bc | |
| if [ "$coverage" -lt "$threshold" ] 2>/dev/null || [ "$coverage" = "0" ]; then | |
| echo "⚠️ Code coverage ($coverage%) is below threshold ($threshold%)" | |
| echo "Note: Coverage improvement needed in future iterations" | |
| else | |
| echo "✅ Code coverage ($coverage%) meets threshold ($threshold%)" | |
| fi | |
| - name: Upload Coverage Report | |
| uses: actions/upload-artifact@v7 | |
| continue-on-error: true | |
| with: | |
| name: coverage-report | |
| path: build/coverage-report.html | |
| retention-days: 30 | |
| dependency-check: | |
| name: Dependency Security Check | |
| runs-on: ubuntu-latest | |
| env: | |
| VCPKG_MANIFEST_PATH: vcpkg.json | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Validate canonical vcpkg manifest | |
| run: | | |
| test -f "${VCPKG_MANIFEST_PATH}" | |
| if [ -f "package/vcpkg/vcpkg.json" ]; then | |
| echo "::error file=package/vcpkg/vcpkg.json::Legacy package manifest detected. Use ${VCPKG_MANIFEST_PATH} as the canonical source of truth." | |
| exit 1 | |
| fi | |
| - name: Check for Vulnerable Dependencies | |
| run: | | |
| # Check CMake dependencies | |
| grep -h "find_package\|FetchContent_Declare" CMakeLists.txt */CMakeLists.txt | \ | |
| while read line; do | |
| echo "Checking: $line" | |
| done | |
| - name: License Compatibility Check | |
| run: | | |
| python3 << 'EOF' > license-report.md | |
| import json | |
| import os | |
| manifest_path = os.environ["VCPKG_MANIFEST_PATH"] | |
| with open(manifest_path, "r", encoding="utf-8") as f: | |
| manifest = json.load(f) | |
| known_licenses = { | |
| "asio": "BSL-1.0", | |
| "zlib": "Zlib", | |
| "openssl": "Apache-2.0", | |
| "lz4": "BSD-2-Clause", | |
| "grpc": "Apache-2.0", | |
| "protobuf": "BSD-3-Clause", | |
| "gtest": "BSD-3-Clause", | |
| "benchmark": "Apache-2.0", | |
| } | |
| def collect_deps(entries): | |
| names = [] | |
| for entry in entries: | |
| if isinstance(entry, str): | |
| names.append(entry) | |
| elif isinstance(entry, dict): | |
| names.append(entry.get("name", "unknown")) | |
| return names | |
| dependency_names = collect_deps(manifest.get("dependencies", [])) | |
| for feature in manifest.get("features", {}).values(): | |
| dependency_names.extend(collect_deps(feature.get("dependencies", []))) | |
| dependency_names = sorted(set(dependency_names)) | |
| print("## License Check") | |
| print() | |
| print(f"**Project**: {manifest.get('name', 'unknown')}") | |
| print(f"**Project License**: {manifest.get('license', 'unknown')}") | |
| print() | |
| print("### Dependencies") | |
| for dependency_name in dependency_names: | |
| if dependency_name.startswith("kcenon-"): | |
| license_name = "BSD-3-Clause" | |
| else: | |
| license_name = known_licenses.get(dependency_name, "UNKNOWN") | |
| print(f"- {dependency_name}: {license_name}") | |
| EOF | |
| - name: Upload License Report | |
| uses: actions/upload-artifact@v7 | |
| continue-on-error: true | |
| with: | |
| name: license-report | |
| path: license-report.md | |
| retention-days: 30 |