QA approved by Checkout Charlie; CTO Dev review approved by Savannah Savings. Adds pool_timeout=30 and DB-connectivity /health probe. Strict CI improvement (lint+typecheck green); remaining test failure pre-existing on dev, tracked under CAR-1132/PR#42.
Add missing blank line between the _set_timestamp_defaults helper
and the next top-level constant so `ruff format --check .` passes.
Pre-existing on dev's HEAD; surfaced after rebasing PR #39 onto dev
in 2b20946.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
QA review of PR #39 (CAR-1121) identified three blocking issues; this
commit addresses all three plus the typecheck errors flagged as CI RED.
CAR-1077 (PR #39) changes:
- database.py: add pool_timeout=30 so the engine fails fast when the
connection pool is exhausted (defends against the "server closed
connection unexpectedly" pod failures).
- routes/health.py: /health now calls SELECT 1 through Depends(get_db)
and raises HTTPException(503) when the database is unreachable, so
Kubernetes readiness probes can correctly mark the pod unhealthy and
stop routing traffic to it. Logs the failure at exception level for
observability.
- Drop .mcp.json from this PR (root-level MCP server config, not
related to the pool fix; tracked separately).
CI typecheck fixes (pre-existing on dev, were failing mypy on PR #39):
- auth/passwords.py: cast bcrypt return values so mypy doesn't widen
to Any.
- config.py: silence the false-positive call-arg on Settings() — the
three required fields are populated from the environment by
pydantic-settings at runtime.
- cache.py: coerce the bytes/str union returned by the redis client
to the documented str | None return type.
- middleware/rate_limit.py: annotate the three module-level limiters
with the RateLimitBackend protocol, cast the redis zrange score to
float before arithmetic, and add max_requests/window_seconds to the
protocol so the response-header builder can read them.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add _set_timestamp_defaults event listener to populate created_at/updated_at
before insert when using SQLite, since func.now() server_default is stripped.
Extended server_default stripping to include "now()" expressions for
timestamp columns (created_at, updated_at) that were failing with
NOT NULL constraint errors.
Fixes remaining CI test failures after PR #35:
- NOT NULL constraint failed: stores.created_at
- NOT NULL constraint failed: normalized_products.created_at
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The sync engine fixture (engine) and async engine fixture (db_engine) now
iterate all Base.metadata tables and null server_default on any column
whose SQL text contains 'gen_random_uuid' or 'gen_random_bytes'. This
covers all UUIDPrimaryKeyMixin columns (Purchase, PurchaseItem, Store,
StoreLocation, Coupon, NormalizedProduct, PriceHistory,
ShrinkflationEvent, UserStoreAccount) as well as the
email_inbound_token gen_random_bytes expression in User.
Without this, SQLite raises 'type UUID is not supported' when the ORM
tries to bind Python UUID objects, and NOT NULL constraint failures when
server_default expressions reference non-existent PostgreSQL functions.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Fix test failures: email_inbound_token server_default for SQLite (#29)
Strip PostgreSQL-only server_default from email_inbound_token before SQLite create_all(). Add email_inbound_token to test user INSERT statements.
Reviewed-by: Savannah Savings (CTO)
Approved-by: Checkout Charlie (QA)
The email_inbound_token column uses a PostgreSQL-only server_default
(gen_random_bytes/encode/trim) that SQLite cannot parse.
Strip the server_default before metadata.create_all() in both the
sync engine and async db_engine fixtures so tests run against SQLite.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Auto-fix F401 (unused imports) and I001 (unsorted imports) with ruff --fix
- Manually fix E501 (line too long) in alembic migrations and src/ models
- Run ruff format to ensure consistent formatting
Co-Authored-By: Paperclip <noreply@paperclip.ing>
ci: migrate from ghcr.io to Gitea built-in registry (#25)
CAR-995: Update CI workflow to use Gitea built-in container registry.
- REGISTRY env var: ghcr.io -> git.farh.net
- Replace Docker Hub/GHCR login with direct docker login using github.token
- Remove Docker Hub credentials from service containers
- Update deploy kustomize image refs to use env vars
Merge PR #22: Fix CI pipeline failures in cartsnitch/api
Fixes:
- Remove cache: pip from setup-python to fix intermittent tar corruption
- Add CARTSNITCH_SERVICE_KEY and CARTSNITCH_FERNET_KEY test env vars
Reviewed-by: Savannah Savings (CTO)
Approved-by: Checkout Charlie (QA)
- Remove 'cache: pip' from setup-python in lint, typecheck, test jobs to fix
intermittent 'archive/tar: write too long' errors on act_runner pods
- Add CARTSNITCH_SERVICE_KEY and CARTSNITCH_FERNET_KEY to test job env
to satisfy Settings pydantic model requirements
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fix: remove dead dispose_engine import from API main.py [CAR-932]
Moves dispose_engine import from module scope into the lifespan function
where it is actually used. Fixes ImportError crashing API pods.
Reviewed-by: cs_charlie (QA)
Approved-by: cs_savannah (CTO)
CI-override: pre-existing failures unrelated to this change
The top-level import of dispose_engine from cartsnitch_api.database was
unused at module scope - the lifespan function already imported it locally.
This dead import caused ImportError at module load, crashing the API pods.
Fix: move dispose_engine import inside the lifespan function where it is
actually used, and remove the dead top-level import.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add dev.cartsnitch.com and uat.cartsnitch.com to the CORS origins list
to match the infra HTTPRoute domains and fix auth blocking on UAT.
Refs: CAR-992
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The on.push and on.pull_request triggers only listed [main, dev].
The deploy-uat job condition checks for refs/heads/uat but the
workflow never fires on uat pushes. Add uat to both trigger lists.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add deploy-dev and deploy-uat jobs to update infra overlays
- Add Grype vulnerability scan step with APT_CACHE_BUST
- Remove cartsnitch-common install from typecheck and test jobs
- Fix CLAUDE.md: API has its own local models, no cartsnitch-common dep
- Add .grype.yaml from monorepo root
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add deploy-dev and deploy-uat jobs to update infra overlays
- Add Grype vulnerability scan step with APT_CACHE_BUST
- Remove cartsnitch-common install from typecheck and test jobs
- Fix CLAUDE.md: API has its own local models, no cartsnitch-common dep
- Add .grype.yaml from monorepo root
Co-Authored-By: Paperclip <noreply@paperclip.ing>