From fa860c5272dedb50dae95dae22b8ab1c3ec29d00 Mon Sep 17 00:00:00 2001 From: jamessiddeley-amd Date: Fri, 5 Sep 2025 11:55:08 -0400 Subject: [PATCH] [rocprof-compute] Fixed CDash compute code coverage upload (#863) * Test CDash upload fixes * Test CDash upload fixes + rename * fix run-ci.py script * fix run-ci.py script * fix run-ci.py script * fix run-ci.py script * fixed workflow * renamed coverage file * fixed run-ci.py script * edited workflow file * edited script desc * Update Coverage.xml --- .../workflows/rocprofiler-compute-cdash.yml | 6 +- .../{coverage-latest.xml => Coverage.xml} | 8 +- projects/rocprofiler-compute/utils/run-ci.py | 101 +++++++++++++++--- .../utils/update-coverage.sh | 43 ++------ 4 files changed, 107 insertions(+), 51 deletions(-) rename projects/rocprofiler-compute/coverage/{coverage-latest.xml => Coverage.xml} (99%) diff --git a/.github/workflows/rocprofiler-compute-cdash.yml b/.github/workflows/rocprofiler-compute-cdash.yml index 7f7b0638b5..669d73e425 100644 --- a/.github/workflows/rocprofiler-compute-cdash.yml +++ b/.github/workflows/rocprofiler-compute-cdash.yml @@ -4,13 +4,13 @@ on: push: branches: [ develop ] paths: - - 'projects/rocprofiler-compute/coverage/coverage-latest.xml' + - '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-latest.xml' + default: 'projects/rocprofiler-compute/coverage/Coverage.xml' concurrency: group: rocprofiler-compute-cdash-${{ github.ref }} @@ -35,7 +35,7 @@ jobs: - name: Check Coverage File Exists working-directory: projects/rocprofiler-compute run: | - COVERAGE_FILE="${{ github.event.inputs.coverage_file || 'coverage/coverage-latest.xml' }}" + 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 diff --git a/projects/rocprofiler-compute/coverage/coverage-latest.xml b/projects/rocprofiler-compute/coverage/Coverage.xml similarity index 99% rename from projects/rocprofiler-compute/coverage/coverage-latest.xml rename to projects/rocprofiler-compute/coverage/Coverage.xml index 5c0496389b..478d115bda 100644 --- a/projects/rocprofiler-compute/coverage/coverage-latest.xml +++ b/projects/rocprofiler-compute/coverage/Coverage.xml @@ -1,5 +1,5 @@ - + @@ -2105,7 +2105,7 @@ - + @@ -4185,7 +4185,7 @@ - + @@ -4340,7 +4340,7 @@ - + diff --git a/projects/rocprofiler-compute/utils/run-ci.py b/projects/rocprofiler-compute/utils/run-ci.py index 1182df46be..8c044faeda 100755 --- a/projects/rocprofiler-compute/utils/run-ci.py +++ b/projects/rocprofiler-compute/utils/run-ci.py @@ -29,6 +29,7 @@ CI script to upload coverage XML files to CDash import argparse import os +import shutil import subprocess import sys import tempfile @@ -82,14 +83,63 @@ set(CTEST_BUILD_NAME "{args.build_name}") set(CTEST_SOURCE_DIRECTORY "{args.source_dir}") set(CTEST_BINARY_DIRECTORY "{args.binary_dir}") +file(MAKE_DIRECTORY "${{CTEST_BINARY_DIRECTORY}}") + +if(NOT EXISTS "${{CTEST_BINARY_DIRECTORY}}/CMakeCache.txt") + file(WRITE "${{CTEST_BINARY_DIRECTORY}}/CMakeCache.txt" + "CMAKE_PROJECT_NAME:STATIC={args.project_name}\\n") +endif() + +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) +") + ctest_start({args.mode}) -set(CTEST_COVERAGE_COMMAND "python3") -set(CTEST_COVERAGE_EXTRA_FLAGS "-m" "coverage" "xml") +set(COVERAGE_SRC_FILE "{args.coverage_file}") +set(COVERAGE_DEST_FILE "${{CTEST_BINARY_DIRECTORY}}/coverage.xml") + +if(NOT EXISTS "${{COVERAGE_SRC_FILE}}") + message(FATAL_ERROR "Coverage file not found: ${{COVERAGE_SRC_FILE}}") +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}}") +endif() + +message(STATUS "Processing coverage file: ${{COVERAGE_DEST_FILE}}") + +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") -file(COPY "{args.coverage_file}" DESTINATION "${{CTEST_BINARY_DIRECTORY}}") ctest_coverage() -ctest_submit(PARTS Coverage RETRY_COUNT 3 RETRY_DELAY 5) + +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}}") +endif() + +message(STATUS "Successfully submitted coverage to CDash") """ return script_content @@ -150,6 +200,10 @@ def main(): choices=["Experimental", "Nightly", "Continuous"], help="CTest dashboard mode", ) + parser.add_argument( + "--dry-run", action="store_true", help="Generate script but don't execute" + ) + args = parser.parse_args() is_monorepo, monorepo_root, project_root = detect_repo_structure() @@ -177,6 +231,24 @@ def main(): 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()) @@ -189,18 +261,23 @@ def main(): print(f"Site: {args.site}") print(f"Submit URL: {args.submit_url}") - try: - import xml.etree.ElementTree as ET + # Ensure build directory exists + os.makedirs(args.binary_dir, exist_ok=True) - 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}") + # 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) + if args.dry_run: + print("\nGenerated CTest script:") + print("=" * 50) + print(script_content) + return 0 + try: with tempfile.NamedTemporaryFile(mode="w", suffix=".cmake", delete=False) as f: f.write(script_content) diff --git a/projects/rocprofiler-compute/utils/update-coverage.sh b/projects/rocprofiler-compute/utils/update-coverage.sh index fe7b0f524f..6ab6f93cd1 100755 --- a/projects/rocprofiler-compute/utils/update-coverage.sh +++ b/projects/rocprofiler-compute/utils/update-coverage.sh @@ -23,29 +23,15 @@ # THE SOFTWARE. ############################################################################## -# generate coverage for develop branch - stores file in repo +# generate_coverage.sh 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 - +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" BUILD_DIR="$PROJECT_ROOT/build" -COVERAGE_FILE="$PROJECT_ROOT/coverage/coverage-latest.xml" +COVERAGE_FILE="$PROJECT_ROOT/coverage/Coverage.xml" -echo "=== Generating Coverage for rocprofiler-compute ===" -echo "Project root: $PROJECT_ROOT" -if [ "$IS_MONOREPO" = true ]; then - echo "Monorepo root: $MONOREPO_ROOT" -fi +echo "=== Generating Coverage for Mainline Promotion ===" echo "Setting up clean build..." rm -rf "$BUILD_DIR" @@ -64,15 +50,7 @@ ctest --verbose --output-on-failure --parallel 1 || { } 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 +ctest -R generate_coverage_report --output-on-failure --parallel 2 if [ ! -f "coverage.xml" ]; then echo "ERROR: coverage.xml not generated" @@ -95,8 +73,9 @@ 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" +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 "" \ No newline at end of file