mirror of
https://github.com/pydantic/pydantic-ai-harness.git
synced 2026-07-21 02:45:34 +00:00
Path-scope the live LocalStack job; drop the stale greenlet pin
The localstack-integration job installs the AWS CLI, pulls the image, and starts a real container against the auth token -- weight unrelated PRs shouldn't pay. A `changes` job (dorny/paths-filter) now gates it on LocalStack paths for pull_request events, and `check` allows the skip so the required aggregate still passes. A run that actually fires still votes, so a live failure keeps blocking merges as before; push/tag events run it unconditionally. Also remove the test-floor greenlet --exclude-newer-package pin: greenlet 3.5.3 has shipped Linux wheels since 2026-06-26, main never carried the pin, and its test-floor is green without it.
This commit is contained in:
@@ -21,6 +21,27 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# Detect whether a pull request touches LocalStack. The live integration job
|
||||
# installs the AWS CLI, pulls the LocalStack image, and starts a real
|
||||
# container against an external auth token -- weight that only pays off when
|
||||
# LocalStack code or its CI wiring changes. Only runs on pull_request; on
|
||||
# push/tag events localstack-integration runs unconditionally.
|
||||
changes:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
localstack: ${{ steps.filter.outputs.localstack }}
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
localstack:
|
||||
- 'pydantic_ai_harness/localstack/**'
|
||||
- 'tests/localstack/**'
|
||||
- 'integration_tests/localstack/**'
|
||||
- '.github/workflows/main.yml'
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -109,12 +130,7 @@ jobs:
|
||||
# The lock validation must be off here: this job deviates from the lock
|
||||
# on purpose, and under UV_LOCKED=1 the lowest-direct resolution fails
|
||||
# because uv refuses to write the lowest-resolved lockfile it produces.
|
||||
# greenlet 3.5.3 was published without Linux wheels, which makes uv's
|
||||
# install phase fail on Ubuntu runners after resolution succeeds.
|
||||
- run: >
|
||||
uv sync --resolution lowest-direct
|
||||
--exclude-newer-package greenlet=2026-06-25T00:00:00Z
|
||||
--group dev --all-extras
|
||||
- run: uv sync --resolution lowest-direct --group dev --all-extras
|
||||
env:
|
||||
UV_LOCKED: '0'
|
||||
- run: uv run --no-sync pytest
|
||||
@@ -154,6 +170,11 @@ jobs:
|
||||
- run: uv run --no-sync pytest
|
||||
|
||||
localstack-integration:
|
||||
needs: [changes]
|
||||
# Skip on pull requests that leave LocalStack untouched; always run on
|
||||
# push/tag events so releases exercise the live path. `always()` lets this
|
||||
# evaluate even though `changes` is skipped on non-pull_request events.
|
||||
if: ${{ always() && (github.event_name != 'pull_request' || needs.changes.outputs.localstack == 'true') }}
|
||||
runs-on: ubuntu-latest
|
||||
name: LocalStack integration tests
|
||||
# The auth token secret lives in this environment; binding the job to it also
|
||||
@@ -216,11 +237,15 @@ jobs:
|
||||
|
||||
check:
|
||||
if: always()
|
||||
needs: [lint, test, test-floor, test-latest, coverage, localstack-integration]
|
||||
needs: [changes, lint, test, test-floor, test-latest, coverage, localstack-integration]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
||||
with:
|
||||
# localstack-integration is skipped on pull requests that don't touch
|
||||
# LocalStack, and `changes` is skipped on push/tag events. Both still
|
||||
# vote (block the merge) when they actually run and fail.
|
||||
allowed-skips: changes, localstack-integration
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
||||
release:
|
||||
|
||||
@@ -38,10 +38,23 @@ def test_localstack_ci_gates_the_aggregate_check() -> None:
|
||||
|
||||
# The aggregate `check` job must depend on localstack-integration so a live
|
||||
# test failure blocks merges rather than passing silently.
|
||||
needs = next(line for line in lines if line.strip().startswith('needs: [lint, test'))
|
||||
needs = next(line for line in lines if line.strip().startswith('needs: [') and 'coverage' in line)
|
||||
assert 'localstack-integration' in needs
|
||||
|
||||
|
||||
def test_localstack_integration_is_scoped_to_localstack_changes() -> None:
|
||||
lines = _workflow_lines()
|
||||
|
||||
# On a pull request the live job runs only when LocalStack paths change, so
|
||||
# unrelated PRs don't pull the image, install the AWS CLI, or spend the token.
|
||||
assert any('needs.changes.outputs.localstack' in line for line in lines)
|
||||
assert any("- 'pydantic_ai_harness/localstack/**'" in line for line in lines)
|
||||
|
||||
# A skipped live job must not fail the required aggregate check; a job that
|
||||
# actually runs and fails still votes (see allowed-skips semantics).
|
||||
assert any('allowed-skips: changes, localstack-integration' in line for line in lines)
|
||||
|
||||
|
||||
def test_localstack_ci_scopes_the_auth_token_to_the_test_step() -> None:
|
||||
lines = _workflow_lines()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user