From 917c59ad045c6a6a0dd938b0cbc12bf637151d64 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:30:40 +0000 Subject: [PATCH 1/8] Initial plan From 18b09432c4d1485361ce27b8daed7e0471c18e78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:39:00 +0000 Subject: [PATCH 2/8] Add CLI support for driver and db-name options in pytest Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/workflows/codecov.yml | 41 ++++++++++++--- tests/conftest.py | 94 +++++++++++++++++++++++++++++++++-- 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 032cb6f..edee95b 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -1,5 +1,5 @@ # This workflow will run tests using pytest and upload the coverage report to Codecov -# Run test with various Python versions +# Run test with various Python versions and database drivers name: Integration Tests on: @@ -15,8 +15,11 @@ jobs: strategy: matrix: python-version: ["3.9","3.10","3.11","3.12"] + driver: ["pg8000", "psycopg2", "psycopg", "psycopg2cffi", "asyncpg"] + # Run tests sequentially to avoid conflicts + max-parallel: 1 - name: Test pgmq-sqlalchemy + name: Test pgmq-sqlalchemy (Python ${{ matrix.python-version }}, Driver ${{ matrix.driver }}) steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} @@ -30,15 +33,41 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: uv sync --extra dev - - name: Start PostgreSQL + - name: Start PostgreSQL with unique database run: | + # Create unique database name for this combination + export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" + export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') + + # Update environment files with unique database name cp pgmq_postgres.template.env pgmq_postgres.env + echo "POSTGRES_DB=${DB_NAME}" >> pgmq_postgres.env + cp pgmq_tests.template.env pgmq_tests.env + echo "SQLALCHEMY_DB=${DB_NAME}" >> pgmq_tests.env + + # Start PostgreSQL make start-db - - name: Run tests and collect coverage - run: uv run pytest tests --cov=pgmq_sqlalchemy.queue --cov-report=xml -n auto tests + + # Create the database + docker compose exec -T pgmq_postgres psql -U postgres -c "CREATE DATABASE ${DB_NAME};" || true + docker compose exec -T pgmq_postgres psql -U postgres -d ${DB_NAME} -c "CREATE EXTENSION IF NOT EXISTS pgmq CASCADE;" || true + - name: Run tests for specific driver + run: | + export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" + export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') + export SQLALCHEMY_DB=${DB_NAME} + + uv run pytest tests --driver=${{ matrix.driver }} --db-name=${DB_NAME} --cov=pgmq_sqlalchemy.queue --cov-report=xml continue-on-error: true - name: Upload coverage reports to Codecov with GitHub Action uses: codecov/codecov-action@v4.2.0 env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Cleanup database + if: always() + run: | + export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" + export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') + docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true + make clear-db || true \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 05a4907..444951b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,74 @@ from tests.constant import ASYNC_DRIVERS, SYNC_DRIVERS +def pytest_addoption(parser): + """Add custom command-line options for pytest.""" + parser.addoption( + "--driver", + action="store", + default=None, + help="Specify the database driver to use for testing (e.g., psycopg2, asyncpg, pg8000, etc.)", + ) + parser.addoption( + "--db-name", + action="store", + default=None, + help="Specify the database name to use for testing", + ) + + +def pytest_collection_modifyitems(config, items): + """Modify test collection to skip tests not matching the --driver option.""" + driver_from_cli = config.getoption("--driver") + + if not driver_from_cli: + # No driver specified, run all tests + return + + # Determine if the specified driver is sync or async + is_async_driver = driver_from_cli in ASYNC_DRIVERS + is_sync_driver = driver_from_cli in SYNC_DRIVERS + + if not is_async_driver and not is_sync_driver: + # Invalid driver + return + + # Filter out tests that don't match the specified driver + skip_marker = pytest.mark.skip(reason=f"Test uses different driver (--driver={driver_from_cli} specified)") + + for item in items: + # Parse the test name to extract driver info + # Format is usually: test_name[fixture_name-driver_name] + item_id = item.nodeid + + # Skip async tests if sync driver specified + if is_sync_driver and 'async' in item_id.lower(): + item.add_marker(skip_marker) + continue + + # Skip sync tests if async driver specified + if is_async_driver and 'async' not in item_id.lower(): + item.add_marker(skip_marker) + continue + + # Check if the test has a specific driver in its ID + # Extract driver name from test ID (e.g., test_name[pgmq_by_dsn-psycopg2]) + if '[' in item_id and ']' in item_id: + # Extract the part between brackets + bracket_content = item_id[item_id.find('[')+1:item_id.find(']')] + + # Check if any known driver is in the bracket content + # Sort drivers by length (descending) to match longer names first (e.g., psycopg2cffi before psycopg2) + sorted_drivers = sorted(SYNC_DRIVERS + ASYNC_DRIVERS, key=len, reverse=True) + for driver in sorted_drivers: + if f"-{driver}]" in item_id or f"-{driver}-" in bracket_content: + # This test is for a specific driver + if driver != driver_from_cli: + # Skip if it doesn't match the CLI driver + item.add_marker(skip_marker) + break + + @pytest.fixture(scope="module") def get_sa_host(): return os.getenv("SQLALCHEMY_HOST", "localhost") @@ -31,7 +99,11 @@ def get_sa_password(): @pytest.fixture(scope="module") -def get_sa_db(): +def get_sa_db(request): + """Get database name from CLI argument or environment variable.""" + db_name_from_cli = request.config.getoption("--db-name") + if db_name_from_cli: + return db_name_from_cli return os.getenv("SQLALCHEMY_DB", "postgres") @@ -44,7 +116,15 @@ def get_dsn( get_sa_password, get_sa_db, ): - driver = request.param + """Get DSN for sync drivers.""" + driver_from_cli = request.config.getoption("--driver") + + # Use CLI driver if specified, otherwise use parametrized driver + if driver_from_cli and driver_from_cli in SYNC_DRIVERS: + driver = driver_from_cli + else: + driver = request.param + return f"postgresql+{driver}://{get_sa_user}:{get_sa_password}@{get_sa_host}:{get_sa_port}/{get_sa_db}" @@ -57,7 +137,15 @@ def get_async_dsn( get_sa_password, get_sa_db, ): - driver = request.param + """Get DSN for async drivers.""" + driver_from_cli = request.config.getoption("--driver") + + # Use CLI driver if specified, otherwise use parametrized driver + if driver_from_cli and driver_from_cli in ASYNC_DRIVERS: + driver = driver_from_cli + else: + driver = request.param + return f"postgresql+{driver}://{get_sa_user}:{get_sa_password}@{get_sa_host}:{get_sa_port}/{get_sa_db}" From 31471c874eb6a2d3c50fec98ad95d80d11a5bb9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:43:10 +0000 Subject: [PATCH 3/8] Update GitHub Actions workflow for matrix testing with drivers Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/workflows/codecov.yml | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index edee95b..06e1aea 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -33,30 +33,28 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: uv sync --extra dev - - name: Start PostgreSQL with unique database + - name: Start PostgreSQL (first time only) + run: | + # Only start if not already running + if ! docker ps | grep -q pgmq_postgres; then + cp pgmq_postgres.template.env pgmq_postgres.env + cp pgmq_tests.template.env pgmq_tests.env + make start-db + fi + - name: Setup unique database for this test run run: | # Create unique database name for this combination export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') - # Update environment files with unique database name - cp pgmq_postgres.template.env pgmq_postgres.env - echo "POSTGRES_DB=${DB_NAME}" >> pgmq_postgres.env - - cp pgmq_tests.template.env pgmq_tests.env - echo "SQLALCHEMY_DB=${DB_NAME}" >> pgmq_tests.env - - # Start PostgreSQL - make start-db - # Create the database - docker compose exec -T pgmq_postgres psql -U postgres -c "CREATE DATABASE ${DB_NAME};" || true - docker compose exec -T pgmq_postgres psql -U postgres -d ${DB_NAME} -c "CREATE EXTENSION IF NOT EXISTS pgmq CASCADE;" || true + docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true + docker compose exec -T pgmq_postgres psql -U postgres -c "CREATE DATABASE ${DB_NAME};" + docker compose exec -T pgmq_postgres psql -U postgres -d ${DB_NAME} -c "CREATE EXTENSION IF NOT EXISTS pgmq CASCADE;" - name: Run tests for specific driver run: | export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') - export SQLALCHEMY_DB=${DB_NAME} uv run pytest tests --driver=${{ matrix.driver }} --db-name=${DB_NAME} --cov=pgmq_sqlalchemy.queue --cov-report=xml continue-on-error: true @@ -69,5 +67,4 @@ jobs: run: | export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') - docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true - make clear-db || true \ No newline at end of file + docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true \ No newline at end of file From f2d382f8abf2c0baf4e9a6a0d07237e87a66d194 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:44:11 +0000 Subject: [PATCH 4/8] Add documentation for new pytest CLI options Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/CONTRIBUTING.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3c32ce3..dcd3255 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -75,6 +75,20 @@ Run tests in local make test-local ``` +Run tests for a specific driver +```bash +uv run pytest tests --driver=psycopg2 +``` + +Run tests with a specific database name +```bash +uv run pytest tests --driver=psycopg2 --db-name=custom_db +``` + +Available drivers: +- Sync drivers: `pg8000`, `psycopg2`, `psycopg`, `psycopg2cffi` +- Async drivers: `asyncpg` + Run tests in docker ```bash make test-docker From 48a099bd3517e4005beb4ee5e6590de29a69894a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:46:01 +0000 Subject: [PATCH 5/8] Address code review feedback - improve code quality Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/workflows/codecov.yml | 20 +++++++++--------- tests/conftest.py | 38 +++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 06e1aea..2e0b802 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -20,6 +20,9 @@ jobs: max-parallel: 1 name: Test pgmq-sqlalchemy (Python ${{ matrix.python-version }}, Driver ${{ matrix.driver }}) + env: + # Create unique database name for this combination + DB_NAME_RAW: pgmq_py${{ matrix.python-version }}_${{ matrix.driver }} steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} @@ -43,19 +46,18 @@ jobs: fi - name: Setup unique database for this test run run: | - # Create unique database name for this combination - export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" - export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') - + # Normalize database name (remove dots and hyphens) + export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') + # Create the database docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true docker compose exec -T pgmq_postgres psql -U postgres -c "CREATE DATABASE ${DB_NAME};" docker compose exec -T pgmq_postgres psql -U postgres -d ${DB_NAME} -c "CREATE EXTENSION IF NOT EXISTS pgmq CASCADE;" - name: Run tests for specific driver run: | - export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" - export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') - + # Normalize database name (remove dots and hyphens) + export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') + uv run pytest tests --driver=${{ matrix.driver }} --db-name=${DB_NAME} --cov=pgmq_sqlalchemy.queue --cov-report=xml continue-on-error: true - name: Upload coverage reports to Codecov with GitHub Action @@ -65,6 +67,6 @@ jobs: - name: Cleanup database if: always() run: | - export DB_NAME="pgmq_py${{ matrix.python-version }}_${{ matrix.driver }}" - export DB_NAME=$(echo $DB_NAME | sed 's/\.//g' | sed 's/-/_/g') + # Normalize database name (remove dots and hyphens) + export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 444951b..ddb95ce 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,43 +29,47 @@ def pytest_addoption(parser): def pytest_collection_modifyitems(config, items): """Modify test collection to skip tests not matching the --driver option.""" driver_from_cli = config.getoption("--driver") - + if not driver_from_cli: # No driver specified, run all tests return - + # Determine if the specified driver is sync or async is_async_driver = driver_from_cli in ASYNC_DRIVERS is_sync_driver = driver_from_cli in SYNC_DRIVERS - + if not is_async_driver and not is_sync_driver: # Invalid driver return - + # Filter out tests that don't match the specified driver skip_marker = pytest.mark.skip(reason=f"Test uses different driver (--driver={driver_from_cli} specified)") - + for item in items: # Parse the test name to extract driver info # Format is usually: test_name[fixture_name-driver_name] item_id = item.nodeid - - # Skip async tests if sync driver specified - if is_sync_driver and 'async' in item_id.lower(): - item.add_marker(skip_marker) - continue - - # Skip sync tests if async driver specified - if is_async_driver and 'async' not in item_id.lower(): - item.add_marker(skip_marker) - continue - + # Check if the test has a specific driver in its ID # Extract driver name from test ID (e.g., test_name[pgmq_by_dsn-psycopg2]) if '[' in item_id and ']' in item_id: # Extract the part between brackets bracket_content = item_id[item_id.find('[')+1:item_id.find(']')] - + + # Check for async fixtures by name (more precise than string matching) + async_fixture_names = ['pgmq_by_async_dsn', 'pgmq_by_async_engine', 'pgmq_by_async_session_maker'] + is_async_test = any(async_fixture in bracket_content for async_fixture in async_fixture_names) + + # Skip async tests if sync driver specified + if is_sync_driver and is_async_test: + item.add_marker(skip_marker) + continue + + # Skip sync tests if async driver specified + if is_async_driver and not is_async_test: + item.add_marker(skip_marker) + continue + # Check if any known driver is in the bracket content # Sort drivers by length (descending) to match longer names first (e.g., psycopg2cffi before psycopg2) sorted_drivers = sorted(SYNC_DRIVERS + ASYNC_DRIVERS, key=len, reverse=True) From 796453799fc81714b5114b5ea0a45541e2c357d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 04:47:08 +0000 Subject: [PATCH 6/8] Final code quality improvements - extract constants Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/workflows/codecov.yml | 2 ++ tests/conftest.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 2e0b802..ffd8b35 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -47,6 +47,8 @@ jobs: - name: Setup unique database for this test run run: | # Normalize database name (remove dots and hyphens) + # Note: We normalize in each step because GitHub Actions doesn't support + # computed environment variables that can be reused across steps export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') # Create the database diff --git a/tests/conftest.py b/tests/conftest.py index ddb95ce..9a48f6b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,6 +9,9 @@ from pgmq_sqlalchemy import PGMQueue from tests.constant import ASYNC_DRIVERS, SYNC_DRIVERS +# Async fixture names for test filtering +ASYNC_FIXTURE_NAMES = ['pgmq_by_async_dsn', 'pgmq_by_async_engine', 'pgmq_by_async_session_maker'] + def pytest_addoption(parser): """Add custom command-line options for pytest.""" @@ -57,8 +60,7 @@ def pytest_collection_modifyitems(config, items): bracket_content = item_id[item_id.find('[')+1:item_id.find(']')] # Check for async fixtures by name (more precise than string matching) - async_fixture_names = ['pgmq_by_async_dsn', 'pgmq_by_async_engine', 'pgmq_by_async_session_maker'] - is_async_test = any(async_fixture in bracket_content for async_fixture in async_fixture_names) + is_async_test = any(async_fixture in bracket_content for async_fixture in ASYNC_FIXTURE_NAMES) # Skip async tests if sync driver specified if is_sync_driver and is_async_test: From 4bf25ff5f7fe35db5dbf2dba0d32500da705b26d Mon Sep 17 00:00:00 2001 From: LIU ZHE YOU Date: Sun, 28 Dec 2025 13:38:11 +0800 Subject: [PATCH 7/8] Remove max-parallel: 1 --- .github/workflows/codecov.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index ffd8b35..fd64217 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -16,8 +16,6 @@ jobs: matrix: python-version: ["3.9","3.10","3.11","3.12"] driver: ["pg8000", "psycopg2", "psycopg", "psycopg2cffi", "asyncpg"] - # Run tests sequentially to avoid conflicts - max-parallel: 1 name: Test pgmq-sqlalchemy (Python ${{ matrix.python-version }}, Driver ${{ matrix.driver }}) env: From 2eaaf677552fe90c9a96ab1082ff5c83ebb393b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 05:59:22 +0000 Subject: [PATCH 8/8] Fix coverage report race condition with separate upload job Co-authored-by: jason810496 <68415893+jason810496@users.noreply.github.com> --- .github/workflows/codecov.yml | 50 +++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index fd64217..9be0110 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -9,7 +9,7 @@ on: branches: [main, develop] jobs: - build: + test: runs-on: ubuntu-latest strategy: @@ -34,14 +34,11 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install dependencies run: uv sync --extra dev - - name: Start PostgreSQL (first time only) + - name: Start PostgreSQL run: | - # Only start if not already running - if ! docker ps | grep -q pgmq_postgres; then - cp pgmq_postgres.template.env pgmq_postgres.env - cp pgmq_tests.template.env pgmq_tests.env - make start-db - fi + cp pgmq_postgres.template.env pgmq_postgres.env + cp pgmq_tests.template.env pgmq_tests.env + make start-db - name: Setup unique database for this test run run: | # Normalize database name (remove dots and hyphens) @@ -58,15 +55,40 @@ jobs: # Normalize database name (remove dots and hyphens) export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') - uv run pytest tests --driver=${{ matrix.driver }} --db-name=${DB_NAME} --cov=pgmq_sqlalchemy.queue --cov-report=xml + # Create unique coverage file name + export COVERAGE_FILE=".coverage.py${{ matrix.python-version }}.${{ matrix.driver }}" + + uv run pytest tests --driver=${{ matrix.driver }} --db-name=${DB_NAME} --cov=pgmq_sqlalchemy.queue --cov-report=xml:coverage-py${{ matrix.python-version }}-${{ matrix.driver }}.xml continue-on-error: true - - name: Upload coverage reports to Codecov with GitHub Action - uses: codecov/codecov-action@v4.2.0 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-py${{ matrix.python-version }}-${{ matrix.driver }} + path: coverage-py${{ matrix.python-version }}-${{ matrix.driver }}.xml + retention-days: 1 - name: Cleanup database if: always() run: | # Normalize database name (remove dots and hyphens) export DB_NAME=$(echo "$DB_NAME_RAW" | sed 's/\.//g' | sed 's/-/_/g') - docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true \ No newline at end of file + docker compose exec -T pgmq_postgres psql -U postgres -c "DROP DATABASE IF EXISTS ${DB_NAME};" || true + + upload-coverage: + needs: test + runs-on: ubuntu-latest + name: Upload coverage to Codecov + steps: + - uses: actions/checkout@v4 + - name: Download all coverage artifacts + uses: actions/download-artifact@v4 + with: + path: coverage-reports + pattern: coverage-* + merge-multiple: true + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.2.0 + with: + directory: ./coverage-reports + fail_ci_if_error: false + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file