From bc28db3d05e1cde3216028b9216b7176f16b8a3b Mon Sep 17 00:00:00 2001 From: Stephen Zhou Date: Sat, 10 Oct 2026 10:14:13 +0000 Subject: [PATCH] ci: upload coverage directly and fail on upload errors (#43826) --- .github/workflows/api-tests.yml | 127 ++++++++------------------------ .github/workflows/cli-tests.yml | 11 +-- .github/workflows/web-tests.yml | 67 ++++------------- codecov.yml | 5 ++ 4 files changed, 59 insertions(+), 151 deletions(-) diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 7f502e034a2..f6ecfdc3e0b 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -143,13 +143,20 @@ jobs: retention-days: 7 if-no-files-found: error - - name: Upload unit coverage data - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + - name: Generate coverage report + run: uv run --project api coverage xml -o coverage.xml + + # Codecov combines all backend uploads under the same commit and api flag. + - name: Report coverage + uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: - name: api-coverage-unit-${{ matrix.python-version }}-${{ matrix.shardIndex }} - path: ${{ env.COVERAGE_FILE }} - if-no-files-found: error - retention-days: 1 + files: ./coverage.xml + disable_search: true + fail_ci_if_error: true + flags: api + name: api-unit-${{ matrix.python-version }}-${{ matrix.shardIndex }}-${{ matrix.shardTotal }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} api-controllers: name: API Controller Tests (3.13) @@ -197,13 +204,20 @@ jobs: if-no-files-found: warn retention-days: 7 - - name: Upload controller coverage data - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + - name: Generate coverage report + run: uv run --project api coverage xml -o coverage.xml + + # Codecov combines all backend uploads under the same commit and api flag. + - name: Report coverage + uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: - name: api-coverage-controllers-3.13 - path: ${{ env.COVERAGE_FILE }} - if-no-files-found: error - retention-days: 1 + files: ./coverage.xml + disable_search: true + fail_ci_if_error: true + flags: api + name: api-controllers-3.13 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} api-integration: name: API Integration Tests (${{ matrix.python-version }}) @@ -255,94 +269,17 @@ jobs: api/tests/integration_tests/tools \ api/tests/test_containers_integration_tests - - name: Upload integration coverage data - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 - with: - name: api-coverage-integration-${{ matrix.python-version }} - path: ${{ env.COVERAGE_FILE }} - if-no-files-found: error - retention-days: 1 - - api-coverage: - name: API Coverage - runs-on: depot-ubuntu-24.04 - needs: - - api-unit - - api-controllers - - api-integration - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - COVERAGE_FILE: .coverage - defaults: - run: - shell: bash - - steps: - - name: Checkout code - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup UV and Python - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0 - with: - python-version: '3.13' - - - name: Download coverage data - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 - with: - path: coverage-data - pattern: api-coverage-* - merge-multiple: true - - - name: Combine coverage - run: | - set -euo pipefail - coverage_version=$(python3 -c 'import tomllib; print(next(p["version"] for p in tomllib.load(open("api/uv.lock", "rb"))["package"] if p["name"] == "coverage"))') - - mapfile -t unit_coverage < <(find coverage-data -type f -name 'coverage-unit-*' -print | sort) - mapfile -t controller_coverage < <(find coverage-data -type f -name 'coverage-controllers-*' -print | sort) - mapfile -t integration_coverage < <(find coverage-data -type f -name 'coverage-integration-*' -print | sort) - if [[ "${#unit_coverage[@]}" -ne 2 ]]; then - echo "expected 2 unit coverage artifacts, found ${#unit_coverage[@]}" >&2 - exit 1 - fi - if [[ "${#controller_coverage[@]}" -ne 1 ]]; then - echo "expected 1 controller coverage artifact, found ${#controller_coverage[@]}" >&2 - exit 1 - fi - if [[ "${#integration_coverage[@]}" -ne 1 ]]; then - echo "expected 1 integration coverage artifact, found ${#integration_coverage[@]}" >&2 - exit 1 - fi - - uvx --from "coverage==$coverage_version" coverage combine "${unit_coverage[@]}" "${controller_coverage[@]}" "${integration_coverage[@]}" - uvx --from "coverage==$coverage_version" coverage xml -o coverage.xml - - # Reuse the XML totals instead of analyzing every source file again for a text report. - python3 - <<'PY' - import os - import xml.etree.ElementTree as ET - - coverage = ET.parse("coverage.xml").getroot() - with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as summary: - summary.write("### API Coverage\n\n") - summary.write("Merged backend coverage report generated for Codecov project status.\n\n") - summary.write("| Metric | Covered | Total | Coverage |\n") - summary.write("| --- | ---: | ---: | ---: |\n") - for label, metric in (("Lines", "lines"), ("Branches", "branches")): - covered = int(coverage.attrib[f"{metric}-covered"]) - total = int(coverage.attrib[f"{metric}-valid"]) - percentage = f"{covered / total:.2%}" if total else "N/A" - summary.write(f"| {label} | {covered} | {total} | {percentage} |\n") - summary.write("\nSee Codecov for per-file coverage details.\n") - PY + - name: Generate coverage report + run: uv run --project api coverage xml -o coverage.xml + # Codecov combines all backend uploads under the same commit and api flag. - name: Report coverage uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: files: ./coverage.xml disable_search: true + fail_ci_if_error: true flags: api + name: api-integration-${{ matrix.python-version }} env: - CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/cli-tests.yml b/.github/workflows/cli-tests.yml index 4231e459fc3..eb9083325ea 100644 --- a/.github/workflows/cli-tests.yml +++ b/.github/workflows/cli-tests.yml @@ -21,8 +21,6 @@ jobs: fail-fast: false matrix: os: [depot-ubuntu-24.04, windows-latest, macos-latest] - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} defaults: run: shell: bash @@ -50,10 +48,13 @@ jobs: run: pnpm run ci - name: Report coverage - if: ${{ env.CODECOV_TOKEN != '' && matrix.os == 'depot-ubuntu-24.04' }} + if: matrix.os == 'depot-ubuntu-24.04' uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: - directory: cli/coverage + files: cli/coverage/coverage-final.json + disable_search: true + fail_ci_if_error: true flags: cli + name: cli-linux env: - CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/web-tests.yml b/.github/workflows/web-tests.yml index faefe69eb15..fbe7ba5bc47 100644 --- a/.github/workflows/web-tests.yml +++ b/.github/workflows/web-tests.yml @@ -33,16 +33,19 @@ jobs: uses: ./.github/actions/setup-web - name: Run tests - run: vp test run --project unit --reporter=blob --reporter=minimal --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage + run: vp test run --project unit --reporter=minimal --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --coverage - - name: Upload blob report - if: ${{ !cancelled() }} - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + # Codecov combines the shard uploads under the same commit and web flag. + - name: Report coverage + uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: - name: blob-report-${{ matrix.shardIndex }} - path: web/.vitest/blob/* - include-hidden-files: true - retention-days: 1 + files: web/coverage/coverage-final.json + disable_search: true + fail_ci_if_error: true + flags: web + name: web-${{ matrix.shardIndex }}-${{ matrix.shardTotal }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} browser-test: name: Web Browser Tests @@ -79,51 +82,10 @@ jobs: include-hidden-files: true retention-days: 7 - merge-reports: - name: Merge Test Reports - if: ${{ !cancelled() }} - needs: [test] - runs-on: depot-ubuntu-24.04-4 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - defaults: - run: - shell: bash - working-directory: ./web - - steps: - - name: Checkout code - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup web environment - uses: ./.github/actions/setup-web - - - name: Download blob reports - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 - with: - path: web/.vitest/blob - pattern: blob-report-* - merge-multiple: true - - - name: Merge reports - run: vp test --merge-reports --coverage --silent=passed-only - - - name: Report coverage - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 - with: - directory: web/coverage - flags: web - env: - CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }} - dify-ui-test: name: dify-ui Tests runs-on: depot-ubuntu-24.04-4 timeout-minutes: 20 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} defaults: run: shell: bash @@ -160,10 +122,13 @@ jobs: - name: Report coverage uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: - directory: packages/dify-ui/coverage + files: packages/dify-ui/coverage/coverage-final.json + disable_search: true + fail_ci_if_error: true flags: dify-ui + name: dify-ui env: - CODECOV_TOKEN: ${{ env.CODECOV_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} dify-ui-storybook-test: name: dify-ui Storybook Tests diff --git a/codecov.yml b/codecov.yml index a5060876986..f5fa6f6bd72 100644 --- a/codecov.yml +++ b/codecov.yml @@ -23,3 +23,8 @@ flags: paths: - "api/" carryforward: true + + cli: + paths: + - "cli/" + carryforward: true