docs: make QA review a standing step in the change checklist
Records the two-environment layout and a numbered checklist every change follows, with QA review as a required stop rather than a judgement call. Production is not where a bad deploy should be found, which is what happened with the categories/tags release. Production promotion now retags the image QA reviewed rather than rebuilding, so what ships is exactly what was tested, and the README carries the full command sequence with a verification gate at each step. Also records the two gates that have already failed here: confirming a pushed commit is actually on the branch, and that a schema/code ordering problem cannot be caught by any local suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -158,12 +158,67 @@ Gitea Actions runs two workflows on every push to `main` and on pull requests:
|
||||
- Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) syntax: `feat:`, `fix:`, `chore:`, `docs:`, `test:`, `ci:`, `refactor:`, etc.
|
||||
- Branches are automatically deleted after a pull request is merged
|
||||
|
||||
## Shipping a change
|
||||
|
||||
Every change follows the same path. **QA is a required stop, not an optional one** — production is not the place to discover that a deploy is wrong.
|
||||
|
||||
| # | Step | Gate before moving on |
|
||||
| --- | --- | --- |
|
||||
| 1 | Implement on a branch, verify locally | Unit, integration, and e2e suites pass; `tsc --noEmit` and `npm run build` clean |
|
||||
| 2 | Commit and push | `git branch -a --contains <sha>` lists the pushed branch — a commit made after a push is silently left behind otherwise |
|
||||
| 3 | Open a PR and merge to `main` | The merge commit contains the expected commits |
|
||||
| 4 | **Deploy to QA and review it** | The change behaves as intended in a browser, behind authentik |
|
||||
| 5 | Promote the reviewed image to production | Migrations recorded, data intact, deployed bundle is the new one |
|
||||
| 6 | Stop the QA stack | — |
|
||||
|
||||
Steps 4 and 5 are detailed under [QA environment](#qa-environment) and [Production deployment](#production-deployment). Step 5 promotes the *same image* that was reviewed in QA, so what ships is what was tested.
|
||||
|
||||
## Production deployment
|
||||
|
||||
Production runs as a single Docker image (multi-stage build — the frontend is built to static files and served directly by the backend), deployed via Portainer behind Nginx Proxy Manager, with authentik forward-auth gating `/admin`. That infrastructure is homelab-specific and documented separately outside this repo.
|
||||
|
||||
The container applies pending migrations before starting the server, so deployed code can never be ahead of the database schema. A failed migration stops the container rather than letting it serve against a schema it doesn't match — check `docker logs` on the app container if it doesn't come up.
|
||||
|
||||
### Promoting a reviewed change to production
|
||||
|
||||
Only after the change has been reviewed in QA.
|
||||
|
||||
```bash
|
||||
# 1. Back up first — the container migrates the schema on its own.
|
||||
sudo docker exec -t redefined-designs-db-syn pg_dump -U redefined -d redefined \
|
||||
> /volume1/configs/redefined-designs/backup-$(date +%Y%m%d-%H%M).sql
|
||||
ls -lh /volume1/configs/redefined-designs/backup-*.sql # size must be plausible
|
||||
|
||||
# 2. Promote the exact image QA reviewed, rather than rebuilding a second time.
|
||||
sudo docker tag redefined-designs:qa redefined-designs:latest
|
||||
|
||||
# 3. Verify the image before touching the running container.
|
||||
sudo docker inspect --format '{{.Config.Cmd}}' redefined-designs:latest
|
||||
# must print: [sh -c node migrate.js up && node dist/server.js]
|
||||
|
||||
# 4. Recreate the container — restarting it would keep the old image.
|
||||
sudo docker stop redefined-designs-syn
|
||||
sudo docker rm redefined-designs-syn
|
||||
# redeploy the stack in Portainer
|
||||
|
||||
# 5. Verify, in this order.
|
||||
sudo docker logs redefined-designs-syn | head -30
|
||||
# migration output appears BEFORE "listening on 3000",
|
||||
# and "listening on 3000" appears exactly once (repeats = crash loop)
|
||||
|
||||
sudo docker exec -it redefined-designs-db-syn psql -U redefined -d redefined \
|
||||
-c "SELECT name, run_on FROM pgmigrations ORDER BY run_on;"
|
||||
sudo docker exec -it redefined-designs-db-syn psql -U redefined -d redefined \
|
||||
-c "SELECT count(*) FROM items;"
|
||||
|
||||
# 6. Confirm the deployed artifact, not just the source.
|
||||
sudo docker exec redefined-designs-syn sh -c "grep -l 'must have all' /app/public/assets/*.js"
|
||||
```
|
||||
|
||||
Then load the storefront in a private window — aggressive bundle caching has produced false "still broken" reports on this project even after a correct deploy.
|
||||
|
||||
**Rollback:** migrations here have been additive, so the previous image still runs against the migrated schema — retag the old image and redeploy. Restoring the SQL dump is a last resort, not a first move.
|
||||
|
||||
## QA environment
|
||||
|
||||
`docker-compose.qa.yml` defines a disposable QA stack for reviewing merged-but-undeployed changes online. It runs alongside production on the same NAS with its own containers, database, volumes, and host port, and is started only when a review is needed.
|
||||
|
||||
Reference in New Issue
Block a user