diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index c1da73b5df..7bce056970 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -14,11 +14,11 @@ concurrency: cancel-in-progress: true jobs: - test: - name: API Tests + api-unit: + name: API Unit Tests runs-on: ubuntu-latest env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + COVERAGE_FILE: coverage-unit defaults: run: shell: bash @@ -50,6 +50,52 @@ jobs: - name: Run dify config tests run: uv run --project api dev/pytest/pytest_config_tests.py + - name: Run Unit Tests + run: uv run --project api bash dev/pytest/pytest_unit_tests.sh + + - name: Upload unit coverage data + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: api-coverage-unit + path: coverage-unit + retention-days: 1 + + api-integration: + name: API Integration Tests + runs-on: ubuntu-latest + env: + COVERAGE_FILE: coverage-integration + STORAGE_TYPE: opendal + OPENDAL_SCHEME: fs + OPENDAL_FS_ROOT: /tmp/dify-storage + defaults: + run: + shell: bash + strategy: + matrix: + python-version: + - "3.12" + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup UV and Python + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + with: + enable-cache: true + python-version: ${{ matrix.python-version }} + cache-dependency-glob: api/uv.lock + + - name: Check UV lockfile + run: uv lock --project api --check + + - name: Install dependencies + run: uv sync --project api --dev + - name: Set up dotenvs run: | cp docker/.env.example docker/.env @@ -73,22 +119,90 @@ jobs: run: | cp api/tests/integration_tests/.env.example api/tests/integration_tests/.env - - name: Run API Tests - env: - STORAGE_TYPE: opendal - OPENDAL_SCHEME: fs - OPENDAL_FS_ROOT: /tmp/dify-storage + - name: Run Integration Tests run: | uv run --project api pytest \ -n auto \ --timeout "${PYTEST_TIMEOUT:-180}" \ api/tests/integration_tests/workflow \ api/tests/integration_tests/tools \ - api/tests/test_containers_integration_tests \ - api/tests/unit_tests + api/tests/test_containers_integration_tests + + - name: Upload integration coverage data + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: api-coverage-integration + path: coverage-integration + retention-days: 1 + + api-coverage: + name: API Coverage + runs-on: ubuntu-latest + needs: + - api-unit + - api-integration + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + COVERAGE_FILE: .coverage + defaults: + run: + shell: bash + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup UV and Python + uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 + with: + enable-cache: true + python-version: "3.12" + cache-dependency-glob: api/uv.lock + + - name: Install dependencies + run: uv sync --project api --dev + + - name: Download coverage data + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: coverage-data + pattern: api-coverage-* + merge-multiple: true + + - name: Combine coverage + run: | + set -euo pipefail + + echo "### API Coverage" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Merged backend coverage report generated for Codecov project status." >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + + unit_coverage="$(find coverage-data -type f -name coverage-unit -print -quit)" + integration_coverage="$(find coverage-data -type f -name coverage-integration -print -quit)" + : "${unit_coverage:?coverage-unit artifact not found}" + : "${integration_coverage:?coverage-integration artifact not found}" + + report_file="$(mktemp)" + uv run --project api coverage combine "$unit_coverage" "$integration_coverage" + uv run --project api coverage report --show-missing | tee "$report_file" + echo "Summary: \`$(tail -n 1 "$report_file")\`" >> "$GITHUB_STEP_SUMMARY" + { + echo "" + echo "
Coverage report" + echo "" + echo '```' + cat "$report_file" + echo '```' + echo "
" + } >> "$GITHUB_STEP_SUMMARY" + uv run --project api coverage xml -o coverage.xml - name: Report coverage - if: ${{ env.CODECOV_TOKEN != '' && matrix.python-version == '3.12' }} + if: ${{ env.CODECOV_TOKEN != '' }} uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3 with: files: ./coverage.xml diff --git a/dev/pytest/pytest_unit_tests.sh b/dev/pytest/pytest_unit_tests.sh index a034083304..1d4ff4d86f 100755 --- a/dev/pytest/pytest_unit_tests.sh +++ b/dev/pytest/pytest_unit_tests.sh @@ -13,4 +13,4 @@ PYTEST_XDIST_ARGS="${PYTEST_XDIST_ARGS:--n auto}" pytest --timeout "${PYTEST_TIMEOUT}" ${PYTEST_XDIST_ARGS} api/tests/unit_tests --ignore=api/tests/unit_tests/controllers # Run controller tests sequentially to avoid import race conditions -pytest --timeout "${PYTEST_TIMEOUT}" api/tests/unit_tests/controllers +pytest --timeout "${PYTEST_TIMEOUT}" --cov-append api/tests/unit_tests/controllers