Retarget deploy pipeline to POS and guard against cross-service clobber
Deploy Ladill POS / deploy (push) Successful in 24s
Deploy Ladill POS / deploy (push) Successful in 24s
The pipeline was copied from Ladill Mini and still deployed into /var/www/ladill-mini, so the first POS push overwrote mini.ladill.com. Retarget every mini reference to pos (app root, archive/workspace names, concurrency group, nginx subdomain, supervisor worker), add a guard step that fails the run unless basename(LADILL_APP_ROOT) matches the repo name, and document the incident + a forking checklist in DEPLOY.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e5d2b84388
commit
57862acb47
@@ -1,4 +1,4 @@
|
||||
name: Deploy Ladill Mini
|
||||
name: Deploy Ladill POS
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -10,7 +10,7 @@ permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: deploy-mini
|
||||
group: deploy-pos
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -19,10 +19,27 @@ jobs:
|
||||
env:
|
||||
NODE_ROOT: /tmp/ladill-node-22-r1
|
||||
NODE_VERSION: "22.14.0"
|
||||
RELEASE_ARCHIVE: /tmp/ladill-mini-release-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tgz
|
||||
WORKSPACE: /tmp/${{ gitea.repository_owner }}-mini-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||
LADILL_APP_ROOT: /var/www/ladill-mini
|
||||
RELEASE_ARCHIVE: /tmp/ladill-pos-release-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tgz
|
||||
WORKSPACE: /tmp/${{ gitea.repository_owner }}-pos-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||
LADILL_APP_ROOT: /var/www/ladill-pos
|
||||
steps:
|
||||
- name: Guard deploy target
|
||||
# Refuse to deploy if this workflow was copied from another service
|
||||
# without retargeting LADILL_APP_ROOT. The app dir basename MUST match
|
||||
# the repo name (ladill-pos -> /var/www/ladill-pos), otherwise a copied
|
||||
# pipeline would clobber a sibling service. See DEPLOY.md "Forking this pipeline".
|
||||
shell: bash {0}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
REPO_NAME="${{ gitea.repository }}"; REPO_NAME="${REPO_NAME##*/}"
|
||||
APP_DIR_NAME="$(basename "$LADILL_APP_ROOT")"
|
||||
if [ "$REPO_NAME" != "$APP_DIR_NAME" ]; then
|
||||
echo "FATAL: repo '$REPO_NAME' != deploy target '$APP_DIR_NAME' (LADILL_APP_ROOT=$LADILL_APP_ROOT)." >&2
|
||||
echo "Refusing to deploy — a mis-targeted workflow would overwrite another service. Retarget deploy.yml env." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Guard OK: $REPO_NAME -> $LADILL_APP_ROOT"
|
||||
|
||||
- name: Checkout
|
||||
shell: bash {0}
|
||||
run: |
|
||||
@@ -78,7 +95,7 @@ jobs:
|
||||
- name: Deploy release
|
||||
shell: bash {0}
|
||||
env:
|
||||
LADILL_RELEASE_ARCHIVE: /tmp/ladill-mini-release-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tgz
|
||||
LADILL_RELEASE_ARCHIVE: /tmp/ladill-pos-release-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tgz
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
: "${LADILL_APP_ROOT:?Set LADILL_APP_ROOT}"
|
||||
@@ -93,11 +110,11 @@ jobs:
|
||||
NGINX_SCRIPT="/var/www/ladill.com/current/deployment/setup-service-subdomain-nginx.sh"
|
||||
fi
|
||||
if [ ! -f "$NGINX_SCRIPT" ]; then
|
||||
echo "WARN: setup-service-subdomain-nginx.sh not found — configure mini.ladill.com vhost manually"
|
||||
echo "WARN: setup-service-subdomain-nginx.sh not found — configure pos.ladill.com vhost manually"
|
||||
exit 0
|
||||
fi
|
||||
if sudo -n bash "$NGINX_SCRIPT" mini --app /var/www/ladill-mini/current; then
|
||||
echo "nginx vhost updated for mini.ladill.com"
|
||||
if sudo -n bash "$NGINX_SCRIPT" pos --app /var/www/ladill-pos/current; then
|
||||
echo "nginx vhost updated for pos.ladill.com"
|
||||
else
|
||||
echo "WARN: nginx vhost step skipped (deploy user cannot sudo) — vhost must already be provisioned"
|
||||
fi
|
||||
|
||||
@@ -12,7 +12,42 @@ Standalone **in-store register** at `pos.ladill.com`. Charges via Ladill Pay (`s
|
||||
|
||||
## Deploy
|
||||
|
||||
Same release model as Mini/Merchant — see `deploy/deploy.sh`.
|
||||
Same release model as Mini/Merchant — see `deploy/deploy.sh`. Pushing to `main`
|
||||
triggers `.gitea/workflows/deploy.yml` on the host `deploy` runner, which builds a
|
||||
release and deploys into `/var/www/ladill-pos`.
|
||||
|
||||
## ⚠️ Forking this pipeline (read before copying to a new service)
|
||||
|
||||
This workflow was bootstrapped by copying Mini's. **If you copy `.gitea/workflows/deploy.yml`,
|
||||
`deploy/deploy.sh`, or `DEPLOY.md` to a new service, retarget EVERY `mini`/`pos` reference**,
|
||||
or the new repo's pipeline will deploy its code on top of the service you copied from.
|
||||
|
||||
Things that must match the new service (search for the old slug and replace all):
|
||||
|
||||
- `deploy.yml`: `name:`, `concurrency.group`, `RELEASE_ARCHIVE`, `WORKSPACE`,
|
||||
`LADILL_APP_ROOT`, the nginx step subdomain (`pos --app /var/www/ladill-pos/current`)
|
||||
- `deploy.sh`: `APP_ROOT` default and the `supervisorctl restart <service>-worker:*` name
|
||||
|
||||
A **guard step** in `deploy.yml` enforces `basename(LADILL_APP_ROOT) == <repo name>` and
|
||||
fails the run on a mismatch — keep repo name and app dir name identical (`ladill-pos` →
|
||||
`/var/www/ladill-pos`).
|
||||
|
||||
> **Incident 2026-06-24:** the initial POS pipeline still pointed at `/var/www/ladill-mini`,
|
||||
> so the first POS push overwrote mini.ladill.com (POS code + a stray `create_pos_tables`
|
||||
> migration against the `ladill_mini` DB). Remediated by repointing mini's `current` symlink
|
||||
> to the last genuine Mini release and dropping the 4 stray `pos_*` tables. The guard step
|
||||
> above exists to make this impossible to repeat.
|
||||
|
||||
## Server prerequisites (one-time, as root)
|
||||
|
||||
Done for `pos.ladill.com`; replicate for any new service:
|
||||
|
||||
1. MySQL: `CREATE DATABASE ladill_pos` + user `ladill_pos@127.0.0.1` (`ALL` on its own db;
|
||||
`SELECT` on `ladill_merchant` + `ladilldb` for commerce links)
|
||||
2. `/var/www/ladill-pos/{releases,shared}` owned `deploy:www-data`
|
||||
3. `shared/.env` (mode 640, `deploy:www-data`) with generated `APP_KEY`, DB creds, and the
|
||||
integration keys from the monolith (see "Platform wiring")
|
||||
4. nginx vhost via `deployment/setup-service-subdomain-nginx.sh pos --app /var/www/ladill-pos/current`
|
||||
|
||||
```bash
|
||||
php artisan migrate --force
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
# Fast on-host release deploy (same model as climpme/web/deploy/deploy.sh).
|
||||
set -Eeuo pipefail
|
||||
|
||||
APP_ROOT="${LADILL_APP_ROOT:-/var/www/ladill-mini}"
|
||||
APP_ROOT="${LADILL_APP_ROOT:-/var/www/ladill-pos}"
|
||||
RELEASES_DIR="$APP_ROOT/releases"
|
||||
SHARED_DIR="$APP_ROOT/shared"
|
||||
CURRENT_LINK="$APP_ROOT/current"
|
||||
@@ -236,7 +236,7 @@ if [ -L "$CURRENT_LINK" ] && [ -f "$CURRENT_LINK/artisan" ]; then
|
||||
(cd "$CURRENT_LINK" && php artisan queue:restart) || true
|
||||
fi
|
||||
if command -v supervisorctl >/dev/null 2>&1; then
|
||||
supervisorctl restart ladill-mini-worker:* 2>/dev/null || true
|
||||
supervisorctl restart ladill-pos-worker:* 2>/dev/null || true
|
||||
fi
|
||||
|
||||
log "Cleaning old releases"
|
||||
|
||||
Reference in New Issue
Block a user