From 262024507cb65f9109470f680ef3550ddff00974 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 4 Sep 2026 07:22:51 +0000 Subject: [PATCH] ci: stop duplicating work across jobs and fix the release tag guard The check job ran pre-commit with every hook, including the local test hook, so the suite ran seven times per pull request: once under 3.13 with coverage there and once more in each leg of the matrix. Nothing cancelled superseded runs either, so three pushes to a branch kept 24 jobs alive. - Skip the test hook in the check job and move the coverage run, with the credentials it needs for the integration tests, into the 3.13 leg of the matrix, which now owns testing - Cancel superseded pull request runs, leaving master runs alone since they gate the release - Fold the changelog job into check, which spent a whole runner on a grep - Install uv with astral-sh/setup-uv, replacing the curl install and the explicit cache steps, and keep a cache per Python version - Bound every job with timeout-minutes, they defaulted to six hours - Narrow the workflow permissions to the contents read that checkout needs The release workflow looked for a tag named v while it creates , and its shallow checkout fetched no tags to look at, so the guard against releasing an existing version never fired. It now checks refs/tags/ with the full history, and builds with uv build instead of installing build with pip under a separate Python. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Qwt5Ey1txWtHnhN5bonYy5 --- .github/workflows/check.yml | 73 +++++++++++++++++++---------------- .github/workflows/release.yml | 22 +++++------ CHANGELOG.md | 2 + 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 10711f8..ef10a4e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -7,18 +7,24 @@ on: pull_request: permissions: - pull-requests: read + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - changelog: - if: github.event_name == 'pull_request' + check: runs-on: ubuntu-latest + timeout-minutes: 10 + steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - name: Check CHANGELOG was updated + if: github.event_name == 'pull_request' run: | if git diff --name-only origin/${{ github.base_ref }}...HEAD | grep -q "^CHANGELOG.md$"; then echo "✅ CHANGELOG.md was updated" @@ -28,33 +34,16 @@ jobs: exit 1 fi - check: - runs-on: ubuntu-latest - env: - AFFILIATE_TAG: ${{ secrets.AFFILIATE_TAG }} - COUNTRY_CODE: ${{ secrets.COUNTRY_CODE }} - CREDENTIAL_ID: ${{ secrets.CREDENTIAL_ID }} - CREDENTIAL_SECRET: ${{ secrets.CREDENTIAL_SECRET }} - API_VERSION: ${{ secrets.API_VERSION }} - - steps: - - uses: actions/checkout@v5 - - name: Set up Python uses: actions/setup-python@v6 with: python-version: "3.13" - name: Install UV - run: curl -LsSf https://astral.sh/uv/install.sh | sh - - - name: Cache UV dependencies - uses: actions/cache@v4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-${{ hashFiles('pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-uv- + enable-cache: true + cache-dependency-glob: pyproject.toml - name: Cache pre-commit uses: actions/cache@v4 @@ -64,32 +53,48 @@ jobs: restore-keys: | ${{ runner.os }}-pre-commit- + # Tests are owned by the test job below, so the test hook is skipped here. - name: Run all checks - run: | - uv run --extra async pre-commit run --all-files --verbose + env: + SKIP: test + run: uv run --extra async pre-commit run --all-files --verbose test: runs-on: ubuntu-latest - timeout-minutes: 2 + timeout-minutes: 5 strategy: fail-fast: false matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] + include: + # Only this leg has the credentials for the integration tests, so it + # is the one that can meet the coverage threshold. + - python-version: "3.13" + coverage: true steps: - uses: actions/checkout@v5 - name: Install UV - run: curl -LsSf https://astral.sh/uv/install.sh | sh - - - name: Cache UV dependencies - uses: actions/cache@v4 + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 with: - path: ~/.cache/uv - key: ${{ runner.os }}-uv-py${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-uv-py${{ matrix.python-version }}- + enable-cache: true + cache-dependency-glob: pyproject.toml + # Each version resolves to different wheels, so they cannot share one + # cache entry. + cache-suffix: py${{ matrix.python-version }} - name: Run tests + if: ${{ !matrix.coverage }} run: uv run --python "${{ matrix.python-version }}" --extra async pytest -rs --no-cov + + - name: Run tests with coverage + if: ${{ matrix.coverage }} + env: + AFFILIATE_TAG: ${{ secrets.AFFILIATE_TAG }} + COUNTRY_CODE: ${{ secrets.COUNTRY_CODE }} + CREDENTIAL_ID: ${{ secrets.CREDENTIAL_ID }} + CREDENTIAL_SECRET: ${{ secrets.CREDENTIAL_SECRET }} + API_VERSION: ${{ secrets.API_VERSION }} + run: uv run --python "${{ matrix.python-version }}" --extra async pytest -rs --cov=amazon_creatorsapi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9bf3671..aab0770 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,7 @@ permissions: jobs: release: runs-on: ubuntu-latest + timeout-minutes: 10 if: github.ref == 'refs/heads/master' environment: pypi outputs: @@ -19,6 +20,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v5 + with: + # Needed so the tag existence check below can see the tags. + fetch-depth: 0 - name: Extract version and notes from CHANGELOG id: changelog @@ -40,7 +44,7 @@ jobs: - name: Check if tag already exists id: check_tag run: | - if git rev-parse "v${{ steps.changelog.outputs.version }}" >/dev/null 2>&1; then + if git rev-parse -q --verify "refs/tags/${{ steps.changelog.outputs.version }}" >/dev/null; then echo "exists=true" >> $GITHUB_OUTPUT else echo "exists=false" >> $GITHUB_OUTPUT @@ -59,21 +63,17 @@ jobs: - name: Skip release (tag exists) if: steps.check_tag.outputs.exists == 'true' run: | - echo "⚠️ Tag v${{ steps.changelog.outputs.version }} already exists. Skipping release creation." + echo "⚠️ Tag ${{ steps.changelog.outputs.version }} already exists. Skipping release creation." exit 1 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Install UV + uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 with: - python-version: "3.x" - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build + # uv build only needs the build backend, not the project dependencies. + enable-cache: false - name: Build package - run: python -m build + run: uv build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ae241..05b2e1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AmazonCreatorsApi` API requests now time out after 30 seconds instead of waiting indefinitely, matching the timeout already used by `AsyncAmazonCreatorsApi`. Pass `timeout=None` to restore the previous behavior - `AsyncAmazonCreatorsApi` now applies `timeout` to the OAuth2 token refresh as well, which previously always used the 5 second default from `httpx` +- The CI workflow now runs the test suite once per Python version instead of also running it inside the linter job, cancels superseded pull request runs and installs `uv` through a cached action +- The release workflow now builds with `uv build`, and its check for an already existing tag now looks for the tag name that is actually created, which never matched before ## [7.0.0] - 2026-09-03