pelagia-portal/.forgejo/workflows/deploy.yml
Hardik 6b0210078a
All checks were successful
PR checks / checks (pull_request) Successful in 42s
PR checks / integration (pull_request) Successful in 31s
chore(deploy): build & (re)start microservices on release tag
The v* tag deploy previously only updated the Next app (ppms); GstService /
EpfoService / PdfService were never built or restarted by automation. Now the
same deploy manages them.

- ecosystem.config.js (root): pm2 definitions for gst-service (3003) /
  epfo-service (3004) / pdf-service (3005). Registers only services whose source
  is checked out (keyed on package.json), so a not-yet-merged service is skipped
  and adopted automatically once its PR lands. Secrets come from the env at pm2
  invocation; ports are fixed here.
- deploy.yml: after the app restart, export the few service secrets out of
  App/.env (never PORT or the ephemeral FORGEJO_TOKEN), npm install + playwright
  install chromium + build each present service, then
  `pm2 startOrReload ecosystem.config.js --update-env` (create on first release,
  reload after) + pm2 save, and health-check :3003/:3004/:3005.
- automation/README.md: documents the flow + the one-time alignment for any
  pre-existing differently-named pm2 process.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 02:59:36 +05:30

98 lines
3.8 KiB
YAML

name: Deploy release to production
# Pushing a release tag (vX.Y.Z) deploys that tag to the portal at
# pms.pelagiamarine.com. Runs on the pms1 host runner (label: host),
# which executes as shad0w with direct access to the pm2-managed app.
on:
push:
tags:
- "v*"
jobs:
deploy:
runs-on: host
steps:
- name: Deploy tag to ~/pms and restart ppms
run: |
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
. "$NVM_DIR/nvm.sh"
TAG="${GITHUB_REF_NAME}"
echo "=== Deploying $TAG ==="
cd "$HOME/pms"
git fetch origin --tags --force
git checkout -f "refs/tags/$TAG"
cd App
pnpm install --frozen-lockfile
pnpm build # includes prisma generate
pnpm db:migrate:deploy
# NOT --update-env: this job runs inside the Forgejo Actions runner, whose
# environment includes an ephemeral FORGEJO_TOKEN (the per-job token, revoked
# when the job ends). --update-env would inject it into ppms, where it shadows
# the real PAT from .env (Next.js does not override an already-set process.env
# var) and breaks the Report Issue button once the job token expires. A plain
# restart re-execs ppms from the pm2 daemon's clean env, so .env wins.
pm2 restart ppms
echo "=== Deployed $TAG ==="
- name: Build & (re)start microservices
run: |
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
. "$NVM_DIR/nvm.sh"
cd "$HOME/pms"
# Pull only the few keys the services need out of the app's .env (the
# single source of truth on the host). Never import PORT (each service's
# port is fixed in ecosystem.config.js) or the runner's ephemeral
# FORGEJO_TOKEN. Missing keys → empty, which the services tolerate.
envget() { grep -E "^$1=" App/.env 2>/dev/null | head -1 | sed -E 's/^[^=]+=//; s/^"//; s/"$//'; }
export PDF_SERVICE_TOKEN="$(envget PDF_SERVICE_TOKEN)"
export ALLOWED_ORIGIN="$(envget ALLOWED_ORIGIN)"
export EPFO_LIVE="$(envget EPFO_LIVE)"
# Build each present service (skip any not yet in the tree, e.g. before
# its feature PR has merged). npm install (not ci) — not every service
# carries a lockfile. Playwright's postinstall fetches the browser; the
# explicit install is a cached, idempotent backstop.
for svc in GstService EpfoService PdfService; do
[ -f "$svc/package.json" ] || { echo "skip $svc (absent)"; continue; }
echo "=== Building $svc ==="
( cd "$svc" && npm install --no-audit --no-fund && npx playwright install chromium && npm run build )
done
# Create on first release, zero-downtime reload thereafter. The
# ecosystem registers only services whose dirs exist.
pm2 startOrReload ecosystem.config.js --update-env
pm2 save
pm2 list
echo "=== Microservices up ==="
- name: Verify services respond
run: |
sleep 3
cd "$HOME/pms"
check() {
local dir="$1" port="$2"
[ -f "$dir/package.json" ] || { echo "skip $dir (absent)"; return 0; }
local code
code=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$port/health" || echo "000")
echo "$dir on :$port /health → HTTP $code"
test "$code" = "200"
}
check GstService 3003
check EpfoService 3004
check PdfService 3005
- name: Verify portal responds
run: |
sleep 5
code=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/login)
echo "Portal /login returned HTTP $code"
test "$code" = "200"