From f3a2bb07a497088bec9534bdf11e0770cf13b14f Mon Sep 17 00:00:00 2001 From: jamessiddeley-amd Date: Tue, 2 Sep 2025 11:21:40 -0400 Subject: [PATCH] [rocprofiler-compute] added ctest coverage and cdash submission (#366) * added cdash automatic CI upload * added cdash automatic CI upload * tweaked wording * changed nightly to continuous * removed unnecessary dry-run arg * updated README.md * edited workflow description * update coverage * formatted cmakelists.txt * ruff formatting and update coverage --- .../workflows/rocprofiler-compute-cdash.yml | 89 + projects/rocprofiler-compute/CMakeLists.txt | 42 +- .../rocprofiler-compute/coverage/README.md | 77 + .../coverage/coverage-latest.xml | 5298 +++++++++++++++++ projects/rocprofiler-compute/utils/run-ci.py | 257 + .../utils/update-coverage.sh | 102 + 6 files changed, 5864 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/rocprofiler-compute-cdash.yml create mode 100644 projects/rocprofiler-compute/coverage/README.md create mode 100644 projects/rocprofiler-compute/coverage/coverage-latest.xml create mode 100755 projects/rocprofiler-compute/utils/run-ci.py create mode 100755 projects/rocprofiler-compute/utils/update-coverage.sh diff --git a/.github/workflows/rocprofiler-compute-cdash.yml b/.github/workflows/rocprofiler-compute-cdash.yml new file mode 100644 index 0000000000..7f7b0638b5 --- /dev/null +++ b/.github/workflows/rocprofiler-compute-cdash.yml @@ -0,0 +1,89 @@ +name: rocprofiler-compute CDash Coverage Upload + +on: + push: + branches: [ develop ] + paths: + - 'projects/rocprofiler-compute/coverage/coverage-latest.xml' + workflow_dispatch: + inputs: + coverage_file: + description: 'Path to coverage XML file' + required: false + default: 'projects/rocprofiler-compute/coverage/coverage-latest.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.8' + + - name: Check Coverage File Exists + working-directory: projects/rocprofiler-compute + run: | + COVERAGE_FILE="${{ github.event.inputs.coverage_file || 'coverage/coverage-latest.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/projects/rocprofiler-compute/CMakeLists.txt b/projects/rocprofiler-compute/CMakeLists.txt index 858655a377..9525ed5ee8 100644 --- a/projects/rocprofiler-compute/CMakeLists.txt +++ b/projects/rocprofiler-compute/CMakeLists.txt @@ -170,13 +170,17 @@ endif() message(STATUS "Enable tests compilation: ${ENABLE_TESTS}") enable_testing() +include(CTest) option(ENABLE_COVERAGE "Enable code coverage" OFF) set(COV_OPTION "") if(${ENABLE_COVERAGE}) set(COV_OPTION "--cov=src" "--cov-append" "--cov-report=term-missing" "--cov-report=lcov:tests/coverage.info") - # "--cov-report=term-missing" "--cov-report=xml:tests/coverage.xml") + + set(CTEST_COVERAGE_COMMAND "python3") + set(CTEST_COVERAGE_EXTRA_FLAGS "-m" "coverage" "xml" "-o" + "${CMAKE_BINARY_DIR}/coverage.xml") endif() message(STATUS "Code coverage: ${ENABLE_COVERAGE}") @@ -351,6 +355,42 @@ add_test( ${COV_OPTION} ${PROJECT_SOURCE_DIR}/tests/test_autogen_config.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +# ----------------------------------- +# Generate coverage tests +# ----------------------------------- + +if(${ENABLE_COVERAGE}) + set(ALL_TEST_NAMES + test_profile_kernel_execution + test_profile_dispatch + test_profile_mem + test_profile_join + test_profile_sort + test_profile_misc + test_profile_section + test_profile_sets_func + test_analyze_commands + test_analyze_workloads + test_L1_cache_counters + test_num_xcds_spec_class + test_num_xcds_cli_output + test_db_connector + test_utils + test_autogen_config) + + string(REPLACE ";" ";" ALL_TESTS_STRING "${ALL_TEST_NAMES}") + + add_test( + NAME generate_coverage_report + COMMAND ${Python3_EXECUTABLE} -m coverage xml -o ${CMAKE_BINARY_DIR}/coverage.xml + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + + set_tests_properties( + generate_coverage_report + PROPERTIES DEPENDS "${ALL_TESTS_STRING}" LABELS "coverage" ENVIRONMENT + "COVERAGE_FILE=${PROJECT_SOURCE_DIR}/.coverage") +endif() + # --------- # Install # --------- diff --git a/projects/rocprofiler-compute/coverage/README.md b/projects/rocprofiler-compute/coverage/README.md new file mode 100644 index 0000000000..52ab47cf58 --- /dev/null +++ b/projects/rocprofiler-compute/coverage/README.md @@ -0,0 +1,77 @@ +# 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 +│ ├── utils/ +│ │ ├── 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 +./utils/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 +``` \ No newline at end of file diff --git a/projects/rocprofiler-compute/coverage/coverage-latest.xml b/projects/rocprofiler-compute/coverage/coverage-latest.xml new file mode 100644 index 0000000000..8acd8b241a --- /dev/null +++ b/projects/rocprofiler-compute/coverage/coverage-latest.xml @@ -0,0 +1,5298 @@ + + + + + + /app/projects/rocprofiler-compute + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/rocprofiler-compute/utils/run-ci.py b/projects/rocprofiler-compute/utils/run-ci.py new file mode 100755 index 0000000000..641c6d2e9c --- /dev/null +++ b/projects/rocprofiler-compute/utils/run-ci.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 +############################################################################## +# 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. +############################################################################## + +""" +CI script to upload coverage XML files to CDash +""" + +import argparse +import os +import subprocess +import sys +import tempfile +from pathlib import Path + + +def detect_repo_structure(): + """Detect if in monorepo or standalone structure""" + cwd = Path.cwd() + + if "projects/rocprofiler-compute" in str(cwd): + parts = cwd.parts + idx = parts.index("rocprofiler-compute") + if idx > 0 and parts[idx - 1] == "projects": + monorepo_root = Path(*parts[: idx - 1]) + project_root = monorepo_root / "projects" / "rocprofiler-compute" + return True, monorepo_root, project_root + + if (cwd / "CMakeLists.txt").exists(): + with open(cwd / "CMakeLists.txt", "r") as f: + content = f.read() + if ( + "project(rocprofiler-compute" in content + or "project(\n rocprofiler-compute" in content + ): + return False, None, cwd + + return False, None, cwd + + +def create_ctest_script(args): + """Generate a CTest script for uploading coverage data""" + + script_content = f""" +cmake_minimum_required(VERSION 3.19) + +set(CTEST_PROJECT_NAME "{args.project_name}") +set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") +set(CTEST_DROP_SITE_CDASH TRUE) + +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_SITE "{args.site}") +set(CTEST_BUILD_NAME "{args.build_name}") +set(CTEST_SOURCE_DIRECTORY "{args.source_dir}") +set(CTEST_BINARY_DIRECTORY "{args.binary_dir}") + +ctest_start({args.mode}) + +set(CTEST_COVERAGE_COMMAND "python3") +set(CTEST_COVERAGE_EXTRA_FLAGS "-m" "coverage" "xml") + +file(COPY "{args.coverage_file}" DESTINATION "${{CTEST_BINARY_DIRECTORY}}") +ctest_coverage() +ctest_submit(PARTS Coverage RETRY_COUNT 3 RETRY_DELAY 5) +""" + 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" + ) + + # required + parser.add_argument( + "--coverage-file", required=True, help="Path to coverage XML file" + ) + 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" + ) + parser.add_argument( + "--submit-url", + default="https://my.cdash.org/submit.php?project=rocprofiler-compute", + help="CDash submission URL", + ) + parser.add_argument( + "--cdash-host", default="my.cdash.org", help="CDash host (for older CMake)" + ) + parser.add_argument( + "--submit-path", + default="/submit.php?project=rocprofiler-compute", + help="CDash submission path (for older CMake)", + ) + parser.add_argument( + "--site", + default=None, + help="Site name for CDash (auto-detected if not provided)", + ) + parser.add_argument( + "--source-dir", + default=None, + help="Source directory path (auto-detected if not provided)", + ) + parser.add_argument( + "--binary-dir", + default=None, + help="Binary directory path (defaults to source-dir/build)", + ) + parser.add_argument( + "--mode", + default="Experimental", + choices=["Experimental", "Nightly", "Continuous"], + help="CTest dashboard mode", + ) + args = parser.parse_args() + + is_monorepo, monorepo_root, project_root = detect_repo_structure() + + if not args.source_dir: + args.source_dir = str(project_root) + + if not args.binary_dir: + args.binary_dir = os.path.join(args.source_dir, "build") + + if not args.site: + if is_monorepo: + args.site = f"Monorepo-{os.uname().nodename}" + 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 + + 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()) + + 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"Build name: {args.build_name}") + print(f"Project: {args.project_name}") + print(f"Site: {args.site}") + print(f"Submit URL: {args.submit_url}") + + try: + import xml.etree.ElementTree as ET + + tree = ET.parse(args.coverage_file) + root = tree.getroot() + line_rate = float(root.get("line-rate", 0)) * 100 + print(f"Line Coverage: {line_rate:.1f}%") + except Exception as e: + print(f"Warning: Could not parse coverage percentage: {e}") + + script_content = create_ctest_script(args) + + 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()}") + + 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!") + print( + f"View results at: { + args.submit_url.replace('/submit.php?project=', '/index.php?project=') + }" + ) + return 0 + + except Exception as e: + print(f"Error executing CTest 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 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/projects/rocprofiler-compute/utils/update-coverage.sh b/projects/rocprofiler-compute/utils/update-coverage.sh new file mode 100755 index 0000000000..fe7b0f524f --- /dev/null +++ b/projects/rocprofiler-compute/utils/update-coverage.sh @@ -0,0 +1,102 @@ +#!/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 for develop branch - stores file in repo + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [[ "$SCRIPT_DIR" == */projects/rocprofiler-compute/* ]]; then + PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + MONOREPO_ROOT="$(cd "$PROJECT_ROOT/../.." && pwd)" + IS_MONOREPO=true +else + PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + MONOREPO_ROOT="" + IS_MONOREPO=false +fi + +BUILD_DIR="$PROJECT_ROOT/build" +COVERAGE_FILE="$PROJECT_ROOT/coverage/coverage-latest.xml" + +echo "=== Generating Coverage for rocprofiler-compute ===" +echo "Project root: $PROJECT_ROOT" +if [ "$IS_MONOREPO" = true ]; then + echo "Monorepo root: $MONOREPO_ROOT" +fi + +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..." +if ctest -R generate_coverage_report --output-on-failure --parallel 2; then + echo "Coverage report generated via ctest" +else + echo "Trying alternative coverage generation..." + cd "$PROJECT_ROOT" + python3 -m coverage combine || true + python3 -m coverage xml -o "$BUILD_DIR/coverage.xml" + cd "$BUILD_DIR" +fi + +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 "Coverage file generated: coverage/coverage-latest.xml" +echo "To update official coverage:" +echo " 1. Commit this file to develop branch" +echo " 2. GitHub Actions will automatically upload to CDash"