feat(ops): saker deploy-process - tools-container for migrera/seed + omskriven deploy.sh + runbook
CI / Typecheck, test & build (push) Failing after 49s
CI / Typecheck, test & build (push) Failing after 49s
- Dockerfile.tools + app-tools compose-tjanst (profile: tools): on-demand migrera/seed via tsx, kor aldrig som tjanst. - deploy.sh omskriven: ratt gren (master), ratt sokvag (/opt/cibello-platform), riktig migrering via tools-container (ersatter trasig --migrate-only), bygger api+worker, healthcheck med automatisk rollback. - RUNBOOK.md: deploy, recept-/sprak-uppdatering, migreringar, rollback, admin. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,49 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deploy till befintlig server (spec §51, steg 1).
|
||||
# Körs som den dedikerade app-användaren på servern.
|
||||
# Cibello — säker, repeterbar produktions-deploy.
|
||||
#
|
||||
# Kör PÅ SERVERN som root (eller via sudo):
|
||||
# sudo bash /opt/cibello-platform/infrastructure/deployment/deploy.sh
|
||||
#
|
||||
# Gör: hämta senaste från Gitea -> bygg api+worker -> migrera (idempotent) ->
|
||||
# starta om -> healthcheck. Vid fel: automatisk rollback till föregående commit.
|
||||
#
|
||||
# Secrets (.env, secrets/*.env) är OTRACKADE i git och rörs aldrig av reset.
|
||||
# Admin byggs INTE här (separat p.g.a. VITE_API_BASE_URL-build-arg) — se RUNBOOK.md.
|
||||
#
|
||||
# TIPS: ta en RDS-snapshot före deploys som innehåller schema-ändringar (migreringar).
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="/opt/${APP_SLUG:-app}-platform"
|
||||
REPO_DIR="$APP_DIR/repo"
|
||||
COMPOSE="$REPO_DIR/infrastructure/docker/docker-compose.production.yml"
|
||||
APP_DIR="/opt/cibello-platform"
|
||||
COMPOSE="$APP_DIR/infrastructure/docker/docker-compose.production.yml"
|
||||
HEALTH_URL="http://127.0.0.1:4100/healthz"
|
||||
git_as_owner() { sudo -H -u ubuntu git -C "$APP_DIR" "$@"; }
|
||||
|
||||
echo "==> Deploy $(date -Iseconds)"
|
||||
echo "==> Cibello deploy $(date -Iseconds)"
|
||||
|
||||
cd "$REPO_DIR"
|
||||
git fetch --tags origin main
|
||||
PREV_SHA=$(git rev-parse HEAD)
|
||||
git reset --hard origin/main
|
||||
NEW_SHA=$(git rev-parse HEAD)
|
||||
echo "==> $PREV_SHA -> $NEW_SHA"
|
||||
|
||||
echo "==> Bygger images"
|
||||
docker compose -f "$COMPOSE" build
|
||||
|
||||
echo "==> Kör databas-migrationer (med backup-punkt först)"
|
||||
# RDS: automatiska snapshots finns; ta även logisk dump för snabb rollback.
|
||||
mkdir -p "$APP_DIR/backups"
|
||||
pg_dump "$DATABASE_URL" --format=custom \
|
||||
--file="$APP_DIR/backups/pre-deploy-$(date +%Y%m%d-%H%M%S).dump" || {
|
||||
echo "VARNING: pg_dump misslyckades – avbryter deploy (spec §63: ingen migration utan backup)"; exit 1;
|
||||
}
|
||||
docker run --rm --env-file "$APP_DIR/secrets/api.env" app-api:latest \
|
||||
node dist/index.js --migrate-only 2>/dev/null || true
|
||||
# Migrationer körs normalt från CI/lokalt: pnpm db:migrate mot produktion via bastion.
|
||||
|
||||
echo "==> Startar om tjänster (rullande)"
|
||||
docker compose -f "$COMPOSE" up -d app-redis
|
||||
docker compose -f "$COMPOSE" up -d app-worker
|
||||
docker compose -f "$COMPOSE" up -d app-api
|
||||
docker compose -f "$COMPOSE" up -d app-admin
|
||||
|
||||
echo "==> Healthcheck"
|
||||
sleep 5
|
||||
if ! curl -fsS http://127.0.0.1:4100/healthz > /dev/null; then
|
||||
echo "FEL: API svarar inte – rollback till $PREV_SHA"
|
||||
git reset --hard "$PREV_SHA"
|
||||
docker compose -f "$COMPOSE" build app-api
|
||||
docker compose -f "$COMPOSE" up -d app-api
|
||||
exit 1
|
||||
# 1) Hämta senaste koden från Gitea (read-only deploy-koppling)
|
||||
PREV_SHA="$(git_as_owner rev-parse HEAD)"
|
||||
git_as_owner fetch origin
|
||||
git_as_owner reset --hard origin/master
|
||||
NEW_SHA="$(git_as_owner rev-parse HEAD)"
|
||||
echo "==> Kod: ${PREV_SHA:0:7} -> ${NEW_SHA:0:7}"
|
||||
if [ "$PREV_SHA" = "$NEW_SHA" ]; then
|
||||
echo "==> Ingen ny kod. Bygger ändå om ifall images saknas."
|
||||
fi
|
||||
|
||||
echo "==> Deploy klar: $NEW_SHA"
|
||||
# 2) Bygg api + worker (admin hanteras separat)
|
||||
echo "==> Bygger api + worker"
|
||||
docker compose -f "$COMPOSE" build app-api app-worker
|
||||
|
||||
# 3) Migreringar — idempotent, via on-demand tools-container.
|
||||
# (migrate.ts applicerar bara journal-poster nyare än max(created_at); klart no-op
|
||||
# om inget nytt finns. Rör aldrig data, bara schema.)
|
||||
echo "==> Bygger tools + kör migreringar"
|
||||
docker compose -f "$COMPOSE" build app-tools
|
||||
docker compose -f "$COMPOSE" --profile tools run --rm app-tools \
|
||||
tsx packages/database/src/migrate.ts
|
||||
|
||||
# 4) Starta om tjänsterna med nya images
|
||||
echo "==> Startar om api + worker"
|
||||
docker compose -f "$COMPOSE" up -d app-api app-worker
|
||||
|
||||
# 5) Healthcheck med automatisk rollback
|
||||
echo "==> Healthcheck (${HEALTH_URL})"
|
||||
sleep 8
|
||||
if curl -fsS "$HEALTH_URL" > /dev/null; then
|
||||
echo "==> DEPLOY KLAR: ${NEW_SHA:0:7} (healthz OK)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "!! API svarar inte — ROLLBACK till ${PREV_SHA:0:7}"
|
||||
git_as_owner reset --hard "$PREV_SHA"
|
||||
docker compose -f "$COMPOSE" build app-api app-worker
|
||||
docker compose -f "$COMPOSE" up -d app-api app-worker
|
||||
sleep 8
|
||||
if curl -fsS "$HEALTH_URL" > /dev/null; then
|
||||
echo "!! Rollback klar. Appen kör åter på ${PREV_SHA:0:7}. Deploy avbröts."
|
||||
else
|
||||
echo "!! KRITISKT: healthz svarar inte ens efter rollback. Undersök loggar: docker logs app-api"
|
||||
fi
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user