80 lines
3.8 KiB
Markdown
80 lines
3.8 KiB
Markdown
# Automatic production deployment
|
|
|
|
The server checks `https://git.ayau.me/syntaxbullet/minabot.git`, branch `main`, every
|
|
minute after the last check finishes. A local commit is deployed after it is
|
|
pushed to Gitea. Other branches are not deployed. If several commits arrive
|
|
between checks, the latest fetched main commit is built.
|
|
|
|
```sh
|
|
git push origin main
|
|
```
|
|
|
|
The repository is public, so the server fetches over HTTPS without credentials.
|
|
Gitea's SSH transport disconnected during transfer, so this checkout also pushes
|
|
over HTTPS. Its repository-local credential helper reads the existing `ayau` Tea
|
|
login only for this exact HTTPS host/repository; it stores no additional token copy.
|
|
The personal Mac SSH key and Tea token are not copied to the server. If the repository
|
|
becomes private, provision repository-scoped read credentials before the change.
|
|
|
|
The pipeline fetches into a bare repository and archives an exact commit into
|
|
`/opt/minabot/releases/<sha>`. It builds a test image, runs typecheck and the full
|
|
test suite, builds the runtime image, runs a disposable production smoke test,
|
|
and validates Compose/Caddy. Secrets and production SQLite stay on the server;
|
|
they are never synced from Git or development during a release.
|
|
|
|
After checks pass, Caddy and the old app stop briefly, a verified database snapshot
|
|
is taken, and the new app starts before Caddy reopens public access. Discord workers
|
|
never overlap. A lock prevents concurrent manual/timer deployments. Successful
|
|
commits are recorded in `/opt/minabot/deployed-sha` and skipped on later checks.
|
|
|
|
A build/test failure leaves the old service running. Failed revisions are recorded
|
|
in `failed-sha` and skipped until a new commit or an explicit retry. On startup
|
|
failure, the old configuration/image is restored only if the schema and migration
|
|
fingerprint is unchanged. Otherwise services remain stopped for operator recovery;
|
|
the script never overwrites the production database with an old snapshot.
|
|
Changes to `.env.production` or Caddy's pinned image remain explicit server operations.
|
|
|
|
## Server operations
|
|
|
|
```sh
|
|
# Check status and recent deployment output
|
|
systemctl status minabot-deploy.timer minabot-deploy.service
|
|
journalctl -u minabot-deploy.service -n 100 --no-pager
|
|
cat /opt/minabot/deployed-sha
|
|
|
|
# Run a check now / retry a previously failed revision
|
|
sudo systemctl start minabot-deploy.service
|
|
/usr/local/bin/minabot-deploy --retry
|
|
|
|
# Pause / resume automatic deployment
|
|
sudo systemctl stop minabot-deploy.timer
|
|
sudo systemctl start minabot-deploy.timer
|
|
```
|
|
|
|
Build/test logs are inside each release directory. Retained release images and
|
|
Docker build cache need occasional housekeeping; the script refuses a build when
|
|
less than 2 GiB is free. Keep the current and previous known-good image and backups.
|
|
Failures are logged locally; external alerts are not configured.
|
|
|
|
To install or update the controller from a reviewed checkout on the server:
|
|
|
|
```sh
|
|
sudo systemctl stop minabot-deploy.timer
|
|
# Let any running deployment finish before replacing its controller.
|
|
sudo systemctl start minabot-deploy.service
|
|
sudo install -m 755 deploy/deploy.sh /usr/local/bin/minabot-deploy
|
|
sudo install -m 644 deploy/minabot-deploy.service deploy/minabot-deploy.timer /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now minabot-deploy.timer
|
|
```
|
|
|
|
Controller/service changes require this explicit installation; normal app,
|
|
Dockerfile, Compose, and Caddyfile changes deploy automatically. Do not force-reset
|
|
`main` to roll back: prefer a revert commit so the pipeline tests the result.
|
|
|
|
For first-time installation, omit the first two commands if the units do not exist.
|
|
|
|
`bun test deploy/deploy.test.ts` verifies success, idempotency, failure before
|
|
cutover, safe rollback, and refusal to replace data after a schema change using
|
|
isolated fake Git/Docker commands. It never contacts production.
|