pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
13 KiB
343 lines
13 KiB
name: Test
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
pull_request:
|
|
schedule:
|
|
# cron every week on monday
|
|
- cron: "0 0 * * 1"
|
|
|
|
permissions: {}
|
|
|
|
env:
|
|
UV_NO_SYNC: true
|
|
INLINE_SNAPSHOT_DEFAULT_FLAGS: review
|
|
|
|
jobs:
|
|
changes:
|
|
runs-on: ubuntu-latest
|
|
# Required permissions
|
|
permissions:
|
|
pull-requests: read
|
|
# Set job outputs to values from filter step
|
|
timeout-minutes: 5
|
|
outputs:
|
|
src: ${{ steps.filter.outputs.src }}
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
|
- uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
src:
|
|
- .github/workflows/test.yml
|
|
- docs_src/**
|
|
- fastapi/**
|
|
- scripts/**
|
|
- tests/**
|
|
- .python-version
|
|
- pyproject.toml
|
|
- uv.lock
|
|
|
|
test:
|
|
needs:
|
|
- changes
|
|
if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master'
|
|
timeout-minutes: 10
|
|
strategy:
|
|
matrix:
|
|
os: [ windows-latest, macos-latest ]
|
|
python-version: [ "3.14", "3.14t" ]
|
|
deprecated-tests: [ "no-deprecation" ]
|
|
uv-resolution:
|
|
- highest
|
|
starlette-src:
|
|
- starlette-pypi
|
|
- starlette-git
|
|
include:
|
|
- os: macos-latest
|
|
python-version: "3.10"
|
|
coverage: coverage
|
|
uv-resolution: lowest-direct
|
|
deprecated-tests: "no-deprecation"
|
|
- os: windows-latest
|
|
python-version: "3.12"
|
|
coverage: coverage
|
|
uv-resolution: lowest-direct
|
|
deprecated-tests: "no-deprecation"
|
|
- os: ubuntu-latest
|
|
python-version: "3.13"
|
|
coverage: coverage
|
|
uv-resolution: highest
|
|
deprecated-tests: "no-deprecation"
|
|
- os: ubuntu-latest
|
|
python-version: "3.13"
|
|
uv-resolution: highest
|
|
codspeed: codspeed
|
|
deprecated-tests: "no-deprecation"
|
|
- os: ubuntu-latest
|
|
python-version: "3.13"
|
|
uv-resolution: highest
|
|
deprecated-tests: "no-deprecation"
|
|
without-httpx2: true
|
|
- os: ubuntu-latest
|
|
python-version: "3.14"
|
|
coverage: coverage
|
|
uv-resolution: highest
|
|
starlette-src: starlette-git
|
|
deprecated-tests: "test-deprecation"
|
|
- os: ubuntu-latest
|
|
python-version: "3.14t"
|
|
coverage: coverage
|
|
uv-resolution: highest
|
|
deprecated-tests: "no-deprecation"
|
|
fail-fast: false
|
|
runs-on: ${{ matrix.os }}
|
|
env:
|
|
UV_PYTHON: ${{ matrix.python-version }}
|
|
UV_RESOLUTION: ${{ matrix.uv-resolution }}
|
|
STARLETTE_SRC: ${{ matrix.starlette-src }}
|
|
steps:
|
|
- name: Dump GitHub context
|
|
env:
|
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
run: echo "$GITHUB_CONTEXT"
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- name: Set up Python
|
|
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
with:
|
|
python-version: ${{ matrix.python-version }}
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
|
with:
|
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
version: "0.11.18"
|
|
enable-cache: true
|
|
cache-dependency-glob: |
|
|
pyproject.toml
|
|
uv.lock
|
|
- name: Install Dependencies
|
|
run: uv sync --no-dev --group tests --extra all
|
|
- name: Ensure that we have the lowest supported Pydantic version
|
|
if: matrix.uv-resolution == 'lowest-direct'
|
|
run: uv pip install "pydantic==2.9.0"
|
|
- name: Install Starlette from source
|
|
if: matrix.starlette-src == 'starlette-git'
|
|
run: uv pip install "git+https://github.com/Kludex/starlette@main"
|
|
- name: Install deprecated libraries just for testing
|
|
if: matrix.deprecated-tests == 'test-deprecation'
|
|
run: uv pip install orjson ujson
|
|
- name: Uninstall httpx2 to run tests with httpx
|
|
if: matrix.without-httpx2 == 'true'
|
|
run: uv pip uninstall httpx2
|
|
- name: Reinstall SQLAlchemy without Cython extensions
|
|
if: matrix.python-version == '3.14t' && matrix.os == 'ubuntu-latest'
|
|
run: "DISABLE_SQLALCHEMY_CEXT=1 uv pip install --force-reinstall --no-binary :all: sqlalchemy"
|
|
- run: mkdir coverage
|
|
- name: Test
|
|
run: uv run --no-sync bash scripts/test-cov.sh $PYTEST_OPTIONS
|
|
env:
|
|
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}}
|
|
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}}
|
|
PYTEST_OPTIONS: ${{ (matrix.without-httpx2 == 'true') && '-W ignore::UserWarning' || '' }}
|
|
# Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow
|
|
- name: Store coverage files
|
|
if: matrix.coverage == 'coverage'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.deprecated-tests}}-${{ hashFiles('**/coverage/.coverage.*') }}
|
|
path: coverage
|
|
include-hidden-files: true
|
|
|
|
benchmark:
|
|
needs:
|
|
- changes
|
|
if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
env:
|
|
UV_PYTHON: "3.13"
|
|
UV_RESOLUTION: highest
|
|
steps:
|
|
- name: Dump GitHub context
|
|
env:
|
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
run: echo "$GITHUB_CONTEXT"
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- name: Set up Python
|
|
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
with:
|
|
python-version: "3.13"
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
|
with:
|
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
version: "0.11.18"
|
|
enable-cache: true
|
|
cache-dependency-glob: |
|
|
pyproject.toml
|
|
uv.lock
|
|
- name: Install Dependencies
|
|
run: uv sync --no-dev --group tests --extra all
|
|
- name: CodSpeed benchmarks
|
|
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
|
|
with:
|
|
mode: simulation
|
|
run: uv run --no-sync pytest tests/benchmarks --codspeed
|
|
- name: CodSpeed memory benchmark
|
|
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
|
|
with:
|
|
mode: memory
|
|
run: uv run --no-sync pytest tests/memory_benchmarks --codspeed
|
|
|
|
regression-test:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Check out the pull request
|
|
if: github.event_name == 'pull_request'
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
ref: ${{ github.sha }}
|
|
path: pr
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
- name: Find changed tests
|
|
if: github.event_name == 'pull_request'
|
|
id: changed-tests
|
|
working-directory: pr
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
run: |
|
|
git diff --name-only --diff-filter=AM -z "$BASE_SHA" "$HEAD_SHA" -- tests \
|
|
| while IFS= read -r -d '' file; do
|
|
case "$(basename "$file")" in
|
|
test_*.py) printf '%s\0' "$file" ;;
|
|
esac
|
|
done > "$RUNNER_TEMP/changed-tests"
|
|
if [ -s "$RUNNER_TEMP/changed-tests" ]; then
|
|
echo "found=true" >> "$GITHUB_OUTPUT"
|
|
git diff --binary "$BASE_SHA" "$HEAD_SHA" -- tests \
|
|
> "$RUNNER_TEMP/tests.patch"
|
|
else
|
|
echo "found=false" >> "$GITHUB_OUTPUT"
|
|
echo "No added or modified test files; regression proof is not applicable."
|
|
fi
|
|
- name: Check out the base revision
|
|
if: steps.changed-tests.outputs.found == 'true'
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
ref: ${{ github.event.pull_request.base.sha }}
|
|
path: base
|
|
persist-credentials: false
|
|
- name: Set up Python
|
|
if: steps.changed-tests.outputs.found == 'true'
|
|
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
with:
|
|
python-version-file: "base/.python-version"
|
|
- name: Setup uv
|
|
if: steps.changed-tests.outputs.found == 'true'
|
|
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
|
with:
|
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
version: "0.11.18"
|
|
enable-cache: true
|
|
- name: Run the changed tests against the base code
|
|
if: steps.changed-tests.outputs.found == 'true'
|
|
working-directory: base
|
|
run: |
|
|
git apply "$RUNNER_TEMP/tests.patch"
|
|
uv sync --locked --no-dev --group tests --extra all
|
|
set +e
|
|
xargs -0 uv run --no-sync pytest -- < "$RUNNER_TEMP/changed-tests"
|
|
status=$?
|
|
set -e
|
|
if [ "$status" -eq 0 ]; then
|
|
echo "::warning::The changed tests already pass on the base revision. Check whether the fix is still needed."
|
|
echo "### Regression proof: base already passes :warning:" >> "$GITHUB_STEP_SUMMARY"
|
|
echo "The changed tests pass without the pull request's code changes." >> "$GITHUB_STEP_SUMMARY"
|
|
elif [ "$status" -eq 1 ]; then
|
|
echo "The changed tests fail on the base revision as expected."
|
|
echo "### Regression proof: base fails as expected :white_check_mark:" >> "$GITHUB_STEP_SUMMARY"
|
|
else
|
|
echo "::error::The base test run was inconclusive (pytest exit code $status)."
|
|
exit "$status"
|
|
fi
|
|
coverage-combine:
|
|
needs:
|
|
- test
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Dump GitHub context
|
|
env:
|
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
run: echo "$GITHUB_CONTEXT"
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
with:
|
|
python-version-file: ".python-version"
|
|
- name: Setup uv
|
|
uses: astral-sh/setup-uv@d31148d669074a8d0a63714ba94f3201e7020bc3 # v8.3.0
|
|
with:
|
|
# Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum.
|
|
# See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837
|
|
version: "0.11.18"
|
|
enable-cache: true
|
|
cache-dependency-glob: |
|
|
pyproject.toml
|
|
uv.lock
|
|
- name: Install Dependencies
|
|
run: uv sync --locked --no-dev --group tests --extra all
|
|
- name: Get coverage files
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
pattern: coverage-*
|
|
path: coverage
|
|
merge-multiple: true
|
|
- run: ls -la coverage
|
|
- run: uv run coverage combine coverage
|
|
- run: uv run coverage html --title "Coverage for ${{ github.sha }}"
|
|
- name: Store coverage HTML
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: coverage-html
|
|
path: htmlcov
|
|
include-hidden-files: true
|
|
- run: uv run coverage report --fail-under=100
|
|
|
|
# https://github.com/marketplace/actions/alls-green#why
|
|
test-alls-green: # This job does nothing and is only used for the branch protection
|
|
if: always()
|
|
needs:
|
|
- test
|
|
- coverage-combine
|
|
- benchmark
|
|
- regression-test
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Dump GitHub context
|
|
env:
|
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
run: echo "$GITHUB_CONTEXT"
|
|
- name: Decide whether the needed jobs succeeded or failed
|
|
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
|
with:
|
|
jobs: ${{ toJSON(needs) }}
|
|
allowed-skips: coverage-combine,test,benchmark
|
|
|