Two supported deploy paths: a long-running host with PM2 (the default CD target), or Docker Compose. Both run from source — Bun executes TypeScript directly, there is no build step.
- CI (
.github/workflows/ci.yml) runs on every push and pull request: lint, typecheck, tests, Prisma migration apply + drift check, Docker build, dependency audit, andactionlint. - CD (
.github/workflows/cd.yml) is triggered by a successful CI run onmain/master(workflow_runtrigger gated onconclusion == 'success'). It SSHes into the production host and invokesscripts/deploy.sh.
The CD workflow connects via appleboy/ssh-action and runs:
cd Projects/azalea
git pull origin main
bash scripts/deploy.shscripts/deploy.sh handles the rest:
bun install --frozen-lockfile --production— production dependencies only.- Backup the SQLite database to
prisma/backups/azalea.db.<UTC-timestamp>.gz(gzipped). The 3 most recent backups are retained. bun run db:migrate— apply pending Prisma migrations.pm2 reload ecosystem.config.js— graceful reload.
Configure these in the GitHub repo settings:
| Secret | Description |
|---|---|
SSH_HOST |
Production host (DNS name or IP). |
SSH_USER |
Username for the SSH connection. |
SSH_KEY |
Private key authorized on the host. |
bun(matching the version inpackage.json).pm2with anecosystem.config.jsone directory above the repo (cd ..fromProjects/azalea).- A working tree at
~/Projects/azaleawhose.envhasDATABASE_URLandDISCORD_TOKEN.SENTRY_DSNis optional — leave it unset to disable error reporting.
The deploy script is just bash — you can run it locally on the host to reproduce or roll back. To restore from a backup:
gunzip -c prisma/backups/azalea.db.<timestamp>.gz > prisma/azalea.db
pm2 reload ecosystem.config.jsdocker compose up -d --buildThe compose file:
- Builds the Bun-based image defined in
Dockerfile. - Reads secrets from
.envviaenv_file. - Mounts a named volume
dataat/usr/src/app/dataso the SQLite database persists across rebuilds. The migrations and schema live in the image, not the volume — schema updates apply on the nextup. - Runs
bunx prisma migrate deploy && bun startas the entrypoint, so migrations are applied at container start.
docker compose pull # if you push images to a registry
docker compose up -d --buildTo wipe the database and start fresh:
docker compose down -v # `-v` removes the named volume
docker compose up -d --buildDATABASE_URL defaults to file:data/azalea.db (matches the Docker volume layout). Existing PM2 deploys may still use file:prisma/azalea.db; both work — the only constraint is that whatever path you pick must be writable by the runtime user.
If you migrate an existing PM2 deploy to the new data/ layout:
mkdir -p data
mv prisma/azalea.db data/azalea.db
# update .env: DATABASE_URL="file:data/azalea.db"
# update scripts/deploy.sh's backup path to match