Three categories of pre-existing CI failure on PR #42:
1. typecheck (mypy src/cartsnitch_api, 9 errors):
- src/cartsnitch_api/config.py:89 — Settings() needs required secret
args that only exist in env at runtime; suppress with
type: ignore[call-arg]
- src/cartsnitch_api/cache.py:38 — redis-py returns Any/bytes,
normalize to str before returning from get()
- src/cartsnitch_api/middleware/rate_limit.py:128,131,134 — three
limiter globals were inferred as RedisSlidingWindow on the if
branch then re-assigned InMemorySlidingWindow on else; declare
them as RateLimitBackend up front
- src/cartsnitch_api/middleware/rate_limit.py:181,187 —
RateLimitBackend Protocol didn't declare max_requests even
though both InMemorySlidingWindow and RedisSlidingWindow expose
it; add max_requests: int to the Protocol
2. test (FK constraint on purchases.user_id):
- tests/conftest.py:_create_test_user_and_session stored user_id
as 32-char hex; test_e2e conftest reads it via raw SQL and wraps
in uuid.UUID (36 chars) before passing to Purchase.user_id, so
the FK never matched. Switch back to str(uuid.uuid4()) (36 chars)
so the stored value and the FK bind value use the same format.
3. Verify lint + format clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Builds on the partial bd6b137 fix (which only stripped server_default
expressions) by also:
- Add _StringUUID TypeDecorator: lets Text/String/UUID columns accept
uuid.UUID values on bind (SQLite has no native UUID type) and returns
uuid.UUID on read so existing test assertions like
isinstance(store.id, uuid.UUID) still pass.
- Replace UUID column types with _StringUUID before create_all so
CREATE TABLE uses CHAR(36) instead of the native UUID type that
SQLite can't bind.
- Extend before_insert listener to also set Text PK columns (User.id)
and func.now()-stripped columns (ingested_at) to Python-side defaults
so INSERTs without explicit values succeed under SQLite.
- Switch _create_test_user_and_session to use 32-char hex user/session
ids so they match the format bound by the TypeDecorator on FK reads.
- Simplify test_encrypted_json.py to use the shared engine/session
fixtures from conftest instead of duplicating its own broken engine.
Tests passing: tests/test_models.py (14), tests/test_encrypted_json.py (6).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>