chore: update pre-commit dependencies to latest versions #244
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths-ignore: | |
| - ".github/*.svg" | |
| pull_request: | |
| branches: | |
| - main | |
| paths-ignore: | |
| - ".github/*.svg" | |
| # Prevent multiple workflows from running concurrently on the same PR | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint-and-format: | |
| name: Lint and Format Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| cache: "pip" | |
| cache-dependency-path: pyproject.toml | |
| - name: Cache uv | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| key: ${{ runner.os }}-uv-3.12-${{ hashFiles('uv.lock') || hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| version: "latest" | |
| - name: Install dependencies (lint) | |
| run: | | |
| python -m pip install --upgrade pip | |
| uv sync --all-extras --group dev | |
| - name: Add project .venv to PATH | |
| run: | | |
| echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH | |
| - name: Verify lint tools are available | |
| run: | | |
| echo "PATH=$PATH" | |
| if ! command -v ruff >/dev/null 2>&1; then | |
| echo "ruff not found in PATH; listing .venv/bin:"; | |
| ls -la .venv/bin || true; | |
| python -m pip show ruff || true; | |
| exit 1; | |
| fi | |
| ruff --version | |
| if ! command -v pyright >/dev/null 2>&1; then | |
| echo "pyright not found in PATH; attempting to show package info:"; | |
| python -m pip show pyright || true; | |
| else | |
| pyright --version || true | |
| fi | |
| - name: Run linters (activate .venv) | |
| run: | | |
| set -euo pipefail | |
| # activate the virtualenv for this step so ruff/pyright are from .venv | |
| if [ -f .venv/bin/activate ]; then | |
| # shellcheck disable=SC1091 | |
| . .venv/bin/activate | |
| fi | |
| ruff format --check . | |
| ruff check . | |
| pyright | |
| unit-tests: | |
| name: Unit Tests (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.12", "3.13", "3.14"] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| cache: "pip" | |
| cache-dependency-path: pyproject.toml | |
| - name: Cache uv | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') || hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| version: "latest" | |
| - name: Install dependencies (unit) | |
| run: | | |
| python -m pip install --upgrade pip | |
| uv sync --all-extras --group dev | |
| - name: Add project .venv to PATH | |
| run: | | |
| echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH | |
| - name: Verify test tools are available | |
| run: | | |
| if ! command -v pytest >/dev/null 2>&1; then | |
| echo "pytest not found in PATH; listing .venv/bin:"; | |
| ls -la .venv/bin || true; | |
| python -m pip show pytest || true; | |
| exit 1; | |
| fi | |
| pytest --version | |
| - name: Run unit tests (activate .venv) | |
| run: | | |
| set -euo pipefail | |
| if [ -f .venv/bin/activate ]; then | |
| . .venv/bin/activate | |
| fi | |
| pytest tests/unit -v --cov=src/asynctasq --cov-report=xml --cov-report=term-missing | |
| - name: Upload coverage artifact | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: coverage-unit-${{ matrix.python-version }} | |
| path: coverage.xml | |
| - name: Upload coverage to Codecov | |
| if: matrix.python-version == '3.12' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| integration-tests: | |
| name: Integration Tests (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.12", "3.13", "3.14"] | |
| services: | |
| localstack: | |
| image: localstack/localstack:4.0 | |
| ports: | |
| - "127.0.0.1:4566:4566" | |
| env: | |
| SERVICES: "sqs,s3" | |
| options: >- | |
| --health-cmd "awslocal sqs list-queues || exit 1" | |
| --health-interval 5s | |
| --health-timeout 3s | |
| --health-retries 5 | |
| --health-start-period 10s | |
| redis: | |
| image: redis:7-alpine | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: test | |
| POSTGRES_PASSWORD: test | |
| POSTGRES_DB: test_db | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| mysql: | |
| image: mysql:8 | |
| env: | |
| MYSQL_ROOT_PASSWORD: test | |
| MYSQL_USER: test | |
| MYSQL_PASSWORD: test | |
| MYSQL_DATABASE: test_db | |
| options: >- | |
| --health-cmd "mysqladmin ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 3306:3306 | |
| rabbitmq: | |
| image: rabbitmq:3-management-alpine | |
| env: | |
| RABBITMQ_DEFAULT_USER: guest | |
| RABBITMQ_DEFAULT_PASS: guest | |
| options: >- | |
| --health-cmd "rabbitmq-diagnostics -q ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5672:5672 | |
| - 15672:15672 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| cache: "pip" | |
| cache-dependency-path: pyproject.toml | |
| - name: Cache uv | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') || hashFiles('pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| version: "latest" | |
| - name: Install dependencies (integration) | |
| run: | | |
| python -m pip install --upgrade pip | |
| uv sync --all-extras --group dev | |
| - name: Add project .venv to PATH | |
| run: | | |
| echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH | |
| - name: Verify test tools are available | |
| run: | | |
| if ! command -v pytest >/dev/null 2>&1; then | |
| echo "pytest not found in PATH; listing .venv/bin:"; | |
| ls -la .venv/bin || true; | |
| python -m pip show pytest || true; | |
| exit 1; | |
| fi | |
| pytest --version | |
| - name: Wait for services (robust) | |
| run: | | |
| set -euo pipefail | |
| wait_port() { | |
| host=$1; port=$2 | |
| for i in {1..120}; do | |
| if (echo > /dev/tcp/${host}/${port}) >/dev/null 2>&1; then | |
| return 0 | |
| fi | |
| sleep 1 | |
| done | |
| return 1 | |
| } | |
| echo "Waiting for postgres (localhost:5432)..." | |
| if ! wait_port 127.0.0.1 5432; then | |
| echo "postgres not ready - gathering diagnostics" | |
| echo "--- Docker containers ---" | |
| docker ps -a --format 'table {{.ID}} {{.Names}} {{.Image}} {{.Status}}' | |
| echo "--- Listening ports ---" | |
| ss -ltnp || netstat -ltnp || true | |
| echo "--- Postgres logs (matching image name 'postgres') ---" | |
| for cid in $(docker ps -a --filter ancestor=postgres --format '{{.Names}}'); do | |
| echo "Logs for $cid:"; docker logs --tail 200 "$cid" || true | |
| done | |
| exit 1 | |
| fi | |
| echo "Waiting for redis (localhost:6379)..." | |
| wait_port 127.0.0.1 6379 || { echo "redis not ready"; exit 1; } | |
| echo "Waiting for mysql (localhost:3306)..." | |
| if ! wait_port 127.0.0.1 3306; then | |
| echo "mysql not ready - gathering diagnostics" | |
| echo "--- Docker containers ---" | |
| docker ps -a --format 'table {{.ID}} {{.Names}} {{.Image}} {{.Status}}' | |
| echo "--- Listening ports ---" | |
| ss -ltnp || netstat -ltnp || true | |
| echo "--- MySQL logs (matching image name 'mysql') ---" | |
| for cid in $(docker ps -a --filter ancestor=mysql --format '{{.Names}}'); do | |
| echo "Logs for $cid:"; docker logs --tail 200 "$cid" || true | |
| done | |
| exit 1 | |
| fi | |
| echo "Waiting for rabbitmq (localhost:5672)..." | |
| wait_port 127.0.0.1 5672 || { echo "rabbitmq not ready"; exit 1; } | |
| echo "Waiting for localstack (localhost:4566)..." | |
| wait_port 127.0.0.1 4566 || { echo "localstack not ready"; exit 1; } | |
| - name: Create LocalStack SQS queue | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| python -m pip install "boto3==1.40.61" "botocore==1.40.61" "s3transfer==0.14.0" | |
| LOCALSTACK_ENDPOINT=http://127.0.0.1:4566 LOCALSTACK_QUEUE_NAME=test-queue python .github/scripts/create_sqs_queue.py | |
| - name: Initialize Postgres and MySQL schemas | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update -y | |
| sudo apt-get install -y postgresql-client default-mysql-client | |
| echo "Initializing Postgres schemas..." | |
| export PGPASSWORD=test | |
| for f in tests/infrastructure/postgres-init/*.sql; do | |
| echo "Applying $f to Postgres" | |
| psql -h 127.0.0.1 -U test -d test_db -f "$f" | |
| done | |
| echo "Initializing MySQL schemas..." | |
| for f in tests/infrastructure/mysql-init/*.sql; do | |
| echo "Applying $f to MySQL as root" | |
| mysql -h 127.0.0.1 -u root -ptest test_db < "$f" | |
| done | |
| - name: Run integration tests (activate .venv) | |
| env: | |
| ASYNCTASQ_REDIS_URL: redis://127.0.0.1:6379 | |
| ASYNCTASQ_POSTGRES_URL: postgresql://test:test@127.0.0.1:5432/test_db | |
| ASYNCTASQ_MYSQL_URL: mysql://test:test@127.0.0.1:3306/test_db | |
| ASYNCTASQ_RABBITMQ_URL: amqp://guest:guest@127.0.0.1:5672/ | |
| run: | | |
| set -euo pipefail | |
| if [ -f .venv/bin/activate ]; then | |
| . .venv/bin/activate | |
| fi | |
| pytest tests/integration -v --cov=src/asynctasq --cov-report=xml --cov-report=term-missing | |
| - name: Upload coverage artifact | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: coverage-integration-${{ matrix.python-version }} | |
| path: coverage.xml | |
| - name: Upload coverage to Codecov | |
| if: matrix.python-version == '3.12' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./coverage.xml | |
| flags: integrationtests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| # Enforce successful completion of all checks for PRs | |
| ci-success: | |
| name: CI Success | |
| if: always() | |
| needs: | |
| - lint-and-format | |
| - unit-tests | |
| - integration-tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check all jobs | |
| run: | | |
| if [[ "${{ needs.lint-and-format.result }}" != "success" ]] || \ | |
| [[ "${{ needs.unit-tests.result }}" != "success" ]] || \ | |
| [[ "${{ needs.integration-tests.result }}" != "success" ]]; then | |
| echo "One or more CI jobs failed" | |
| exit 1 | |
| fi | |
| echo "All CI jobs passed successfully" |