Commit Graph

19 Commits

Author SHA1 Message Date
tyler babac8734d fix: revert to one-psql-per-migration to avoid aborted transaction cascade
Deploy to route.crispygoat.com / deploy (push) Failing after 2m1s
Build / build (push) Has been cancelled
Batching all migrations into one psql session caused a hard error to put
Postgres into an aborted transaction state, blocking every subsequent
migration. Back to per-file calls with PAGER= still set to prevent hang.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 20:07:48 -06:00
tyler 2d3c995135 fix: set PAGER= to prevent psql hanging on non-interactive terminal
Deploy to route.crispygoat.com / deploy (push) Has been cancelled
Build / build (push) Has been cancelled
psql was launching less/more for query output in the CI shell, then
blocking indefinitely on "Press RETURN to continue". Also batch all
numbered migrations into one psql session instead of one process per file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 20:05:50 -06:00
tyler 803cc5470d fix: use fixed port 3010 for production postgrest, remove dynamic allocation
Deploy to route.crispygoat.com / deploy (push) Has been cancelled
Build / build (push) Has been cancelled
Dynamic port leasing was the root cause of all the "address already in use"
failures. Production now always uses 3010; dev still uses 3001. No more
.postgrest-port file, no more port scanning loop, no more race conditions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:12:06 -06:00
tyler 7dd29cc44f fix: use separate docker ps calls to remove containers by name prefix
Deploy to route.crispygoat.com / deploy (push) Failing after 12s
Build / build (push) Has been cancelled
Multiple --filter name= flags are ANDed in docker ps, so combining
route_commerce_ and route-commerce- in one call matched nothing and
left db/minio running. Split into two calls, dedup with sort -u.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:09:40 -06:00
tyler 0771b401f3 fix: tear down all route-commerce containers by name before redeploy
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled
docker compose down was silently failing (|| true) when the compose file
was stale, leaving db/minio running on the old network subnet. The new
postgrest container then couldn't bind because Docker tried to reuse the
same subnet with conflicting container IPs.

Now: rm -f all containers matching route_commerce_/route-commerce- by name
first (works regardless of compose file state), then remove the network
explicitly so Docker allocates a clean subnet on the next up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:04:41 -06:00
tyler 472f188ea6 fix: kill docker-proxy broadly to prevent port binding race on redeploy
Deploy to route.crispygoat.com / deploy (push) Failing after 15s
Build / build (push) Has been cancelled
The three hardcoded pkill lines only covered ports 3011-3013. docker-proxy
can linger after compose down, causing "address already in use" when the new
stack races to bind the same port. Replace with a single pattern covering all
30xx ports and bump sleep to 5s.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 19:03:13 -06:00
tyler 7ddb06d7bd fix(deploy): harden port-freeing against TOCTOU bind failures
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled
The Start Docker stack step was racing itself: docker compose down
errors were silently swallowed (|| true), leaving the previous
postgrest container in a half-torn-down state. fuser -k would kill
the listener, ss would see 3011 as free, the script would pick 3011,
and then docker compose up would fail to bind because the port was
in TIME_WAIT (or a stale docker-proxy listener was still holding it).

Three changes:

1. Don't swallow docker compose down errors. If the previous stack
   isn't actually down, fail loudly so we can investigate.
2. Explicitly remove any surviving route_commerce_postgrest container
   and kill any leftover docker-proxy listeners for ports 3011-3013
   before picking a port.
3. Verify the postgrest container is gone after the cleanup. If it's
   not, exit 1 instead of continuing into a guaranteed bind failure.
4. Port-picking loop now retries with a 1s sleep on each port (handles
   TIME_WAIT settling), and uses a stricter ss grep that matches
   127.0.0.1:<port> anchored on whitespace to avoid false positives
   from substring matches (e.g. :30110 matching :3011).

Reproduces the failure mode from the run on 2026-06-06: postgrest
failed to bind 127.0.0.1:3011 with 'address already in use' even
though the script had just reported it as free.
2026-06-06 00:55:38 +00:00
tyler ffed10cd66 fix(deploy): dynamically find a free PostgREST host port
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled
Previous attempts hardcoded 3011, but something on tyler's host is
holding 3011 too. Instead of guessing ports, make the deploy probe
for the first free port starting from 3011 and thread that choice
through the rest of the workflow.

How it works:
1. Start Docker stack frees 3001 + the previous deploy's chosen port
   (read from .postgrest-port) so the lowest free port can be picked
   back up
2. Loops from 3011 upward, checking ss -tln until it finds a free
   port in the 3011-30200 range
3. Writes the chosen port to .postgrest-port in the workspace
4. Sets NEXT_PUBLIC_API_URL based on that port
5. Writes POSTGREST_HOST_PORT and NEXT_PUBLIC_API_URL to the .env
   that docker compose reads
6. Build and Deploy steps read .postgrest-port to set their
   NEXT_PUBLIC_API_URL dynamically — no more hardcoded 3011
2026-06-06 00:12:23 +00:00
tyler 9759dd042e fix(deploy): move PostgREST host port to 3011 to coexist with dev stack
Build / build (push) Has been cancelled
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
The dev PostgREST (started outside docker compose for local development)
and the production PostgREST (started by docker compose up) were both
trying to bind 127.0.0.1:3001. Even with fuser -k in the deploy cleanup,
something on tyler's host (likely a process supervisor restarting the
dev PostgREST) keeps reclaiming 3001 between our check and the
docker bind.

Move the production PostgREST to host port 3011, keeping the container's
internal port at 3001 (PostgREST's default). This lets dev and prod
coexist on the same host without fighting over a port.

Update NEXT_PUBLIC_API_URL to http://localhost:3011 in:
- Build step env (so the build bakes in the right URL)
- Start Docker stack .env append (so docker compose + app see the URL)
- Deploy step .env.production writing (so runtime app uses 3011)
2026-06-06 00:05:18 +00:00
tyler e6911a184c fix(deploy): use --force-recreate on docker compose up
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled
The previous attempt's `docker compose down` removed the project's
network, but on the subsequent `docker compose up`, the postgrest
container was being recreated rather than created from scratch, and
its network attachment still pointed to the now-orphaned old network
ID. The new db/minio containers attached to the freshly-created
network fine; only postgrest failed with 'network ... not found'.

`-d --force-recreate` tells docker compose to throw away any
existing container state and build from scratch, eliminating stale
network references.
2026-06-05 23:59:32 +00:00
tyler 427c728900 fix(deploy): free port 3001 before bringing up the stack
Deploy to route.crispygoat.com / deploy (push) Failing after 13s
Build / build (push) Has been cancelled
On hosts with leftover dev processes or stuck containers from prior
attempts, docker compose fails with 'address already in use' when
trying to bind PostgREST to 127.0.0.1:3001. The previous deploy
attempt actually got as far as starting Postgres and MinIO, then
PostgREST failed at port binding — leaving the Postgres container
running, which would persist for the next attempt and keep
re-occupying 3001 indirectly.

Add a defensive pre-check: if 3001 is bound, kill the holder
(fuser -k) and remove any docker container publishing 3001, then
docker compose down --remove-orphans to clear stuck state. Sleep 3
to let the kernel release the port.
2026-06-05 23:55:30 +00:00
tyler d29835c146 fix(deploy): seed docker-compose.yml and supabase/ into APP_DIR
Build / build (push) Has been cancelled
Deploy to route.crispygoat.com / deploy (push) Failing after 18s
Same first-deploy bootstrap pattern as .env.example: 'Start Docker stack'
needs docker-compose.yml at $APP_DIR for 'docker compose up', and
'Apply migrations' needs supabase/migrations/ at $APP_DIR for psql.
Neither was copied there until the 'Deploy' step runs at the end of
the job — so the first deploy on a fresh host fails before any
runtime file is ever placed.

Each step now seeds the file/dir it needs from the workspace before
using it. The 'Deploy' step's later copy remains as a refresh for
subsequent deploys.
2026-06-05 23:20:26 +00:00
tyler 1c133c5e06 fix(deploy): seed .env.example into APP_DIR if missing
Deploy to route.crispygoat.com / deploy (push) Failing after 3s
Build / build (push) Has been cancelled
The Start Docker stack step does `cd $APP_DIR && [ -f .env ] || cp .env.example .env`
but never ensured .env.example existed in APP_DIR. The rsync in the Deploy step
also doesn't copy it. The first deploy on a fresh host therefore failed with
'cp: cannot stat .env.example' before ever bringing up the stack.

Fix: copy .env.example from the workspace into APP_DIR if it isn't already
there, before the cd.
2026-06-05 23:17:10 +00:00
tyler 452eef7606 feat(deploy): bring up Docker stack + apply migrations in Gitea workflow 2026-06-05 15:22:38 +00:00
tyler e41ce98b74 Fix workflow: use actual secrets, fix env file writing 2026-06-05 15:12:53 +00:00
tyler 85db68ed70 Load .env.production from server before build 2026-06-05 15:12:53 +00:00
tyler 4eb6b173e0 Use npm install instead of npm ci (no lockfile) 2026-06-05 15:12:53 +00:00
tyler 2635c0a99d Remove npm cache from workflow (local runner) 2026-06-05 15:12:53 +00:00
tyler 3a9c6e3934 Add Gitea Actions deploy workflow 2026-06-05 15:12:53 +00:00