CI: fail fast on expired/wrong-org API key - #97
Conversation
Live tests run against prod gated on a manually-rotated API key, so an expired/invalid or wrong-org key currently surfaces as a confusing failure deep inside the suite — either a swallowed ClientError reported as "No data_id found" (test_get) or an opaque HTTP 500. - Add scripts/ci_auth_preflight.py and a `preflight` CI job (runs once before the 3x4 matrix). It authenticates and checks the required data types exist, failing fast with an actionable message that distinguishes an expired/invalid key (401/403) from a wrong-org key (auth OK, no data). - test_get: re-raise 401/403 from search() as a clear pytest.fail instead of swallowing it via `except ClientError: continue` (other errors, e.g. an alias unsupported for the org, stay benign). - ruff: ignore T201 under scripts/ (CLI status scripts print by design). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| .github/workflows/testing.yml | Adds a preflight job after lint and makes the live-test matrix depend on its success. |
| scripts/ci_auth_preflight.py | Validates API authentication and corpus availability, but transport exceptions bypass its diagnostic handling. |
| tests/test_client.py | Converts search authentication responses into an explicit pytest failure while retaining fallback behavior for other HTTP errors. |
| pyproject.toml | Allows intentional print calls in scripts without changing lint behavior elsewhere. |
Sequence Diagram
sequenceDiagram
participant CI as GitHub Actions
participant P as Preflight script
participant API as Atomscale API
participant T as Test matrix
CI->>P: Run after lint
loop Required data types
P->>API: "search(type, status=success)"
API-->>P: Results or error
end
alt Authentication/corpus check passes
P-->>CI: Exit 0
CI->>T: Start matrix
else Check fails
P-->>CI: Exit 1
CI--xT: Skip matrix
end
Prompt To Fix All With AI
### Issue 1
scripts/ci_auth_preflight.py:43-44
**Transport failures bypass diagnostics**
When DNS, TLS, timeout, or connection errors occur, `client.search()` raises a transport exception rather than `ClientError`, so the preflight emits a raw traceback and skips the test matrix without the actionable diagnostic this job is intended to provide.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "Add CI auth preflight and surface auth e..." | Re-trigger Greptile
| data = client.search(data_type=data_type, status="success") | ||
| except ClientError as exc: |
There was a problem hiding this comment.
Transport failures bypass diagnostics
When DNS, TLS, timeout, or connection errors occur, client.search() raises a transport exception rather than ClientError, so the preflight emits a raw traceback and skips the test matrix without the actionable diagnostic this job is intended to provide.
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/ci_auth_preflight.py
Line: 43-44
Comment:
**Transport failures bypass diagnostics**
When DNS, TLS, timeout, or connection errors occur, `client.search()` raises a transport exception rather than `ClientError`, so the preflight emits a raw traceback and skips the test matrix without the actionable diagnostic this job is intended to provide.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Why
The live test suite runs against prod, gated on a manually-rotated
AS_API_KEYsecret. When that key expires, becomes invalid, or is scoped to the wrong organization, the failure surfaces in a confusing way that looks like a code bug:test_getloops over data types and doesexcept ClientError: continue, then reportspytest.fail("No data_id found for required data type 'rheed_image'")— an auth/org problem disguised as missing data.HTTP 500deep inside the parallel fan-out.Neither points at the real cause (the key), and both only appear after the full 3×4 matrix has spun up.
What
preflightCI job (new) — runs once afterlint, before the test matrix (testnowneeds: preflight). It authenticates and checks the required data types are present, then fails fast with an actionable message that distinguishes the two failure modes:401/403→ "AS_API_KEY is expired, invalid, or malformed — refresh the AS_API_KEY repository secret."scripts/ci_auth_preflight.py(kept in sync withtest_get'srequired_types).test_getno longer hides auth errors — a401/403fromsearch()is re-raised as a clearpytest.failinstead of being swallowed byexcept ClientError: continue. OtherClientErrors (e.g. an alias unsupported for the org) stay benign and try the next alias.T201(print) ignored underscripts/, since CLI status scripts print by design.Effect
Notes for reviewer
uv pip install --system -e .) and hitshttps://api.atomscale.aiwithsecrets.AS_API_KEY, same as the test job.pre-commit runpasses ruff / ruff-format / codespell on the changed files; the script exits 1 with a clean message when no key is set. (tyonly checkssrc/atomicds, untouched here.)ResultIDsso a newly-ingested bad prod record can't wedgetest_get.🤖 Generated with Claude Code