greenc-FNAL running code coverage for Phlex #739
Workflow file for this run
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
| # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json | |
| name: Code Coverage | |
| run-name: "${{ github.actor }} running code coverage for Phlex" | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| workflow_dispatch: | |
| inputs: | |
| phlex-coverage-compiler: | |
| description: 'Compiler to use for coverage build (gcc or clang)' | |
| required: false | |
| default: 'clang' | |
| phlex-enable-form: | |
| description: 'Enable FORM integration (set to OFF to exclude FORM sources)' | |
| required: false | |
| default: 'ON' | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| pre-check: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| is_act: ${{ steps.detect_act.outputs.is_act }} | |
| steps: | |
| - name: Detect act environment | |
| id: detect_act | |
| uses: Framework-R-D/phlex/.github/actions/detect-act-env@main | |
| detect-changes: | |
| needs: pre-check | |
| if: github.event_name != 'workflow_dispatch' && needs.pre-check.outputs.is_act != 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: read | |
| outputs: | |
| has_changes: ${{ steps.filter.outputs.matched }} | |
| steps: | |
| - name: Check out source code | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| fetch-depth: 0 | |
| path: phlex-src | |
| - name: Detect coverage relevant changes | |
| id: filter | |
| uses: Framework-R-D/phlex/.github/actions/detect-relevant-changes@main | |
| with: | |
| repo-path: phlex-src | |
| base-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} | |
| head-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| file-type: | | |
| cpp | |
| cmake | |
| - name: Report detection outcome | |
| run: | | |
| if [ "${{ steps.filter.outputs.matched }}" != "true" ]; then | |
| echo "::notice::No coverage relevant changes detected; workflow will be skipped." | |
| else | |
| echo "::group::Coverage relevant files" | |
| printf '%s\n' "${{ steps.filter.outputs.matched_files }}" | |
| echo "::endgroup::" | |
| fi | |
| coverage: | |
| needs: [pre-check, detect-changes] | |
| if: > | |
| github.event_name == 'workflow_dispatch' || | |
| needs.pre-check.outputs.is_act == 'true' || | |
| (needs.detect-changes.result == 'success' && needs.detect-changes.outputs.has_changes == 'true') | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: ghcr.io/framework-r-d/phlex-ci:latest | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| outputs: | |
| has_coverage_xml: ${{ steps.coverage_outputs.outputs.has_coverage_xml }} | |
| has_coverage_html: ${{ steps.coverage_outputs.outputs.has_coverage_html }} | |
| has_coverage_llvm_info: ${{ steps.coverage_outputs.outputs.has_coverage_llvm_info }} | |
| artifact_upload_available: ${{ steps.artifact_runtime.outputs.available }} | |
| steps: | |
| - name: Determine coverage options | |
| id: coverage_options | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| requested_compiler="${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-coverage-compiler'] || '' }}" | |
| default_compiler="clang" | |
| requested_form="${{ github.event_name == 'workflow_dispatch' && github.event.inputs['phlex-enable-form'] || '' }}" | |
| default_form="ON" | |
| compiler="${requested_compiler:-$default_compiler}" | |
| form="${requested_form:-$default_form}" | |
| echo "compiler=$compiler" >> "$GITHUB_OUTPUT" | |
| echo "enable_form=$form" >> "$GITHUB_OUTPUT" | |
| - name: Check out source code | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| path: phlex-src | |
| - name: Setup build environment | |
| uses: Framework-R-D/phlex/.github/actions/setup-build-env@main | |
| - name: Announce CMake configuration | |
| run: echo "➡️ Configuring CMake for coverage..." | |
| - name: Configure CMake with GCC coverage | |
| id: configure_gcc | |
| if: ${{ steps.coverage_options.outputs.compiler == 'gcc' }} | |
| uses: Framework-R-D/phlex/.github/actions/configure-cmake@main | |
| with: | |
| cpp-compiler: g++ | |
| preset: coverage-gcc | |
| enable-form: ${{ steps.coverage_options.outputs.enable_form }} | |
| form-root-storage: ${{ steps.coverage_options.outputs.enable_form }} | |
| - name: Configure CMake with Clang coverage | |
| id: configure_clang | |
| if: ${{ steps.coverage_options.outputs.compiler == 'clang' }} | |
| uses: Framework-R-D/phlex/.github/actions/configure-cmake@main | |
| with: | |
| cpp-compiler: clang++ | |
| preset: coverage-clang | |
| enable-form: ${{ steps.coverage_options.outputs.enable_form }} | |
| form-root-storage: ${{ steps.coverage_options.outputs.enable_form }} | |
| - name: Unknown Compiler Error | |
| if: ${{ steps.coverage_options.outputs.compiler != 'gcc' && steps.coverage_options.outputs.compiler != 'clang' }} | |
| run: | | |
| echo "ERROR: Unknown compiler '${{ steps.coverage_options.outputs.compiler }}'. Must be 'gcc' or 'clang'." | |
| exit 1 | |
| - name: Announce build | |
| run: echo "➡️ Building with coverage instrumentation..." | |
| - name: Build with coverage instrumentation | |
| id: build | |
| uses: Framework-R-D/phlex/.github/actions/build-cmake@main | |
| - name: Run tests with coverage | |
| run: | | |
| . /entrypoint.sh | |
| cd "$GITHUB_WORKSPACE/phlex-build" | |
| echo "➡️ Running tests with coverage..." | |
| PROFILE_ROOT="$GITHUB_WORKSPACE/phlex-build/test/profraw" | |
| echo "Cleaning LLVM profile directory: $PROFILE_ROOT" | |
| rm -rf "$PROFILE_ROOT" | |
| mkdir -p "$PROFILE_ROOT" | |
| export LLVM_PROFILE_FILE="$PROFILE_ROOT/%m-%p.profraw" | |
| echo "::group::Running ctest for coverage" | |
| if ctest --progress --output-on-failure -j "$(nproc)"; then | |
| echo "::endgroup::" | |
| echo "✅ All tests passed." | |
| else | |
| echo "::endgroup::" | |
| echo "::error::Some tests failed." | |
| exit 1 | |
| fi | |
| - name: Generate coverage reports (GCC) | |
| id: report_gcc | |
| if: ${{ steps.coverage_options.outputs.compiler == 'gcc' }} | |
| shell: bash | |
| run: | | |
| . /entrypoint.sh | |
| cd "$GITHUB_WORKSPACE/phlex-build" | |
| echo "➡️ Generating coverage reports for GCC..." | |
| echo "::group::Running coverage-gcov target" | |
| if cmake --build . --target coverage-gcov -v; then | |
| echo "::endgroup::" | |
| echo "✅ GCC coverage report generation succeeded." | |
| else | |
| echo "::endgroup::" | |
| echo "::error::GCC coverage report generation failed." | |
| exit 1 | |
| fi | |
| - name: Generate coverage reports (Clang) | |
| id: report_clang | |
| if: ${{ steps.coverage_options.outputs.compiler == 'clang' }} | |
| shell: bash | |
| run: | | |
| . /entrypoint.sh | |
| cd "$GITHUB_WORKSPACE/phlex-build" | |
| echo "➡️ Generating coverage reports for Clang..." | |
| echo "::group::Running coverage-llvm target" | |
| if cmake --build . --target coverage-llvm -v; then | |
| echo "::endgroup::" | |
| echo "✅ Clang coverage report generation succeeded." | |
| else | |
| echo "::endgroup::" | |
| echo "::error::Clang coverage report generation failed." | |
| exit 1 | |
| fi | |
| - name: Capture coverage artifact availability | |
| id: coverage_outputs | |
| if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} | |
| shell: bash | |
| run: | | |
| cd "$GITHUB_WORKSPACE/phlex-build" | |
| if [ -f coverage.xml ]; then | |
| echo "has_coverage_xml=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_coverage_xml=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| if [ -d coverage-html ]; then | |
| echo "has_coverage_html=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_coverage_html=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| if [ -f coverage-llvm.info ]; then | |
| echo "has_coverage_llvm_info=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_coverage_llvm_info=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Unknown Coverage Report Error | |
| if: ${{ steps.report_gcc.outcome == 'skipped' && steps.report_clang.outcome == 'skipped' }} | |
| run: | | |
| echo "ERROR: No coverage report was generated. Must run either GCC or Clang coverage report step." | |
| exit 1 | |
| - name: Prepare coverage artifact bundle | |
| if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ARTIFACT_DIR="$GITHUB_WORKSPACE/coverage-artifacts" | |
| rm -rf "$ARTIFACT_DIR" | |
| mkdir -p "$ARTIFACT_DIR" | |
| cd "$GITHUB_WORKSPACE/phlex-build" | |
| for file in \ | |
| coverage-llvm.txt \ | |
| coverage-llvm.info \ | |
| coverage.profdata \ | |
| coverage.xml \ | |
| coverage.info \ | |
| coverage.info.final; do | |
| if [ -f "$file" ]; then | |
| cp "$file" "$ARTIFACT_DIR/" | |
| fi | |
| done | |
| if [ -d coverage-html ]; then cp -R coverage-html "$ARTIFACT_DIR/"; fi | |
| - name: Detect artifact upload availability | |
| id: artifact_runtime | |
| if: ${{ steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped' }} | |
| shell: bash | |
| run: | | |
| if [ "${GITHUB_ACTOR}" = "nektos/act" ] || [ "${ACT:-}" = "true" ]; then | |
| echo "::notice::Artifact upload disabled for local act executions." | |
| echo "available=false" >> "$GITHUB_OUTPUT" | |
| elif [ -z "${ACTIONS_RUNTIME_TOKEN:-}" ]; then | |
| echo "::warning::ACTIONS_RUNTIME_TOKEN missing; continuing and trusting actions/upload-artifact to handle authentication." | |
| echo "available=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "available=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install Node.js runtime for artifact publishing | |
| if: ${{ (steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped') && steps.artifact_runtime.outputs.available == 'true' && github.actor != 'nektos/act' }} | |
| run: | | |
| curl -fsSL https://deb.nodesource.com/setup_20.x | bash - | |
| apt-get update | |
| apt-get install -y nodejs | |
| - name: Upload coverage bundle | |
| if: ${{ (steps.report_gcc.outcome != 'skipped' || steps.report_clang.outcome != 'skipped') && steps.artifact_runtime.outputs.available == 'true' && github.actor != 'nektos/act' }} | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: coverage-generated | |
| path: coverage-artifacts/ | |
| retention-days: 30 | |
| coverage-upload: | |
| needs: coverage | |
| if: ${{ needs.coverage.result == 'success' && needs.coverage.outputs.artifact_upload_available == 'true' && github.actor != 'nektos/act' }} | |
| runs-on: ubuntu-latest | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| steps: | |
| - name: Check out source code for Codecov mapping | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download coverage bundle | |
| uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 | |
| with: | |
| name: coverage-generated | |
| path: coverage-artifacts | |
| - name: Determine coverage files for Codecov | |
| id: codecov_targets | |
| run: | | |
| set -euo pipefail | |
| files=() | |
| if [ -f coverage-artifacts/coverage.xml ]; then | |
| files+=("coverage-artifacts/coverage.xml") | |
| fi | |
| if [ -f coverage-artifacts/coverage-llvm.info ]; then | |
| files+=("coverage-artifacts/coverage-llvm.info") | |
| fi | |
| ls -al coverage-artifacts || true | |
| if [ "${#files[@]}" -eq 0 ]; then | |
| echo "No coverage files detected; skipping Codecov upload." >&2 | |
| echo "found=false" >> "$GITHUB_OUTPUT" | |
| echo "files=" >> "$GITHUB_OUTPUT" | |
| else | |
| file_csv=$(IFS=,; printf '%s' "${files[*]}") | |
| echo "Codecov upload targets: ${files[*]}" | |
| echo "found=true" >> "$GITHUB_OUTPUT" | |
| echo "files=${file_csv}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload coverage to Codecov | |
| if: ${{ steps.codecov_targets.outputs.found == 'true' }} | |
| uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 | |
| with: | |
| files: ${{ steps.codecov_targets.outputs.files }} | |
| flags: unittests | |
| name: phlex-coverage | |
| fail_ci_if_error: true | |
| verbose: true | |
| root_dir: . | |
| token: ${{ env.CODECOV_TOKEN }} | |
| - name: Publish HTML coverage report | |
| if: ${{ needs.coverage.outputs.has_coverage_html == 'true' }} | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: coverage-html-report | |
| path: coverage-artifacts/coverage-html/ | |
| if-no-files-found: warn | |
| retention-days: 30 | |
| coverage-skipped: | |
| needs: [pre-check, detect-changes] | |
| if: > | |
| github.event_name != 'workflow_dispatch' && | |
| needs.pre-check.outputs.is_act != 'true' && | |
| needs.detect-changes.result == 'success' && | |
| needs.detect-changes.outputs.has_changes != 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: No relevant coverage changes detected | |
| run: echo "::notice::No relevant C++ changes detected; coverage workflow skipped." |