diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..30702fc --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,58 @@ +name: Deploy to LXC + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Deploy via SSH + uses: appleboy/ssh-action@v1 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + key: ${{ secrets.DEPLOY_KEY }} + port: ${{ secrets.DEPLOY_PORT || 22 }} + script: | + set -e + + APP_DIR="${{ secrets.DEPLOY_PATH || '/opt/buildfor_life_ops/app' }}" + REPO_URL="https://git.b4l.co.th/B4L/buildfor_life_ops.git" + + # Clone if first deploy, otherwise pull. Public HTTPS — no deploy key needed. + if [ ! -d "$APP_DIR" ]; then + echo "==> First deploy, cloning..." + git clone "$REPO_URL" "$APP_DIR" + cd "$APP_DIR" + else + cd "$APP_DIR" + echo "==> Resetting local changes..." + git checkout -- . + echo "==> Pulling latest code..." + git pull origin main + fi + + # Activate the pinned Node via fnm and make pnpm available via Corepack. + # Both are expected to be installed per DEPLOYMENT.md. + export PATH="$HOME/.local/share/fnm:$PATH" + eval "$(fnm env --shell bash)" + fnm use --install-if-missing + corepack enable >/dev/null 2>&1 || true + + echo "==> Installing dependencies..." + pnpm install --frozen-lockfile + + echo "==> Building..." + pnpm run build + + echo "==> Running migrations..." + pnpm run db:migrate + + echo "==> Restarting service..." + sudo systemctl restart buildfor_life_ops + + echo "==> Waiting for startup..." + sleep 2 + systemctl is-active --quiet buildfor_life_ops && echo "Deploy successful!" || (echo "Service failed to start!" && exit 1) diff --git a/.gitea/workflows/validate.yml b/.gitea/workflows/validate.yml new file mode 100644 index 0000000..0a9d5ae --- /dev/null +++ b/.gitea/workflows/validate.yml @@ -0,0 +1,31 @@ +name: Validate + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run validation (svelte-check + build) + run: pnpm run validate diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..0a9d5ae --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,31 @@ +name: Validate + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run validation (svelte-check + build) + run: pnpm run validate diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index aa6a476..c54568b 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -236,6 +236,22 @@ Environment=HOST_HEADER=x-forwarded-host ## 12. Upgrades +### Automated (CI-driven) + +`.gitea/workflows/deploy.yml` runs on every push to `main`. It SSHes into the LXC host, pulls, installs, builds, migrates, and restarts the service. Required Gitea secrets: + +| Secret | Purpose | +| --- | --- | +| `DEPLOY_HOST` | SSH host of the LXC container | +| `DEPLOY_USER` | SSH user (must own `$DEPLOY_PATH` and have a sudoers entry for `systemctl restart buildfor_life_ops`) | +| `DEPLOY_KEY` | Private SSH key matching an authorized key on the deploy user | +| `DEPLOY_PORT` | *(optional, default `22`)* | +| `DEPLOY_PATH` | *(optional, default `/opt/buildfor_life_ops/app`)* | + +The repo itself is cloned from `https://git.b4l.co.th/B4L/buildfor_life_ops.git` (public HTTPS) — no repo deploy key needed, unlike the budget sibling. + +### Manual + ```bash cd /opt/buildfor_life_ops/app git fetch --tags @@ -245,15 +261,15 @@ git checkout fnm use --install-if-missing pnpm install --frozen-lockfile -pnpm run db:migrate pnpm run build +pnpm run db:migrate pnpm install --prod --frozen-lockfile systemctl restart buildfor_life_ops journalctl -u buildfor_life_ops -n 100 --no-pager ``` -A migration that cannot be rolled back forward-only (rare — see `drizzle/README.md`) needs a maintenance window and a DB snapshot first. +A migration that cannot be rolled forward-only (rare — see `drizzle/README.md`) needs a maintenance window and a DB snapshot first. ## 13. Rollback