@@ -338,30 +338,22 @@ jobs:
338338 env :
339339 TOOLKIT_VERSION : ${{ steps.version.outputs.VERSION }}
340340 PYTHON_VERSION : ${{ matrix.python-version }}
341- COVERAGE_FILE : coverage/ .coverage.${{ matrix.python-version }}
341+ COVERAGE_FILE : .coverage.${{ matrix.python-version }}
342342 run : |
343343 set -euo pipefail
344344
345- # Create coverage directory
346- mkdir -p coverage
347-
348- # Run tests with coverage
349345 poetry run pytest tests/unit \
350346 --cov=deepnote_toolkit \
351347 --cov=installer \
352348 --cov=deepnote_core \
353349 --cov-branch \
354350 --cov-report=term-missing:skip-covered \
355- --cov-report=xml:coverage/coverage-${PYTHON_VERSION}.xml \
356- --cov-report=json:coverage/coverage-${PYTHON_VERSION}.json \
357351 --junitxml=junit.xml \
358352 -o junit_family=legacy
359353
360354 # Check if coverage file was generated
361- if [ -f "coverage/ .coverage.${PYTHON_VERSION}" ]; then
355+ if [ -f ".coverage.${PYTHON_VERSION}" ]; then
362356 echo "coverage_generated=true" >> $GITHUB_OUTPUT
363- echo "Coverage files found:"
364- ls -la coverage/
365357 else
366358 echo "coverage_generated=false" >> $GITHUB_OUTPUT
367359 echo "Warning: No coverage file generated"
@@ -373,7 +365,7 @@ jobs:
373365 PYTHON_VERSION : ${{ matrix.python-version }}
374366 run : |
375367 echo "## Python ${PYTHON_VERSION} Coverage" >> $GITHUB_STEP_SUMMARY
376- poetry run coverage report --data-file=coverage/ .coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY
368+ poetry run coverage report --data-file=.coverage.${PYTHON_VERSION} --format=markdown >> $GITHUB_STEP_SUMMARY
377369
378370 - name : Upload test results to Codecov (these are results not coverage reports)
379371 if : ${{ !cancelled() }}
@@ -382,14 +374,93 @@ jobs:
382374 token : ${{ secrets.CODECOV_TOKEN }}
383375 flags : python-${{ matrix.python-version }}
384376
385- - name : Upload coverage to Codecov
377+ - name : Upload coverage artifacts
378+ if : steps.test-unit.outputs.coverage_generated == 'true'
379+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
380+ with :
381+ name : coverage-${{ matrix.python-version }}
382+ path : .coverage.${{ matrix.python-version }}
383+ retention-days : 1
384+
385+ coverage-combine :
386+ name : Combine and Upload Coverage
387+ runs-on : ubuntu-latest
388+ needs : tests-unit
389+ if : always()
390+ steps :
391+ - name : Checkout code
392+ uses : actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
393+ with :
394+ persist-credentials : false
395+
396+ - name : Set up Python
397+ uses : actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
398+ with :
399+ python-version : ' 3.11'
400+
401+ - name : Install coverage
402+ run : pip install coverage[toml]
403+
404+ - name : Download all coverage artifacts
405+ uses : actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
406+ continue-on-error : true
407+ with :
408+ pattern : coverage-*
409+ path : coverage-data/
410+ merge-multiple : true
411+
412+ - name : Combine coverage files
413+ id : combine
414+ run : |
415+ set -euo pipefail
416+
417+ if [ ! -d "coverage-data" ] || [ -z "$(ls -A coverage-data 2>/dev/null)" ]; then
418+ echo "No coverage artifacts were downloaded. All tests may have failed before generating coverage."
419+ echo "success=false" >> $GITHUB_OUTPUT
420+ exit 0
421+ fi
422+
423+ echo "Downloaded coverage files:"
424+ ls -la coverage-data/
425+
426+ shopt -s nullglob
427+ coverage_files=(coverage-data/.coverage.*)
428+ if [ ${#coverage_files[@]} -eq 0 ]; then
429+ echo "No .coverage.* files found to combine"
430+ echo "success=false" >> $GITHUB_OUTPUT
431+ exit 0
432+ fi
433+
434+ echo "Found ${#coverage_files[@]} coverage file(s) to combine"
435+
436+ cd coverage-data
437+ coverage combine
438+ coverage xml -o coverage.xml
439+ coverage report
440+
441+ echo "## Combined Coverage Report" >> $GITHUB_STEP_SUMMARY
442+ coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
443+
444+ echo "success=true" >> $GITHUB_OUTPUT
445+
446+ - name : Upload combined coverage to Codecov
447+ if : steps.combine.outputs.success == 'true'
386448 uses : codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5
387449 with :
388450 token : ${{ secrets.CODECOV_TOKEN }}
389- slug : deepnote/deepnote-toolkit
390- files : ./coverage/coverage-${{ matrix.python-version }}.xml
451+ slug : ${{ github.repository }}
452+ files : ./coverage-data/coverage.xml
453+ flags : combined
391454 fail_ci_if_error : ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push' }}
392455
456+ - name : Upload combined coverage report
457+ if : steps.combine.outputs.success == 'true'
458+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
459+ with :
460+ name : coverage-combined-report
461+ path : coverage-data/coverage.xml
462+ retention-days : 30
463+
393464 audit-prod :
394465 name : Audit - Production
395466 runs-on : ubuntu-latest
0 commit comments