.github/workflows/ci.yml — on push/PR:
- backend job: dotnet restore/build/test with a live postgres service
- web job: pnpm install + vite build + tsc, uploads dist artifact
- pos job: windows-latest, dotnet publish self-contained win-x64
single-file exe as artifact
.github/workflows/docker.yml — on push to main (if src changed) or manual:
- api image → ghcr.io/nurdotnet/food-market-api:{latest,sha}
- web image → ghcr.io/nurdotnet/food-market-web:{latest,sha}
- uses buildx + GHA cache
deploy/Dockerfile.api — multi-stage (.NET 8 sdk → aspnet runtime),
healthcheck on /health, App_Data + logs volumes mounted.
deploy/Dockerfile.web — node20 build → nginx 1.27 runtime; ships the
Vite dist + nginx.conf that proxies /api, /connect, /health to api
service and serves the SPA with fallback to index.html.
deploy/nginx.conf — SPA + API reverse-proxy configuration.
deploy/docker-compose.yml — production-shape stack: postgres 16 +
api (from ghcr image) + web (from ghcr image), named volumes, env-
driven tags so stage/prod can pin specific SHAs.
deploy/backup.sh — pg_dump wrapper with 3 modes: local (brew
postgres), --docker (compose container), --remote HOST:PORT. Writes
gzipped dumps to ~/food-market-backups, 30-day retention.
docs/24x7.md — explains where Claude/CI/stage live, which pieces
depend on the Mac, and the exact steps to hand off secrets via
~/.food-market-secrets/ so I can push them into GitHub Secrets.
Next, once user supplies Proxmox + FTP + Telegram creds: stage deploy
workflow, notification workflow, and (optional) claude-runner VM so
I no longer depend on the Mac being awake.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1.3 KiB
Bash
Executable file
42 lines
1.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Dumps the food-market Postgres DB to a timestamped gzipped file.
|
|
# Usage:
|
|
# deploy/backup.sh — local dev DB (postgres@14 via Unix socket)
|
|
# deploy/backup.sh --remote HOST:PORT — over network
|
|
# deploy/backup.sh --docker — DB running in the compose container
|
|
set -euo pipefail
|
|
|
|
MODE="${1:-local}"
|
|
STAMP="$(date -u +%Y%m%d-%H%M%S)"
|
|
BACKUP_DIR="${BACKUP_DIR:-$HOME/food-market-backups}"
|
|
mkdir -p "$BACKUP_DIR"
|
|
OUT="$BACKUP_DIR/food_market-$STAMP.sql.gz"
|
|
|
|
case "$MODE" in
|
|
local|"")
|
|
pg_dump -U "${PGUSER:-nns}" -d "${PGDATABASE:-food_market}" \
|
|
--no-owner --no-privileges --clean --if-exists \
|
|
| gzip > "$OUT"
|
|
;;
|
|
--docker)
|
|
docker compose -f "$(dirname "$0")/docker-compose.yml" exec -T postgres \
|
|
pg_dump -U food_market -d food_market --no-owner --no-privileges --clean --if-exists \
|
|
| gzip > "$OUT"
|
|
;;
|
|
--remote)
|
|
HOST="$2"
|
|
pg_dump -h "${HOST%:*}" -p "${HOST#*:}" -U "${PGUSER:-food_market}" -d food_market \
|
|
--no-owner --no-privileges --clean --if-exists \
|
|
| gzip > "$OUT"
|
|
;;
|
|
*)
|
|
echo "usage: $0 [local|--docker|--remote HOST:PORT]" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
echo "Wrote $OUT ($(du -h "$OUT" | cut -f1))"
|
|
|
|
# Retain last 30 days
|
|
find "$BACKUP_DIR" -name 'food_market-*.sql.gz' -mtime +30 -delete 2>/dev/null || true
|