This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch feat/publish-python-junit-test-results in repository https://gitbox.apache.org/repos/asf/superset.git
commit 2f0e3bce25197dbe1a6ddb9bb0c9e33893496b01 Author: rusackas <[email protected]> AuthorDate: Mon Jul 27 22:00:00 2026 -0700 feat(ci): publish Python unit test results as PR check annotations Right now a red check on the Python-Unit job just says "failed" and sends contributors to raw pytest logs to find out which test broke. Add EnricoMi/publish-unit-test-result-action so failing tests get annotated inline on the PR diff instead. pytest already writes JUnit XML for free via --junit-xml; wire that up for all three pytest invocations in the unit-tests job and upload it as an artifact (uploaded even on failure, since that's exactly when it's needed). A second workflow, triggered via workflow_run (same pattern already used for the translation-regression bot), downloads that artifact and publishes the check run. workflow_run always runs in the base-branch context, so it can safely be granted checks:write even for PRs from forks or Dependabot, without ever checking out untrusted PR code. Scoped to Python-Unit only for now; the frontend's 8-way jest shard and the Python integration test matrix are natural follow-ups once this pattern proves out. --- .../workflows/superset-python-unittest-report.yml | 65 ++++++++++++++++++++++ .github/workflows/superset-python-unittest.yml | 33 ++++++++++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/.github/workflows/superset-python-unittest-report.yml b/.github/workflows/superset-python-unittest-report.yml new file mode 100644 index 00000000000..46d86c0d170 --- /dev/null +++ b/.github/workflows/superset-python-unittest-report.yml @@ -0,0 +1,65 @@ +name: Python Unit Test Results + +on: + # zizmor: ignore[dangerous-triggers] - runs in base-branch context and only consumes artifacts uploaded by Python-Unit; never checks out PR code (see note below) + workflow_run: + workflows: ["Python-Unit"] + types: [completed] + +# This workflow publishes a check run annotating failing Python unit tests +# inline on the PR diff, using JUnit XML uploaded by the Python-Unit workflow. +# It uses the workflow_run trigger so that it always runs in the base-branch +# context and can safely be granted write permissions, even for PRs from +# forks or Dependabot. +# +# IMPORTANT: This workflow must NEVER check out code from the PR branch. All +# data comes from artifacts uploaded by the Python-Unit workflow. +permissions: + contents: read + checks: write + issues: read + actions: read + +jobs: + report: + runs-on: ubuntu-26.04 + timeout-minutes: 10 + if: > + github.event.workflow_run.conclusion == 'success' || + github.event.workflow_run.conclusion == 'failure' + steps: + # Fails soft (continue-on-error) because the source unit-tests job is + # itself gated on change detection: a docs-only PR skips it entirely, + # so there is nothing to download or report on. + - name: Download JUnit results + id: download + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + pattern: "junit-results-*" + path: artifacts + merge-multiple: true + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Download event file + id: download-event + if: steps.download.outcome == 'success' + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: "Event File" + path: event + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish test results + if: steps.download.outcome == 'success' && steps.download-event.outcome == 'success' + uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2.24.0 + with: + commit: ${{ github.event.workflow_run.head_sha }} + event_file: event/event.json + event_name: ${{ github.event.workflow_run.event }} + files: "artifacts/**/*.xml" + check_name: "Python Unit Test Results" + comment_mode: "off" diff --git a/.github/workflows/superset-python-unittest.yml b/.github/workflows/superset-python-unittest.yml index 64f3c683ae6..728f06384d9 100644 --- a/.github/workflows/superset-python-unittest.yml +++ b/.github/workflows/superset-python-unittest.yml @@ -74,14 +74,14 @@ jobs: SUPERSET_TESTENV: true SUPERSET_SECRET_KEY: not-a-secret run: | - pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear --maxfail=50 + pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear --maxfail=50 --junit-xml=test-results/junit-unit.xml - name: Python 100% coverage unit tests env: SUPERSET_TESTENV: true SUPERSET_SECRET_KEY: not-a-secret run: | - pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100 - pytest --durations-min=0.5 --cov=superset/semantic_layers/ ./tests/unit_tests/semantic_layers/ --cache-clear --cov-fail-under=100 + pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100 --junit-xml=test-results/junit-sql-coverage.xml + pytest --durations-min=0.5 --cov=superset/semantic_layers/ ./tests/unit_tests/semantic_layers/ --cache-clear --cov-fail-under=100 --junit-xml=test-results/junit-semantic-layers-coverage.xml - name: Upload code coverage uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: @@ -89,6 +89,33 @@ jobs: verbose: true use_oidc: true slug: apache/superset + # Uploaded even when a pytest step above fails, since that is exactly + # when the JUnit results are needed downstream, to annotate the PR with + # the failing tests. Consumed by the "Python Unit Test Results" workflow + # via workflow_run (see that workflow for why it can't just be a step + # here: it needs to run with write permissions, which this PR-triggered + # job can't safely have on a fork PR). + - name: Upload JUnit test results + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: junit-results-${{ matrix.python-version }} + path: test-results/ + retention-days: 7 + + # Uploads the raw pull_request event payload so the "Python Unit Test + # Results" workflow (running via workflow_run, in base-branch context) can + # look up which PR/commit to annotate without checking out untrusted code. + event-file: + runs-on: ubuntu-26.04 + timeout-minutes: 5 + steps: + - name: Upload event file + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: Event File + path: ${{ github.event_path }} + retention-days: 7 # Stable required-status-check anchor. `unit-tests` is a matrix job gated on # change detection, so on non-Python PRs it is skipped and never produces its
