From 9538e4d26d43a7aa5ab84a77876da9bd9a567b52 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Mon, 6 Jul 2026 22:02:35 +0200 Subject: [PATCH 1/4] Split CI into parallel unit, integration, and coverage report jobs. Run test jobs in parallel and merge coverage artifacts for an accurate full-suite PR report. Co-authored-by: Cursor --- .gitea/workflows/test.yml | 90 +++++++++++++++++++++++++++++++++++++-- README.md | 2 + 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index c456ad6..0528f38 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - test: + unit-tests: runs-on: ubuntu-latest steps: - name: Checkout code @@ -26,10 +26,92 @@ jobs: UV_LINK_MODE: copy run: uv sync --all-extras - - name: Run pytest + - name: Run unit tests + run: | + uv run pytest tests/unit/ -m "not integration" \ + --cov=python_repositories \ + --cov-report= + + - name: Upload unit coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-unit + path: .coverage + retention-days: 1 + + integration-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: .python-version + + - name: Install uv + run: pip install uv + + - name: Install dependencies env: - PYTHONPATH: . - run: uv run pytest --cov=python_repositories --cov-report=term-missing > coverage.txt + UV_LINK_MODE: copy + run: uv sync --all-extras + + - name: Verify Docker + run: docker info + + - name: Run integration tests + run: | + uv run pytest -m integration \ + --cov=python_repositories \ + --cov-report= + + - name: Upload integration coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-integration + path: .coverage + retention-days: 1 + + coverage-report: + needs: [unit-tests, integration-tests] + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' || github.event_name == 'push' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version-file: .python-version + + - name: Install uv + run: pip install uv + + - name: Install dependencies + env: + UV_LINK_MODE: copy + run: uv sync --all-extras + + - name: Download unit coverage + uses: actions/download-artifact@v4 + with: + name: coverage-unit + path: coverage-unit + + - name: Download integration coverage + uses: actions/download-artifact@v4 + with: + name: coverage-integration + path: coverage-integration + + - name: Combine coverage report + run: | + uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage + uv run coverage report -m --include='python_repositories/*' > coverage.txt + cat coverage.txt - name: Post coverage summary to PR if: github.event_name == 'pull_request' diff --git a/README.md b/README.md index 6976771..8cc4587 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,8 @@ uv run pytest -v # full suite (requires Doc Integration tests are marked with `@pytest.mark.integration` and require Docker (testcontainers). Run unit tests alone for quick local feedback. +CI runs unit and integration tests in parallel, then merges coverage into a single report (see [`.gitea/workflows/test.yml`](.gitea/workflows/test.yml)). + `pre-commit` is included in the dev dependency group. `uv sync` installs the CLI, but git does not run hooks until you install them with `pre-commit install` (one time per clone). After that, commits run the checks defined in [`.pre-commit-config.yaml`](.pre-commit-config.yaml) (ruff, mypy, pyupgrade, prettier, and general file hygiene). To run all hooks manually without committing: From 5d33ec6091c4d6b3672bb89d9f0d0a2acae4b9fb Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Tue, 7 Jul 2026 19:17:57 +0200 Subject: [PATCH 2/4] Use artifact action v3 for Gitea Actions compatibility. Gitea does not support upload-artifact/download-artifact v4 yet. Co-authored-by: Cursor --- .gitea/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 0528f38..14a5203 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -33,7 +33,7 @@ jobs: --cov-report= - name: Upload unit coverage - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: coverage-unit path: .coverage @@ -68,7 +68,7 @@ jobs: --cov-report= - name: Upload integration coverage - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: coverage-integration path: .coverage @@ -96,13 +96,13 @@ jobs: run: uv sync --all-extras - name: Download unit coverage - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: coverage-unit path: coverage-unit - name: Download integration coverage - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: coverage-integration path: coverage-integration From 0315a33a3b520ed7a7f90bed76325c8bb562b6e0 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Tue, 7 Jul 2026 19:27:26 +0200 Subject: [PATCH 3/4] Avoid cross-job artifacts; combine coverage with --cov-append. Gitea artifact download is unreliable with v3 actions, so the report job re-runs both suites on one runner after parallel test gates pass. Co-authored-by: Cursor --- .gitea/workflows/test.yml | 49 ++++++++++----------------------------- README.md | 2 +- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 14a5203..e6d6b49 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -27,17 +27,7 @@ jobs: run: uv sync --all-extras - name: Run unit tests - run: | - uv run pytest tests/unit/ -m "not integration" \ - --cov=python_repositories \ - --cov-report= - - - name: Upload unit coverage - uses: actions/upload-artifact@v3 - with: - name: coverage-unit - path: .coverage - retention-days: 1 + run: uv run pytest tests/unit/ -m "not integration" -v integration-tests: runs-on: ubuntu-latest @@ -62,17 +52,7 @@ jobs: run: docker info - name: Run integration tests - run: | - uv run pytest -m integration \ - --cov=python_repositories \ - --cov-report= - - - name: Upload integration coverage - uses: actions/upload-artifact@v3 - with: - name: coverage-integration - path: .coverage - retention-days: 1 + run: uv run pytest -m integration -v coverage-report: needs: [unit-tests, integration-tests] @@ -95,22 +75,17 @@ jobs: UV_LINK_MODE: copy run: uv sync --all-extras - - name: Download unit coverage - uses: actions/download-artifact@v3 - with: - name: coverage-unit - path: coverage-unit - - - name: Download integration coverage - uses: actions/download-artifact@v3 - with: - name: coverage-integration - path: coverage-integration - - - name: Combine coverage report + # Gitea Actions lacks cross-job artifact download APIs; re-run tests here + # with --cov-append on one runner for an accurate combined report. + - name: Run tests with combined coverage run: | - uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage - uv run coverage report -m --include='python_repositories/*' > coverage.txt + uv run pytest tests/unit/ -m "not integration" \ + --cov=python_repositories \ + --cov-report= + uv run pytest -m integration \ + --cov=python_repositories \ + --cov-append \ + --cov-report=term-missing > coverage.txt cat coverage.txt - name: Post coverage summary to PR diff --git a/README.md b/README.md index 8cc4587..09d26eb 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ uv run pytest -v # full suite (requires Doc Integration tests are marked with `@pytest.mark.integration` and require Docker (testcontainers). Run unit tests alone for quick local feedback. -CI runs unit and integration tests in parallel, then merges coverage into a single report (see [`.gitea/workflows/test.yml`](.gitea/workflows/test.yml)). +CI runs unit and integration tests in parallel for fast feedback; a follow-up job re-runs both suites with `--cov-append` to produce a combined coverage report (Gitea Actions does not support cross-job artifact download yet). `pre-commit` is included in the dev dependency group. `uv sync` installs the CLI, but git does not run hooks until you install them with `pre-commit install` (one time per clone). After that, commits run the checks defined in [`.pre-commit-config.yaml`](.pre-commit-config.yaml) (ruff, mypy, pyupgrade, prettier, and general file hygiene). From c1f4826d780bf452ac0ce52f195eb172b749d002 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Tue, 7 Jul 2026 19:35:19 +0200 Subject: [PATCH 4/4] Use christopherhx v4 artifact actions for parallel coverage merge. Restore per-job coverage uploads while keeping unit and integration jobs parallel on Gitea 1.26. Co-authored-by: Cursor --- .gitea/workflows/test.yml | 51 ++++++++++++++++++++++++++++++--------- README.md | 2 +- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index e6d6b49..e57424b 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -27,7 +27,18 @@ jobs: run: uv sync --all-extras - name: Run unit tests - run: uv run pytest tests/unit/ -m "not integration" -v + run: | + uv run pytest tests/unit/ -m "not integration" \ + --cov=python_repositories \ + --cov-report= + + - name: Upload unit coverage + uses: https://github.com/christopherHX/gitea-upload-artifact@v4 + with: + name: coverage-unit + path: .coverage + retention-days: 1 + compression-level: 0 integration-tests: runs-on: ubuntu-latest @@ -52,7 +63,18 @@ jobs: run: docker info - name: Run integration tests - run: uv run pytest -m integration -v + run: | + uv run pytest -m integration \ + --cov=python_repositories \ + --cov-report= + + - name: Upload integration coverage + uses: https://github.com/christopherHX/gitea-upload-artifact@v4 + with: + name: coverage-integration + path: .coverage + retention-days: 1 + compression-level: 0 coverage-report: needs: [unit-tests, integration-tests] @@ -75,17 +97,22 @@ jobs: UV_LINK_MODE: copy run: uv sync --all-extras - # Gitea Actions lacks cross-job artifact download APIs; re-run tests here - # with --cov-append on one runner for an accurate combined report. - - name: Run tests with combined coverage + - name: Download unit coverage + uses: https://github.com/christopherHX/gitea-download-artifact@v4 + with: + name: coverage-unit + path: coverage-unit + + - name: Download integration coverage + uses: https://github.com/christopherHX/gitea-download-artifact@v4 + with: + name: coverage-integration + path: coverage-integration + + - name: Combine coverage report run: | - uv run pytest tests/unit/ -m "not integration" \ - --cov=python_repositories \ - --cov-report= - uv run pytest -m integration \ - --cov=python_repositories \ - --cov-append \ - --cov-report=term-missing > coverage.txt + uv run coverage combine coverage-unit/.coverage coverage-integration/.coverage + uv run coverage report -m --include='python_repositories/*' > coverage.txt cat coverage.txt - name: Post coverage summary to PR diff --git a/README.md b/README.md index 09d26eb..cb93dff 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ uv run pytest -v # full suite (requires Doc Integration tests are marked with `@pytest.mark.integration` and require Docker (testcontainers). Run unit tests alone for quick local feedback. -CI runs unit and integration tests in parallel for fast feedback; a follow-up job re-runs both suites with `--cov-append` to produce a combined coverage report (Gitea Actions does not support cross-job artifact download yet). +CI runs unit and integration tests in parallel with coverage, then merges `.coverage` artifacts in a follow-up job (via [christopherhx/gitea-\*-artifact@v4](https://github.com/christopherHX/gitea-upload-artifact) for Gitea 1.26 compatibility). `pre-commit` is included in the dev dependency group. `uv sync` installs the CLI, but git does not run hooks until you install them with `pre-commit install` (one time per clone). After that, commits run the checks defined in [`.pre-commit-config.yaml`](.pre-commit-config.yaml) (ruff, mypy, pyupgrade, prettier, and general file hygiene).