From 26b0e2bb92caf2d16cabe455792350f20d6f42ca Mon Sep 17 00:00:00 2001 From: saurabh Date: Thu, 4 Dec 2025 20:55:21 +0530 Subject: [PATCH] Fixed #36620 -- Fixed workflow to summarize coverage in PRs. Follow-up to a89183e63844a937aacd3ddb73c4952ef869d2cc, which was reverted in e4c4a178aa642f8493b7ae2c0ad58527af51f67e because a change to the workflow trigger resulted in the PR branch not being checked out. We used this opportunity to reimplement the coverage tracing and coverage commenting in a two-workflow pattern with more granular permissions. To reduce duplicative workflows, we removed the existing python test workflow on PRs, at least until we run more distinct configurations on GitHub actions. The run with coverage tracing enabled is sufficient for now. The existing workflow still runs on pushes to main. We can revisit when adding more test configurations. --- .github/workflows/coverage_comment.yml | 72 +++++++++++++++++++++++++ .github/workflows/coverage_tests.yml | 75 ++++++++++++++++++++++++++ .github/workflows/tests.yml | 1 + zizmor.yml | 1 + 4 files changed, 149 insertions(+) create mode 100644 .github/workflows/coverage_comment.yml create mode 100644 .github/workflows/coverage_tests.yml diff --git a/.github/workflows/coverage_comment.yml b/.github/workflows/coverage_comment.yml new file mode 100644 index 0000000000..d63e6f4a75 --- /dev/null +++ b/.github/workflows/coverage_comment.yml @@ -0,0 +1,72 @@ +name: Coverage Comment + +on: + workflow_run: + workflows: ["Coverage Tests"] + types: + - completed + +permissions: + contents: read + pull-requests: write + +jobs: + comment: + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' && + github.repository == 'django/django' && + github.event.workflow_run.pull_requests[0] != null + name: Post Coverage Comment + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Download diff coverage report + uses: actions/download-artifact@v4 + with: + name: diff-coverage-report-${{ github.event.workflow_run.pull_requests[0].number }} + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Post/update PR comment + env: + PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} + uses: actions/github-script@v8 + with: + script: | + const fs = require('fs'); + const reportPath = 'diff-cover-report.md'; + let body = 'No coverage data available.'; + if (fs.existsSync(reportPath)) { + body = fs.readFileSync(reportPath, 'utf8'); + } + const commentBody = '### 📊 Coverage Report for Changed Files\n\n```\n' + body + '\n```\n\n**Note:** Missing lines are warnings only. Some lines may not be covered by SQLite tests as they are database-specific.\n\nFor more information about code coverage on pull requests, see the [contributing documentation](https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/unit-tests/#code-coverage-on-pull-requests).'; + + const prNumber = parseInt(process.env.PR_NUMBER); + if (isNaN(prNumber)) { + core.setFailed('PR number is not available or invalid.'); + return; + } + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + for (const c of comments) { + if ((c.body || '').includes('📊 Coverage Report for Changed Files')) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: c.id, + }); + } + } + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody, + }); diff --git a/.github/workflows/coverage_tests.yml b/.github/workflows/coverage_tests.yml new file mode 100644 index 0000000000..af463bb295 --- /dev/null +++ b/.github/workflows/coverage_tests.yml @@ -0,0 +1,75 @@ +name: Coverage Tests + +on: + pull_request: + paths-ignore: + - 'docs/**' + - '**/*.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + coverage: + if: github.repository == 'django/django' + name: Coverage Tests (Windows) + runs-on: windows-latest + timeout-minutes: 60 + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.14' + cache: 'pip' + cache-dependency-path: 'tests/requirements/py3.txt' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip wheel + python -m pip install -r tests/requirements/py3.txt -e . + python -m pip install 'coverage[toml]' diff-cover + + - name: Run tests with coverage + env: + PYTHONPATH: ${{ github.workspace }}/tests + COVERAGE_PROCESS_START: ${{ github.workspace }}/tests/.coveragerc + RUNTESTS_DIR: ${{ github.workspace }}/tests + run: | + python -Wall tests/runtests.py -v2 + + - name: Generate coverage report + if: success() + env: + COVERAGE_RCFILE: ${{ github.workspace }}/tests/.coveragerc + RUNTESTS_DIR: ${{ github.workspace }}/tests + run: | + python -m coverage combine + python -m coverage report --show-missing + python -m coverage xml -o tests/coverage.xml + + - name: Generate diff coverage report + if: success() + run: | + if (Test-Path 'tests/coverage.xml') { + diff-cover tests/coverage.xml --compare-branch=origin/main --fail-under=0 > diff-cover-report.md + } else { + Set-Content -Path diff-cover-report.md -Value 'No coverage data available.' + } + + - name: Upload diff coverage report + if: success() + uses: actions/upload-artifact@v4 + with: + name: diff-coverage-report-${{ github.event.pull_request.number }} + path: diff-cover-report.md + retention-days: 1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b709ed5145..079fae6328 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,6 +19,7 @@ permissions: jobs: windows: + if: github.event_name == 'push' runs-on: windows-latest strategy: matrix: diff --git a/zizmor.yml b/zizmor.yml index 76e53f73cc..23630337b4 100644 --- a/zizmor.yml +++ b/zizmor.yml @@ -1,6 +1,7 @@ rules: dangerous-triggers: ignore: + - coverage_comment.yml - labels.yml - new_contributor_pr.yml unpinned-uses: