feat(deploy): scripts/deploy-api-only.sh + Hetzner doc for manual code-only redeploys
Some checks failed
Some checks failed
Manual deploys had been using a bare `git pull && docker compose up -d
--build api` sequence, which works for the container itself but silently
skipped writing `.build-info`. The stale `.build-info` left
`?v=<commit-sha>` pointing at the previous deploy's SHA on every shared
JS/CSS URL — so browsers happily kept cached pre-fix assets even after
a successful rebuild. Bit us today: ~5 hours of "is this even deployed?"
debugging on the loyalty-dashboard redirect-flicker fix.
deploy.sh wasn't a substitute because it's a CI/CD script: stashes
working tree, runs alembic, restarts every service in the full profile
(db, redis, api, celery-worker, celery-beat, flower), 60s health budget.
Heavy and disruptive for an api-only hotfix.
New scripts/deploy-api-only.sh fills the gap with the narrow path:
- Refuses if working tree is dirty (no silent stash → no pop conflicts).
- git pull --ff-only.
- Writes .build-info (the critical missing step).
- docker compose -f docker-compose.yml --profile full up -d --build api
(only the api service — db/redis/celery untouched).
- Tight 30s health budget since DB doesn't need to come back up.
- Exit codes 0/1/2/3 for clean automation.
docs/deployment/hetzner-server-setup.md §16.5 split into 16.5a
(code-only — points at the new script as the default) and 16.5b
(full deploy fallback — kept the existing deploy.sh path for migrations
/ Dockerfile / docker-compose / requirements changes). §12 footnote on
.build-info refreshed to mention both scripts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -559,7 +559,7 @@ docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
|
||||
```
|
||||
|
||||
!!! note "After the reset"
|
||||
`init_production.py` re-creates the four admin users with their **default** passwords (see `init_production.py:280-300`). Any admin-side configuration that lives in the `admin_settings` table (e.g. the manual SMTP overrides under `/admin/settings`) is wiped and must be re-applied. The `/health` endpoint reads `.build-info` which is only regenerated by `scripts/deploy.sh`, so after a manual reset it will report the **previous** commit; harmless but worth knowing.
|
||||
`init_production.py` re-creates the four admin users with their **default** passwords (see `init_production.py:280-300`). Any admin-side configuration that lives in the `admin_settings` table (e.g. the manual SMTP overrides under `/admin/settings`) is wiped and must be re-applied. The `/health` endpoint reads `.build-info` which is only regenerated by `scripts/deploy.sh` or `scripts/deploy-api-only.sh` (see [Step 16.5](#165-manual-deploy)), so after a manual reset it will report the **previous** commit; harmless but worth knowing.
|
||||
|
||||
### Seeded Data Summary
|
||||
|
||||
@@ -1197,14 +1197,51 @@ deploy:
|
||||
script: cd ${{ secrets.DEPLOY_PATH }} && bash scripts/deploy.sh
|
||||
```
|
||||
|
||||
### 16.5 Manual Fallback
|
||||
### 16.5 Manual Deploy
|
||||
|
||||
If CI is down, deploy manually:
|
||||
Two manual paths, pick the right one for the change you're shipping.
|
||||
|
||||
#### 16.5a — Code-only fix (default for ad-hoc manual deploys)
|
||||
|
||||
For frontend / template / api-only changes that don't touch the Dockerfile,
|
||||
requirements.txt, docker-compose.yml, or alembic migrations. Rebuilds and
|
||||
restarts **only** the api container — db, redis, celery-worker, celery-beat,
|
||||
flower stay running.
|
||||
|
||||
```bash
|
||||
cd ~/apps/orion && bash scripts/deploy-api-only.sh
|
||||
```
|
||||
|
||||
What it does (`scripts/deploy-api-only.sh`):
|
||||
|
||||
1. Refuses if working tree is dirty (no silent stash → no risk of pop conflicts).
|
||||
2. `git pull --ff-only`.
|
||||
3. **Writes `.build-info`** — this is the critical step that ensures the
|
||||
`?v=<commit-sha>` cache-bust query on every shared JS/CSS URL flips to the
|
||||
new SHA. Without this, browsers happily keep serving the previous
|
||||
deploy's cached assets even though the new code is in the image.
|
||||
4. `docker compose -f docker-compose.yml --profile full up -d --build api`.
|
||||
5. Health-check with a 30s budget (tight, since the DB/Redis weren't touched).
|
||||
|
||||
Exit codes: `0` success, `1` git pull / dirty tree, `2` docker build/up
|
||||
failed, `3` health check failed.
|
||||
|
||||
#### 16.5b — Full deploy (use when CI is down)
|
||||
|
||||
Use this when you've also changed migrations, the Dockerfile,
|
||||
requirements.txt, or docker-compose.yml itself — anything that needs the
|
||||
full restart-everything + migrate cycle that the CI runs. Restarts EVERY
|
||||
service in the `full` profile (db, redis, api, celery-worker, celery-beat,
|
||||
flower) and runs `alembic upgrade heads`.
|
||||
|
||||
```bash
|
||||
cd ~/apps/orion && bash scripts/deploy.sh
|
||||
```
|
||||
|
||||
Heavier — brief DB downtime, Redis is blown away (sessions / rate-limit
|
||||
counters / cached anything), in-flight Celery tasks killed — so don't use
|
||||
it for code-only fixes.
|
||||
|
||||
### 16.6 Verify
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user