From d49e2e35fd99466a518d28b79e65117b2574223a Mon Sep 17 00:00:00 2001 From: jamessiddeley-amd Date: Mon, 17 Nov 2025 09:24:24 -0500 Subject: [PATCH] [rocprof-compute] Automate ctest coverage and test cases on runners with CDash (#1481) * Add nightly coverage workflow * ruff formatting * temp workflow testing * restore workflow file * add workflow condition * update workflow file * update workflow file * fix typo in run-ci.py * edit run-ci.py * add python deps install * add python deps install * add python deps install * add python deps install * check if enable coverage is on when using workflow * remove github CI breakdown and fix enable coverage * set cache variables must be set before dashboard starts * Update run-ci.py * Update run-ci.py to fix ctest cache * Update rocprofiler-compute-code-coverage.yml to install tests * Update rocprofiler-compute-code-coverage.yml * Restore workflow file * Update run-ci.py * Simplify workflow build command * Update run-ci.py to build tests * edited run-ci script * edit ctest configure commands * edit ctest configure commands to be on one line * edit ctest configure command to include path to amdclang++ * update clang check in tests/cmakelists.txt * update rocm * update rocm * update rocm version 7.0.2 * update tests/CMakeLists.txt * use tarball instead for rocm install * apt install rocm-dev instead for 7.0.0 release * workflow tweaks * update to use new 'tools' dir * install rocm-dev * add CMAKE_CXX_COMPILER as clang * update tests/cmakelists.txt * update cdasg site and build names * remove run automatically on pull requests * ruff format * increased timeouts for tests * add back reruns for workflow testing * fix typo * rename workflow "nightly" -> "code" * added tracks to keep track of gpu (325 vs 355) * remove test_db_connector.py * revert build names and tracking * update workflow pushes * CMake format * changed parallel level back to 1 --- .../workflows/rocprofiler-compute-cdash.yml | 89 - .../rocprofiler-compute-code-coverage.yml | 157 + projects/rocprofiler-compute/CMakeLists.txt | 12 +- .../rocprofiler-compute/coverage/Coverage.xml | 5588 ----------------- .../rocprofiler-compute/coverage/README.md | 77 - .../rocprofiler-compute/tests/CMakeLists.txt | 4 +- projects/rocprofiler-compute/tools/run-ci.py | 380 +- .../tools/update-coverage.sh | 81 - 8 files changed, 392 insertions(+), 5996 deletions(-) delete mode 100644 .github/workflows/rocprofiler-compute-cdash.yml create mode 100644 .github/workflows/rocprofiler-compute-code-coverage.yml delete mode 100644 projects/rocprofiler-compute/coverage/Coverage.xml delete mode 100644 projects/rocprofiler-compute/coverage/README.md delete mode 100755 projects/rocprofiler-compute/tools/update-coverage.sh diff --git a/.github/workflows/rocprofiler-compute-cdash.yml b/.github/workflows/rocprofiler-compute-cdash.yml deleted file mode 100644 index 82def8ef20..0000000000 --- a/.github/workflows/rocprofiler-compute-cdash.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: rocprofiler-compute CDash Coverage Upload - -on: - push: - branches: [ develop ] - paths: - - 'projects/rocprofiler-compute/coverage/Coverage.xml' - workflow_dispatch: - inputs: - coverage_file: - description: 'Path to coverage XML file' - required: false - default: 'projects/rocprofiler-compute/coverage/Coverage.xml' - -concurrency: - group: rocprofiler-compute-cdash-${{ github.ref }} - cancel-in-progress: true - -jobs: - upload-coverage: - runs-on: ubuntu-latest - name: Upload Coverage to CDash - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - sparse-checkout: projects/rocprofiler-compute - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - - name: Check Coverage File Exists - working-directory: projects/rocprofiler-compute - run: | - COVERAGE_FILE="${{ github.event.inputs.coverage_file || 'coverage/Coverage.xml' }}" - if [[ "$COVERAGE_FILE" == projects/rocprofiler-compute/* ]]; then - COVERAGE_FILE="${COVERAGE_FILE#projects/rocprofiler-compute/}" - fi - - if [ ! -f "$COVERAGE_FILE" ]; then - echo "ERROR: Coverage file not found at $COVERAGE_FILE!" - echo "Please run manual coverage generation" - echo "Use: cd projects/rocprofiler-compute && ./utils/update_coverage.sh" - exit 1 - fi - - COVERAGE_INFO=$(python3 -c " - import xml.etree.ElementTree as ET - try: - tree = ET.parse('$COVERAGE_FILE') - root = tree.getroot() - line_rate = float(root.get('line-rate', 0)) * 100 - print(f'{line_rate:.1f}%') - except Exception as e: - print(f'Error parsing coverage: {e}') - exit(1) - ") - - echo "Line Coverage: $COVERAGE_INFO" - echo "COVERAGE_INFO=$COVERAGE_INFO" >> $GITHUB_ENV - echo "COVERAGE_FILE=$COVERAGE_FILE" >> $GITHUB_ENV - - - name: Upload to CDash - working-directory: projects/rocprofiler-compute - run: | - GIT_SHA_SHORT=$(git rev-parse --short HEAD) - BRANCH_NAME=${GITHUB_REF#refs/heads/} - - python3 utils/run-ci.py \ - --coverage-file "${{ env.COVERAGE_FILE }}" \ - --build-name "${BRANCH_NAME}-${GIT_SHA_SHORT}-$(date +%Y%m%d)" \ - --mode "Continuous" \ - --site "Monorepo-Upload" \ - --project-name "rocprofiler-compute" \ - --source-dir "." \ - --binary-dir "build" - - - name: Summary - run: | - echo "## CDash Upload Complete!" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY - echo "- **Line Coverage**: ${{ env.COVERAGE_INFO }}" >> $GITHUB_STEP_SUMMARY - echo "- **Commit**: $(git rev-parse --short HEAD)" >> $GITHUB_STEP_SUMMARY - echo "- **CDash Project**: rocprofiler-compute" >> $GITHUB_STEP_SUMMARY - echo "- **Coverage File**: ${{ env.COVERAGE_FILE }}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/rocprofiler-compute-code-coverage.yml b/.github/workflows/rocprofiler-compute-code-coverage.yml new file mode 100644 index 0000000000..9ade629aba --- /dev/null +++ b/.github/workflows/rocprofiler-compute-code-coverage.yml @@ -0,0 +1,157 @@ +name: rocprofiler-compute Code Coverage +run-name: rocprofiler-compute-code-coverage + +on: + schedule: + - cron: '0 2 * * *' + workflow_dispatch: + inputs: + runner_matrix: + description: 'Runner configuration' + required: false + type: string + +env: + ROCM_PATH: "/opt/rocm" + ROCM_VERSION: "7.0.2" + +jobs: + prepare_matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.generate_matrix.outputs.matrix }} + + steps: + - name: Generate matrix + id: generate_matrix + run: | + MATRIX='[{"os-release":"22.04","gpu":"mi355","arch":"gfx950","runner":"linux-mi355-1gpu-ossci-rocm","code-name":"jammy"},{"os-release":"24.04","gpu":"mi355","arch":"gfx950","runner":"linux-mi355-1gpu-ossci-rocm","code-name":"noble"},{"os-release":"22.04","gpu":"mi325","arch":"gfx94X","runner":"linux-mi325-1gpu-ossci-rocm","code-name":"jammy"},{"os-release":"24.04","gpu":"mi325","arch":"gfx94X","runner":"linux-mi325-1gpu-ossci-rocm","code-name":"noble"}]' + + if [ -n "${{ github.event.inputs.runner_matrix }}" ]; then + MATRIX='${{ github.event.inputs.runner_matrix }}' + fi + + echo "matrix=${MATRIX}" >> $GITHUB_OUTPUT + + coverage: + name: Coverage • ${{ matrix.system.gpu }} • Ubuntu ${{ matrix.system.os-release }} + needs: prepare_matrix + strategy: + fail-fast: false + matrix: + system: ${{ fromJSON(needs.prepare_matrix.outputs.matrix) }} + runs-on: ${{ matrix.system.runner }} + env: + HIP_PLATFORM: "amd" + OMPI_ALLOW_RUN_AS_ROOT: 1 + OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: 1 + permissions: + packages: read + container: + image: ghcr.io/rocm/rocprofiler-ubuntu:${{ matrix.system.os-release }}-systems-ci-${{ matrix.system.arch }} + options: + --privileged + --ipc host + --group-add video + --device /dev/kfd + --device /dev/dri + --cap-add CAP_SYS_ADMIN + + steps: + - uses: actions/checkout@v5 + with: + sparse-checkout: projects/rocprofiler-compute/ + + - name: Update system packages + run: | + apt-get update + apt-get dist-upgrade -y + echo "✅ System packages updated!" + + - name: Install amdgpu and dependencies + shell: bash + run: | + ROCM_MAJOR=$(echo ${{ env.ROCM_VERSION }} | sed 's/\./ /g' | awk '{print $1}') + ROCM_MINOR=$(echo ${{ env.ROCM_VERSION }} | sed 's/\./ /g' | awk '{print $2}') + ROCM_VERSN=$(( (${ROCM_MAJOR}*10000)+(${ROCM_MINOR}*100) )) + wget -N -P /tmp/ https://repo.radeon.com/amdgpu-install/${ROCM_MAJOR}.${ROCM_MINOR}/ubuntu/${{ matrix.system.code-name }}/amdgpu-install_${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1_all.deb + apt-get install -y /tmp/amdgpu-install_${ROCM_MAJOR}.${ROCM_MINOR}.${ROCM_VERSN}-1_all.deb + apt-get update + apt install -y amd-smi-lib libdw-dev + echo "✅ amdgpu and dependencies Installed!" + + - name: Install MPI + run: | + apt install -y libopenmpi-dev + echo "✅ MPI Installed!" + + - name: Install ROCm + run: | + apt install -y rocm-dev + echo "✅ ROCm Installation Complete!" + + - name: Install Python Dependencies + working-directory: projects/rocprofiler-compute + run: | + pip install -r requirements.txt --break-system-packages --ignore-installed + pip install -r requirements-test.txt --break-system-packages --ignore-installed + echo "✅ Python dependencies installed!" + + - name: Configure, Build, Test, and Upload Coverage + id: run_coverage + timeout-minutes: 120 + working-directory: projects/rocprofiler-compute + continue-on-error: true + run: | + set -e + git config --global --add safe.directory ${GITHUB_WORKSPACE} + git config --global --add safe.directory ${PWD} + + BUILD_NAME="ROCm/rocprofiler-compute-${{ github.ref_name }}-ubuntu-${{ matrix.system.os-release }}-${{ matrix.system.gpu }}" + SITE_NAME="${{ matrix.system.runner }}" + + PATH=${{ env.ROCM_PATH }}/bin:${{ env.ROCM_PATH }}/llvm/bin:$PATH \ + LD_LIBRARY_PATH=${{ env.ROCM_PATH }}/lib:${{ env.ROCM_PATH }}/llvm/lib:$LD_LIBRARY_PATH \ + python3 ./tools/run-ci.py \ + --build-name "${BUILD_NAME}" \ + --site "${SITE_NAME}" \ + --mode "Nightly" \ + --build-jobs 16 \ + --pytest-numprocs 8 \ + --install + + - name: Check Coverage Configuration + if: always() + working-directory: projects/rocprofiler-compute + run: | + echo "=== Checking Build Configuration ===" + if [ -f "build/CMakeCache.txt" ]; then + echo "CMakeCache.txt contents (relevant variables):" + grep -E "ENABLE_TESTS|ENABLE_COVERAGE|INSTALL_TESTS|PYTEST_NUMPROCS" build/CMakeCache.txt || echo "⚠️ Coverage variables not found!" + echo "" + echo "=== Checking for coverage.xml ===" + if [ -f "build/coverage.xml" ]; then + echo "✅ coverage.xml found!" + ls -lh build/coverage.xml + else + echo "❌ coverage.xml NOT found!" + fi + echo "" + echo "=== Checking CTest results ===" + if [ -f "build/Testing/Temporary/LastTest.log" ]; then + echo "Last 50 lines of test log:" + tail -n 50 build/Testing/Temporary/LastTest.log + fi + else + echo "❌ build/CMakeCache.txt not found - build may have failed!" + fi + + - name: Upload Logs on Failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-logs-${{ matrix.system.gpu }}-${{ matrix.system.os-release }} + path: | + projects/rocprofiler-compute/build/Testing/Temporary/LastTest*.log + projects/rocprofiler-compute/build/coverage.xml + retention-days: 7 diff --git a/projects/rocprofiler-compute/CMakeLists.txt b/projects/rocprofiler-compute/CMakeLists.txt index 971ecaa789..30b10dd2cc 100644 --- a/projects/rocprofiler-compute/CMakeLists.txt +++ b/projects/rocprofiler-compute/CMakeLists.txt @@ -164,7 +164,7 @@ if(LOCALHOST MATCHES "TheraS01|.*\.thera\.amd\.com|thera-hn") file(READ ${PROJECT_SOURCE_DIR}/cmake/modfile.thera.mod mod_additions) file( APPEND - ${PROJECT_BINARY_DIR}/${MOD_INSTALL_PATH}/${ROCPROFCOMPUTE_FULL_VERSION}.lua + ${PROJECT_BINARY_DIR}/${MOD_INSTALL_PATH}/${ROCPROFCOMPUTE_FULL_VERSION}.lua ${mod_additions} ) list(POP_BACK CMAKE_MESSAGE_INDENT) @@ -336,7 +336,11 @@ set_tests_properties( test_profile_misc test_profile_path test_profile_roofline - PROPERTIES LABELS "profile" RESOURCE_GROUPS gpus:1 + test_profile_section + test_profile_pc_sampling + test_profile_sets_func + test_profile_live_attach_detach + PROPERTIES LABELS "profile" RESOURCE_GROUPS gpus:1 TIMEOUT 1800 ) # --------------------------- @@ -463,6 +467,7 @@ if(${ENABLE_COVERAGE}) DEPENDS "${ALL_TESTS_STRING}" LABELS "coverage" ENVIRONMENT "COVERAGE_FILE=${PROJECT_SOURCE_DIR}/.coverage" + TIMEOUT 600 ) endif() @@ -489,8 +494,7 @@ install( src/config.py src/rocprof_compute_base.py src/roofline.py - VERSION - VERSION.sha + VERSION VERSION.sha DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/${PROJECT_NAME} COMPONENT main ) diff --git a/projects/rocprofiler-compute/coverage/Coverage.xml b/projects/rocprofiler-compute/coverage/Coverage.xml deleted file mode 100644 index b7b56945e1..0000000000 --- a/projects/rocprofiler-compute/coverage/Coverage.xml +++ /dev/null @@ -1,5588 +0,0 @@ - - - - - - /app/projects/rocprofiler-compute - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/rocprofiler-compute/coverage/README.md b/projects/rocprofiler-compute/coverage/README.md deleted file mode 100644 index 95d37c4861..0000000000 --- a/projects/rocprofiler-compute/coverage/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Coverage Workflow for rocprofiler-compute in Monorepo - -## Overview - -This document describes the coverage generation and CDash upload workflow for `rocprofiler-compute` within the super-repo structure. - -## Directory Structure - -``` -monorepo/ -├── projects/ -│ └── rocprofiler-compute/ -│ ├── CMakeLists.txt -│ ├── coverage/ -│ │ └── coverage-latest.xml # committed coverage file -│ ├── tools/ -│ │ ├── update_coverage.sh # coverage generation/update script -│ │ └── run-ci.py # CDash upload script -│ └── ... -└── .github/ - └── workflows/ - └── rocprofiler-compute-cdash.yml # gitHub Action for auto-upload -``` - -## Workflows - -### 1. Manual Coverage Generation (Periodic Update) - -Run this periodically to update the coverage baseline: - -```bash -# From monorepo root -cd projects/rocprofiler-compute -./tools/update_coverage.sh - -# This will: -# - Build with coverage enabled -# - Run all tests -# - Generate coverage.xml -# - Copy/overwrite to coverage/coverage-latest.xml -# - Show instructions for committing -``` - -### 2. Commit Coverage to Repository - -```bash -# From monorepo root -git add projects/rocprofiler-compute/coverage/coverage-latest.xml -git commit -m "rocprofiler-compute: Update coverage to XX.X% line coverage" -git push origin develop -``` - -### 3. Automatic CDash Upload - -When `coverage/coverage-latest.xml` is pushed to `develop` branch: -- GitHub Action triggers automatically -- Uploads coverage to CDash -- Posts summary to GitHub Actions - -## CDash Project - -View results at: https://my.cdash.org/index.php?project=rocprofiler-compute - -## Maintenance - -## Troubleshooting - -### Coverage Generation Fails - -```bash -#check Python dependencies -pip install coverage pytest pytest-cov - -#verify tests can run -cd projects/rocprofiler-compute/build -ctest --verbose -``` diff --git a/projects/rocprofiler-compute/tests/CMakeLists.txt b/projects/rocprofiler-compute/tests/CMakeLists.txt index 5400bb961a..40f712dc42 100644 --- a/projects/rocprofiler-compute/tests/CMakeLists.txt +++ b/projects/rocprofiler-compute/tests/CMakeLists.txt @@ -1,10 +1,10 @@ set(CMAKE_HIP_COMPILER "amdclang++" CACHE STRING "desired c++ compiler" FORCE) -if(CMAKE_HIP_COMPILER_ID STREQUAL "Clang") +if(CMAKE_HIP_COMPILER_ID STREQUAL "Clang" OR CMAKE_HIP_COMPILER_ID STREQUAL "ROCMClang") message(STATUS "Using ${CMAKE_HIP_COMPILER} to build for amdgpu backend") else() message( FATAL_ERROR - "'amdclang++' compiler required to compile test binaries for ROCm platform." + "'amdclang++' compiler required to compile test binaries for ROCm platform. Found: ${CMAKE_HIP_COMPILER_ID}" ) endif() diff --git a/projects/rocprofiler-compute/tools/run-ci.py b/projects/rocprofiler-compute/tools/run-ci.py index f692fac0ee..467fccdfd1 100755 --- a/projects/rocprofiler-compute/tools/run-ci.py +++ b/projects/rocprofiler-compute/tools/run-ci.py @@ -23,13 +23,8 @@ # THE SOFTWARE. ############################################################################## -""" -CI script to upload coverage XML files to CDash -""" - import argparse import os -import shutil import subprocess import sys import tempfile @@ -60,16 +55,44 @@ def detect_repo_structure(): return False, None, cwd -def create_ctest_script(args): - """Generate a CTest script for uploading coverage data""" +def generate_ctest_dashboard_script(args, source_dir, binary_dir): + """ + Generate a complete CTest dashboard script that handles: + - Configuration + - Build + - Test + - Coverage + - Submit to CDash + """ + cache_entries = [ + "CMAKE_BUILD_TYPE:STRING=Release", + f"CMAKE_PREFIX_PATH:PATH={os.environ.get('ROCM_PATH', '/opt/rocm')}", + "ENABLE_TESTS:BOOL=ON", + "INSTALL_TESTS:BOOL=ON", + "ENABLE_COVERAGE:BOOL=ON", + f"PYTEST_NUMPROCS:STRING={args.pytest_numprocs}", + ] + + test_args = "" + if args.ctest_args: + test_args = " ".join(args.ctest_args) + + # ruff: noqa script_content = f""" cmake_minimum_required(VERSION 3.19) +############################################################################## +# CTest Dashboard Script for rocprofiler-compute +# Auto-generated by run-ci.py +############################################################################## + +# Dashboard configuration set(CTEST_PROJECT_NAME "{args.project_name}") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_DROP_SITE_CDASH TRUE) +# CDash submission settings if(CMAKE_VERSION VERSION_GREATER 3.14) set(CTEST_SUBMIT_URL "{args.submit_url}") else() @@ -78,93 +101,143 @@ else() set(CTEST_DROP_LOCATION "{args.submit_path}") endif() +# Build identification set(CTEST_SITE "{args.site}") set(CTEST_BUILD_NAME "{args.build_name}") -set(CTEST_SOURCE_DIRECTORY "{args.source_dir}") -set(CTEST_BINARY_DIRECTORY "{args.binary_dir}") +set(CTEST_SOURCE_DIRECTORY "{source_dir}") +set(CTEST_BINARY_DIRECTORY "{binary_dir}") -file(MAKE_DIRECTORY "${{CTEST_BINARY_DIRECTORY}}") +# Build config +set(CTEST_CMAKE_GENERATOR "Unix Makefiles") +set(CTEST_BUILD_CONFIGURATION "Release") -if(NOT EXISTS "${{CTEST_BINARY_DIRECTORY}}/CMakeCache.txt") - file(WRITE "${{CTEST_BINARY_DIRECTORY}}/CMakeCache.txt" - "CMAKE_PROJECT_NAME:STATIC={args.project_name}\\n") -endif() +# Config CMake command with all required options +set(CTEST_CONFIGURE_COMMAND "cmake -B ${{CTEST_BINARY_DIRECTORY}} ${{CTEST_SOURCE_DIRECTORY}} -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH={os.environ.get("ROCM_PATH", "/opt/rocm")} -DENABLE_TESTS=ON -DINSTALL_TESTS=ON -DENABLE_COVERAGE=ON -DPYTEST_NUMPROCS={args.pytest_numprocs}") -file(WRITE "${{CTEST_BINARY_DIRECTORY}}/CTestConfig.cmake" " -set(CTEST_PROJECT_NAME \\"{args.project_name}\\") -set(CTEST_NIGHTLY_START_TIME \\"01:00:00 UTC\\") -if(CMAKE_VERSION VERSION_GREATER 3.14) - set(CTEST_SUBMIT_URL \\"{args.submit_url}\\") -else() - set(CTEST_DROP_METHOD \\"https\\") - set(CTEST_DROP_SITE \\"{args.cdash_host}\\") - set(CTEST_DROP_LOCATION \\"{args.submit_path}\\") -endif() -set(CTEST_DROP_SITE_CDASH TRUE) -") +message(STATUS "CMake configure command: ${{CTEST_CONFIGURE_COMMAND}}") +message(STATUS "Starting {args.mode} dashboard...") ctest_start({args.mode}) -set(COVERAGE_SRC_FILE "{args.coverage_file}") -set(COVERAGE_DEST_FILE "${{CTEST_BINARY_DIRECTORY}}/coverage.xml") +# Config step +message(STATUS "Configuring project...") +ctest_configure( + RETURN_VALUE configure_result + CAPTURE_CMAKE_ERROR configure_error +) -if(NOT EXISTS "${{COVERAGE_SRC_FILE}}") - message(FATAL_ERROR "Coverage file not found: ${{COVERAGE_SRC_FILE}}") +if(configure_result OR configure_error) + message(WARNING "Configuration had issues but continuing...") endif() -file(COPY "${{COVERAGE_SRC_FILE}}" DESTINATION "${{CTEST_BINARY_DIRECTORY}}") -get_filename_component(SRC_FILENAME "${{COVERAGE_SRC_FILE}}" NAME) -if(NOT SRC_FILENAME STREQUAL "coverage.xml") - file(RENAME "${{CTEST_BINARY_DIRECTORY}}/${{SRC_FILENAME}}" - "${{COVERAGE_DEST_FILE}}") +# Build step +message(STATUS "Building project...") +set(CTEST_BUILD_FLAGS "-j{args.build_jobs}") +ctest_build( + TARGET {"install" if args.install else "all"} + RETURN_VALUE build_result + CAPTURE_CMAKE_ERROR build_error +) + +if(build_result OR build_error) + message(WARNING "Build had issues but continuing...") endif() -message(STATUS "Processing coverage file: ${{COVERAGE_DEST_FILE}}") +# Test step +message(STATUS "Running tests...") +ctest_test( + {test_args} + PARALLEL_LEVEL 1 + RETURN_VALUE test_result + CAPTURE_CMAKE_ERROR test_error +) -file(MAKE_DIRECTORY "${{CTEST_BINARY_DIRECTORY}}/Testing") -file(MAKE_DIRECTORY "${{CTEST_BINARY_DIRECTORY}}/Testing/CoverageInfo") - -file(COPY "${{COVERAGE_DEST_FILE}}" - DESTINATION "${{CTEST_BINARY_DIRECTORY}}/Testing/CoverageInfo") - -ctest_coverage() - -ctest_submit(PARTS Coverage - RETRY_COUNT 3 - RETRY_DELAY 5 - CAPTURE_CMAKE_ERROR submit_error) - -if(submit_error) - message(FATAL_ERROR "Failed to submit coverage to CDash. " - "Error code: ${{submit_error}}") +if(test_result OR test_error) + message(WARNING "Some tests failed but continuing with coverage and upload...") endif() -message(STATUS "Successfully submitted coverage to CDash") +# Coverage step (if coverage file exists) +set(COVERAGE_FILE "${{CTEST_BINARY_DIRECTORY}}/coverage.xml") +if(EXISTS "${{COVERAGE_FILE}}") + message(STATUS "Processing coverage data...") + + file(MAKE_DIRECTORY "${{CTEST_BINARY_DIRECTORY}}/Testing/CoverageInfo") + file(COPY "${{COVERAGE_FILE}}" + DESTINATION "${{CTEST_BINARY_DIRECTORY}}/Testing/CoverageInfo/") + + ctest_coverage( + RETURN_VALUE coverage_result + CAPTURE_CMAKE_ERROR coverage_error + ) + + if(coverage_result OR coverage_error) + message(WARNING "Coverage processing had issues but continuing...") + endif() +else() + message(STATUS "No coverage file found at ${{COVERAGE_FILE}}") + message(STATUS "Skipping coverage step") +endif() + +message(STATUS "Submitting to CDash...") +ctest_submit( + RETRY_COUNT 3 + RETRY_DELAY 5 + RETURN_VALUE submit_result + CAPTURE_CMAKE_ERROR submit_error +) + +if(submit_result OR submit_error) + message(WARNING "CDash submission encountered issues") + message(STATUS "Results available locally in: ${{CTEST_BINARY_DIRECTORY}}/Testing/") +else() + message(STATUS "Successfully submitted to CDash!") + message(STATUS "View at: {args.submit_url.replace("/submit.php?project=", "/index.php?project=")}") + message(STATUS "Build name: {args.build_name}") +endif() + +message(STATUS "") +message(STATUS "========================================") +message(STATUS "Dashboard Summary") +message(STATUS "========================================") +if(test_result) + message(STATUS "Tests: FAILED (some tests failed or timed out)") +else() + message(STATUS "Tests: PASSED") +endif() +if(submit_result OR submit_error) + message(STATUS "CDash Upload: FAILED") +else() + message(STATUS "CDash Upload: SUCCESS") +endif() +message(STATUS "========================================") + +# For nightly/continuous, don't fail on test failures +# Only warn in Experimental mode +if("{args.mode}" STREQUAL "Experimental" AND test_result) + message(WARNING "Tests failed in Experimental mode") +endif() """ + return script_content def main(): - if not os.getenv("CI"): - print("WARNING: CDash upload should normally only be done from CI/CD") - response = input("Continue anyway? (y/N): ") - if response.lower() != "y": - print("Aborted.") - return 1 - parser = argparse.ArgumentParser( - description="Upload coverage XML to CDash for rocprofiler-compute" + description="CI script for rocprofiler-compute: build, test, and upload to CDash" ) - # required parser.add_argument( - "--coverage-file", required=True, help="Path to coverage XML file" + "--build-name", + "--name", + dest="build_name", + required=True, + help="Build name for CDash", ) - parser.add_argument("--build-name", required=True, help="Build name for CDash") - # optional parser.add_argument( - "--project-name", default="rocprofiler-compute", help="CDash project name" + "--project-name", + default="rocprofiler-compute", + help="CDash project name", ) parser.add_argument( "--submit-url", @@ -172,7 +245,9 @@ def main(): help="CDash submission URL", ) parser.add_argument( - "--cdash-host", default="my.cdash.org", help="CDash host (for older CMake)" + "--cdash-host", + default="my.cdash.org", + help="CDash host (for older CMake)", ) parser.add_argument( "--submit-path", @@ -186,11 +261,13 @@ def main(): ) parser.add_argument( "--source-dir", + "-S", default=None, help="Source directory path (auto-detected if not provided)", ) parser.add_argument( "--binary-dir", + "-B", default=None, help="Binary directory path (defaults to source-dir/build)", ) @@ -201,10 +278,33 @@ def main(): help="CTest dashboard mode", ) parser.add_argument( - "--dry-run", action="store_true", help="Generate script but don't execute" + "--build-jobs", + "-j", + type=int, + default=8, + help="Number of parallel build jobs", + ) + parser.add_argument( + "--install", + action="store_true", + help="Build install target instead of all target", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Generate dashboard script but don't execute", + ) + parser.add_argument( + "--pytest-numprocs", + type=int, + default=4, + help="Number of parallel processes for pytest", ) - args = parser.parse_args() + args, unknown = parser.parse_known_args() + + args.cmake_args = [] + args.ctest_args = [] is_monorepo, monorepo_root, project_root = detect_repo_structure() @@ -220,113 +320,83 @@ def main(): else: args.site = os.uname().nodename - coverage_path = Path(args.coverage_file) - if not coverage_path.is_absolute(): - if not coverage_path.exists(): - coverage_path = project_root / args.coverage_file - - if not coverage_path.exists(): - print(f"ERROR: Coverage file not found: {coverage_path}", file=sys.stderr) - print(f" Searched in: {Path(args.coverage_file).absolute()}") - print(f" And in: {project_root / args.coverage_file}") - return 1 - - try: - import xml.etree.ElementTree as ET - - tree = ET.parse(coverage_path) - root = tree.getroot() - if root.tag != "coverage": - print( - f"ERROR: File does not appear to be a coverage XML file " - f"(root tag: {root.tag})", - file=sys.stderr, - ) - return 1 - line_rate = float(root.get("line-rate", 0)) * 100 - print(f"Line Coverage: {line_rate:.1f}%") - except Exception as e: - print(f"ERROR: Could not parse coverage XML file: {e}", file=sys.stderr) - return 1 - - args.coverage_file = str(coverage_path.absolute()) - args.source_dir = str(Path(args.source_dir).absolute()) - args.binary_dir = str(Path(args.binary_dir).absolute()) + source_dir = Path(args.source_dir).absolute() + binary_dir = Path(args.binary_dir).absolute() + print("=" * 80) + print("rocprofiler-compute CI Dashboard") + print("=" * 80) print(f"Repository type: {'Monorepo' if is_monorepo else 'Standalone'}") - print(f"Project root: {project_root}") - print(f"Uploading coverage file: {args.coverage_file}") + print(f"Source directory: {source_dir}") + print(f"Binary directory: {binary_dir}") print(f"Build name: {args.build_name}") - print(f"Project: {args.project_name}") + print(f"Dashboard mode: {args.mode}") + print(f"CDash project: {args.project_name}") print(f"Site: {args.site}") - print(f"Submit URL: {args.submit_url}") + print("=" * 80) - # Ensure build directory exists - os.makedirs(args.binary_dir, exist_ok=True) - - # Copy CTestConfig.cmake if it exists in source - source_ctest_config = Path(args.source_dir) / "CTestConfig.cmake" - if source_ctest_config.exists(): - shutil.copy2(source_ctest_config, Path(args.binary_dir) / "CTestConfig.cmake") - print("Copied CTestConfig.cmake to build directory") - - script_content = create_ctest_script(args) + script_content = generate_ctest_dashboard_script(args, source_dir, binary_dir) if args.dry_run: - print("\nGenerated CTest script:") - print("=" * 50) + print("\nGenerated CTest Dashboard Script:") + print("=" * 80) print(script_content) + print("=" * 80) return 0 + binary_dir.mkdir(parents=True, exist_ok=True) + + with tempfile.NamedTemporaryFile( + mode="w", suffix=".cmake", delete=False, dir=binary_dir + ) as f: + f.write(script_content) + script_path = f.name + + print(f"\nDashboard script: {script_path}") + print("=" * 80) + try: - with tempfile.NamedTemporaryFile(mode="w", suffix=".cmake", delete=False) as f: - f.write(script_content) - script_path = f.name - - print(f"\nScript written to: {script_path}") - - original_dir = os.getcwd() - os.chdir(args.source_dir) - cmd = ["ctest", "-S", script_path, "-V"] - print(f"Executing: {' '.join(cmd)}") - print(f"Working directory: {os.getcwd()}") + print(f"Running: {' '.join(cmd)}") + print("=" * 80) + print() - result = subprocess.run(cmd, capture_output=True, text=True) - - if result.stdout: - print("\nSTDOUT:") - print(result.stdout) - - if result.stderr: - print("\nSTDERR:") - print(result.stderr) - - os.chdir(original_dir) - - if result.returncode != 0: - print(f"\nCTest failed with return code: {result.returncode}") - return result.returncode - - print("\n✅ Coverage successfully uploaded to CDash!") - cdash_url = args.submit_url.replace( - "/submit.php?project=", "/index.php?project=" + process = subprocess.Popen( + cmd, + cwd=source_dir, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + universal_newlines=True, ) - print(f"View results at: {cdash_url}") - return 0 + + for line in process.stdout: + print(line, end="") + + returncode = process.wait() + + print() + print("=" * 80) + if returncode == 0: + print("✅ Dashboard completed successfully!") + else: + print(f"⚠️ Dashboard completed with return code: {returncode}") + print("=" * 80) + + return returncode except Exception as e: - print(f"Error executing CTest script: {e}", file=sys.stderr) + print(f"\n❌ Error executing dashboard script: {e}", file=sys.stderr) import traceback traceback.print_exc() return 1 finally: - if "script_path" in locals(): - try: - os.unlink(script_path) - except Exception: - pass + try: + os.unlink(script_path) + except Exception: + pass if __name__ == "__main__": diff --git a/projects/rocprofiler-compute/tools/update-coverage.sh b/projects/rocprofiler-compute/tools/update-coverage.sh deleted file mode 100755 index 8506e4a0fe..0000000000 --- a/projects/rocprofiler-compute/tools/update-coverage.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -############################################################################## -# MIT License -# -# Copyright (c) 2025 Advanced Micro Devices, Inc. All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -############################################################################## - -# generate_coverage.sh - -set -e - -PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -BUILD_DIR="$PROJECT_ROOT/build" -COVERAGE_FILE="$PROJECT_ROOT/coverage/Coverage.xml" - -echo "=== Generating Coverage for Mainline Promotion ===" - -echo "Setting up clean build..." -rm -rf "$BUILD_DIR" -mkdir -p "$BUILD_DIR" -cd "$BUILD_DIR" - -echo "Configuring with coverage enabled..." -cmake -DENABLE_COVERAGE=ON -DENABLE_TESTS=ON -DPYTEST_NUMPROCS=8 .. - -echo "Building..." -make -j$(nproc) - -echo "Running ALL tests to generate coverage (this may take a while)..." -ctest --verbose --output-on-failure --parallel 1 || { - echo "WARNING: Some tests failed, but continuing with coverage generation" -} - -echo "Generating coverage report..." -ctest -R generate_coverage_report --output-on-failure --parallel 2 - -if [ ! -f "coverage.xml" ]; then - echo "ERROR: coverage.xml not generated" - exit 1 -fi - -COVERAGE_INFO=$(python3 -c " -import xml.etree.ElementTree as ET -tree = ET.parse('coverage.xml') -root = tree.getroot() -line_rate = float(root.get('line-rate', 0)) * 100 -print(f'{line_rate:.1f}%') -") - -mkdir -p "$PROJECT_ROOT/coverage" -cp coverage.xml "$COVERAGE_FILE" - -echo "" -echo "=== Coverage Generated Successfully ===" -echo "Line Coverage: $COVERAGE_INFO" -echo "File: $COVERAGE_FILE" -echo "" -echo "Next steps:" -echo "1. git add $COVERAGE_FILE" -echo "2. git commit -m 'Update coverage: $COVERAGE_INFO'" -echo "3. Proceed with push to develop" -echo "4. CDash upload will happen automatically on push" -echo ""