From 5be446239573b083da67b607e738f7501457a0b5 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Mon, 3 Nov 2025 09:42:55 -0500 Subject: [PATCH] Update sonar and CI (#16153) * actually upload PR coverage reports and inject PR number if report is generated from a PR * upload general report of devel on merge and make things kinda pretty --- .github/workflows/ci.yml | 19 +++ .github/workflows/sonarcloud_pr.yml | 255 ++++++++++++++++++++++------ 2 files changed, 220 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea1b5e326f..608a9f75d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,17 @@ jobs: AWX_DOCKER_CMD='${{ matrix.tests.command }}' make docker-runner + - name: Inject PR number into coverage.xml + if: >- + !cancelled() + && github.event_name == 'pull_request' + && steps.make-run.outputs.cov-report-files != '' + run: | + if [ -f "reports/coverage.xml" ]; then + sed -i '2i' reports/coverage.xml + echo "Injected PR number ${{ github.event.pull_request.number }} into coverage.xml" + fi + - name: Upload test coverage to Codecov if: >- !cancelled() @@ -96,6 +107,14 @@ jobs: }} token: ${{ secrets.CODECOV_TOKEN }} + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.tests.name }}-artifacts + path: reports/coverage.xml + retention-days: 5 + - name: Upload awx jUnit test reports if: >- !cancelled() diff --git a/.github/workflows/sonarcloud_pr.yml b/.github/workflows/sonarcloud_pr.yml index 192066707f..19eecd8b03 100644 --- a/.github/workflows/sonarcloud_pr.yml +++ b/.github/workflows/sonarcloud_pr.yml @@ -1,85 +1,232 @@ ---- -name: SonarQube +# SonarCloud Analysis Workflow for awx +# +# This workflow runs SonarCloud analysis triggered by CI workflow completion. +# It is split into two separate jobs for clarity and maintainability: +# +# FLOW: CI completes → workflow_run triggers this workflow → appropriate job runs +# +# JOB 1: sonar-pr-analysis (for PRs) +# - Triggered by: workflow_run (CI on pull_request) +# - Steps: Download coverage → Get PR info → Get changed files → Run SonarCloud PR analysis +# - Scans: All changed files in the PR (Python, YAML, JSON, etc.) +# - Quality gate: Focuses on new/changed code in PR only +# +# JOB 2: sonar-branch-analysis (for long-lived branches) +# - Triggered by: workflow_run (CI on push to devel) +# - Steps: Download coverage → Run SonarCloud branch analysis +# - Scans: Full codebase +# - Quality gate: Focuses on overall project health +# +# This ensures coverage data is always available from CI before analysis runs. +# +# What files are scanned: +# - All files in the repository that SonarCloud can analyze +# - Excludes: tests, scripts, dev environments, external collections (see sonar-project.properties) + +# With much help from: +# https://community.sonarsource.com/t/how-to-use-sonarcloud-with-a-forked-repository-on-github/7363/30 +# https://community.sonarsource.com/t/how-to-use-sonarcloud-with-a-forked-repository-on-github/7363/32 +name: SonarCloud on: - workflow_run: + workflow_run: # This is triggered by CI being completed. workflows: - CI types: - completed - permissions: read-all - jobs: - sonarqube: + sonar-pr-analysis: + name: SonarCloud PR Analysis runs-on: ubuntu-latest - if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' + if: | + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'pull_request' && + github.repository == 'ansible/awx' steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - show-progress: false + - uses: actions/checkout@v4 - - name: Download coverage report artifact - uses: actions/download-artifact@v4 + # Download all individual coverage artifacts from CI workflow + - name: Download coverage artifacts + uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 with: - name: coverage-report - path: reports/ - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} + github_token: ${{ secrets.GITHUB_TOKEN }} + workflow: CI + run_id: ${{ github.event.workflow_run.id }} + pattern: api-test-artifacts - - name: Download PR number artifact - uses: actions/download-artifact@v4 - with: - name: pr-number - path: . - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - - - name: Extract PR number - run: | - cat pr-number.txt - echo "PR_NUMBER=$(cat pr-number.txt)" >> $GITHUB_ENV - - - name: Get PR info - uses: octokit/request-action@v2.x - id: pr_info - with: - route: GET /repos/{repo}/pulls/{number} - repo: ${{ github.event.repository.full_name }} - number: ${{ env.PR_NUMBER }} + # Extract PR metadata from workflow_run event + - name: Set PR metadata and prepare files for analysis env: + COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} + REPO_NAME: ${{ github.event.repository.full_name }} + HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Set PR info into env run: | - echo "PR_BASE=${{ fromJson(steps.pr_info.outputs.data).base.ref }}" >> $GITHUB_ENV - echo "PR_HEAD=${{ fromJson(steps.pr_info.outputs.data).head.ref }}" >> $GITHUB_ENV + # Find all downloaded coverage XML files + coverage_files=$(find . -name "coverage.xml" -type f | tr '\n' ',' | sed 's/,$//') + echo "Found coverage files: $coverage_files" + echo "COVERAGE_PATHS=$coverage_files" >> $GITHUB_ENV + + # Extract PR number from first coverage.xml file found + first_coverage=$(find . -name "coverage.xml" -type f | head -1) + if [ -f "$first_coverage" ]; then + PR_NUMBER=$(grep -m 1 '