Skip to content

docs: complete Google-style docstring coverage (99.2% → 100%) #113

docs: complete Google-style docstring coverage (99.2% → 100%)

docs: complete Google-style docstring coverage (99.2% → 100%) #113

Workflow file for this run

# CI/CD Pipeline - UV Workspace Aware
# Runs tests, linting, type checking, and security scans for each package.
#
# Features:
# - Path-based change detection (only test changed packages)
# - Per-package test jobs
# - Matrix testing (Python 3.10-3.13)
# - Security scanning (Bandit, Safety)
# - SonarCloud/Codecov integration
name: CI
on:
push:
branches: [main, master, develop]
pull_request:
types: [opened, synchronize, reopened]
branches: [main, master, develop]
workflow_dispatch:
# Cancel in-progress runs for same PR/branch
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
checks: write
jobs:
# Detect which packages have changed
detect-changes:
name: Detect Changed Packages
runs-on: ubuntu-latest
outputs:
cloudflare-auth: ${{ steps.filter.outputs.cloudflare-auth }}
gcs-utilities: ${{ steps.filter.outputs.gcs-utilities }}
shared: ${{ steps.filter.outputs.shared }}
any-package: >-
${{ steps.filter.outputs.cloudflare-auth == 'true' ||
steps.filter.outputs.gcs-utilities == 'true' ||
steps.filter.outputs.shared == 'true' }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Detect path changes
uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3
id: filter
with:
filters: |
cloudflare-auth:
- 'packages/cloudflare-auth/**'
gcs-utilities:
- 'packages/gcs-utilities/**'
shared:
- 'pyproject.toml'
- 'uv.lock'
- '.github/workflows/**'
- 'src/**'
# Test cloudflare-auth package
test-cloudflare-auth:
name: Test cloudflare-auth (Python ${{ matrix.python-version }})
needs: detect-changes
if: needs.detect-changes.outputs.cloudflare-auth == 'true' || needs.detect-changes.outputs.shared == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Install uv
uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install workspace dependencies
run: uv sync --all-extras
- name: Run tests with coverage
run: |
uv run pytest packages/cloudflare-auth/tests \
--cov=packages/cloudflare-auth/src/cloudflare_auth \
--cov-report=xml:coverage-cloudflare-auth.xml \
--cov-report=term-missing \
--no-cov-on-fail \
--cov-fail-under=0 \
-v
- name: Run type checker
run: uv run basedpyright packages/cloudflare-auth/src/
- name: Run linter
run: uv run ruff check packages/cloudflare-auth/
- name: Upload coverage artifact
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: coverage-cloudflare-auth
path: coverage-cloudflare-auth.xml
# Test gcs-utilities package
test-gcs-utilities:
name: Test gcs-utilities (Python ${{ matrix.python-version }})
needs: detect-changes
if: needs.detect-changes.outputs.gcs-utilities == 'true' || needs.detect-changes.outputs.shared == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Install uv
uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
enable-cache: true
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install workspace dependencies
run: uv sync --all-extras
- name: Run tests with coverage
run: |
uv run pytest packages/gcs-utilities/tests \
--cov=packages/gcs-utilities/src/gcs_utilities \
--cov-report=xml:coverage-gcs-utilities.xml \
--cov-report=term-missing \
--no-cov-on-fail \
--cov-fail-under=0 \
-v
- name: Run type checker
run: uv run basedpyright packages/gcs-utilities/src/
- name: Run linter
run: uv run ruff check packages/gcs-utilities/
- name: Upload coverage artifact
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: coverage-gcs-utilities
path: coverage-gcs-utilities.xml
# Security scan for entire workspace
security:
name: Security Scan
needs: detect-changes
if: needs.detect-changes.outputs.any-package == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Install uv
uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
with:
enable-cache: true
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Run Bandit security scan
run: |
uv run bandit -r packages/cloudflare-auth/src/ packages/gcs-utilities/src/ -c pyproject.toml || true
# Upload combined coverage to Codecov
coverage:
name: Upload Coverage
needs: [test-cloudflare-auth, test-gcs-utilities]
if: always() && (needs.test-cloudflare-auth.result == 'success' || needs.test-gcs-utilities.result == 'success')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Download coverage artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: coverage-*
merge-multiple: true
- name: Upload to Codecov
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
with:
files: coverage-cloudflare-auth.xml,coverage-gcs-utilities.xml
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# Terminal CI gate -- the single required check for branch protection.
# Runs even when test jobs are skipped (no changed packages). Skipped
# upstream jobs report result="skipped", which is not a failure.
ci-gate:
name: CI Gate
runs-on: ubuntu-latest
needs: [detect-changes, test-cloudflare-auth, test-gcs-utilities, security, coverage]
if: always()
steps:
- name: Check all jobs
env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
failed=$(echo "$NEEDS_JSON" | jq '[to_entries[] | select(.value.result == "failure")] | length')
if [ "$failed" -gt 0 ]; then
echo "::error::One or more CI jobs failed"
exit 1
fi
echo "CI Gate passed"