feat(deploy): auto-seed a known Payload admin user on every deploy
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Canceled after 0s
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Canceled after 0s
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Canceled after 0s
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Canceled after 0s
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Canceled after 0s
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Canceled after 0s
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Canceled after 0s
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Canceled after 0s
Follow-up to MITHOME-97: after every deploy, a brand-new database (first-ever deploy, or a volume wipe) leaves the Payload admin behind the "Create first user" screen — someone has to notice and fill it in by hand, which means environments can silently end up with no known admin credentials, or with whatever a random person happened to type in at the time. deploy.sh now calls Payload's built-in `POST /api/users/first-register` REST endpoint right after the healthcheck passes, using ADMIN_EMAIL / ADMIN_PASSWORD from the environment's .env file. That endpoint only succeeds when the `users` collection is completely empty (throws 403 Forbidden otherwise) — which makes this naturally idempotent: the first deploy against a fresh database creates the known admin, every later deploy gets a harmless 403 and skips it. It never overwrites an existing user's password. Missing ADMIN_EMAIL/ADMIN_PASSWORD in the env file just skips the step with a warning, it doesn't fail the deploy. Documented the new variables in .env.staging.example and .env.production.example (next to the existing PAYLOAD_SECRET instructions), and the new deploy.sh step 4 in .agent/workflows/deploy.md. Also dropped a stale "Content Editor is staging feliratot kap" line from the same doc (that behavior belonged to the CMS retired in MITHOME-93 and no longer exists). Verified locally against real Payload instances (not just reading the code): a fresh, empty MongoDB returns 200 and creates the user; a second call against the same now-non-empty database returns 403 and changes nothing; a database that already had a different user (the existing dev DB) also correctly returns 403. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
94647d5293
commit
729268a3fe
@@ -9,7 +9,7 @@ description: Deployment munkafolyamata — lokális teszttől a stagingen át a
|
|||||||
- **Nincs Dokploy / registry push** — a deploy natív Docker Compose-zal, a szerveren buildelve történik.
|
- **Nincs Dokploy / registry push** — a deploy natív Docker Compose-zal, a szerveren buildelve történik.
|
||||||
- **Környezetenként külön compose fájl**: `docker-compose.staging.yml` (app: 127.0.0.1:8081, saját Mongo) és `docker-compose.prod.yml` (app: 8080). A két környezet ugyanazon a hoston, külön hálózaton és volume-mal fut.
|
- **Környezetenként külön compose fájl**: `docker-compose.staging.yml` (app: 127.0.0.1:8081, saját Mongo) és `docker-compose.prod.yml` (app: 8080). A két környezet ugyanazon a hoston, külön hálózaton és volume-mal fut.
|
||||||
- **Környezeti változók**: kötelező `.env.staging` / `.env.production` fájlból jönnek (minta: `.env.staging.example`, `.env.production.example`). Bizalmas értékeknek (MONGO_ROOT_PASSWORD, MONGODB_URI) **nincs fallback** — hiányzó env hangosan hibázik.
|
- **Környezeti változók**: kötelező `.env.staging` / `.env.production` fájlból jönnek (minta: `.env.staging.example`, `.env.production.example`). Bizalmas értékeknek (MONGO_ROOT_PASSWORD, MONGODB_URI) **nincs fallback** — hiányzó env hangosan hibázik.
|
||||||
- **Staging megkülönböztetés**: a `NEXT_PUBLIC_DEPLOY_ENV=staging` build arg amber banner-t jelenít meg a weboldalon; a Content Editor is staging feliratot kap.
|
- **Staging megkülönböztetés**: a `NEXT_PUBLIC_DEPLOY_ENV=staging` build arg amber banner-t jelenít meg a weboldalon.
|
||||||
|
|
||||||
## Előfeltételek
|
## Előfeltételek
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ Bármely lépés hibája azonnal leállítja a folyamatot. Paraméterek környez
|
|||||||
1. Kötelező `.env.<env>` fájl betöltése (`--env-file` a compose-nak).
|
1. Kötelező `.env.<env>` fájl betöltése (`--env-file` a compose-nak).
|
||||||
2. `docker compose -f docker-compose.<env>.yml up --build --force-recreate -d` — a friss Dockerfile/build-arg változások is érvényesüljenek.
|
2. `docker compose -f docker-compose.<env>.yml up --build --force-recreate -d` — a friss Dockerfile/build-arg változások is érvényesüljenek.
|
||||||
3. Healthcheck: max 60s-ig kérdezi a `http://localhost:<port>/api/health`-t (staging: 8081, prod: 8080). Sikertelenség esetén app-logok kiírása + exit 1.
|
3. Healthcheck: max 60s-ig kérdezi a `http://localhost:<port>/api/health`-t (staging: 8081, prod: 8080). Sikertelenség esetén app-logok kiírása + exit 1.
|
||||||
|
4. **Payload admin-seedelés** (MITHOME-97): healthcheck után meghívja a Payload beépített `POST /api/users/first-register` endpointját az `.env.<env>`-ben megadott `ADMIN_EMAIL`/`ADMIN_PASSWORD`-del. Ez az endpoint csakis akkor enged létrehozni felhasználót, ha a `users` collection teljesen üres — ezért idempotens: egy vadonatúj adatbázisnál (első deploy, vagy volume-törlés utáni újrakezdés) automatikusan létrehozza az ismert admin fiókot, minden további deployon pedig 403-at kap és ártalmatlanul kihagyja (a jelszót utólag sosem írja felül). Ha az `ADMIN_EMAIL`/`ADMIN_PASSWORD` hiányzik az env fájlból, ezt a lépést egyszerűen kihagyja (figyelmeztetéssel, nem hibával) — ilyenkor az első felhasználót manuálisan kell létrehozni `/admin` alatt.
|
||||||
|
|
||||||
## Tartalom publikálása (Payload admin)
|
## Tartalom publikálása (Payload admin)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ MONGO_ROOT_PASSWORD=changeme
|
|||||||
# environmenttel.
|
# environmenttel.
|
||||||
PAYLOAD_SECRET=changeme
|
PAYLOAD_SECRET=changeme
|
||||||
|
|
||||||
|
# Payload admin — ismert, biztosan létező admin fiók (MITHOME-97). A
|
||||||
|
# deploy.sh minden deploy után meghívja a Payload "first-register" REST
|
||||||
|
# endpointját ezekkel az adatokkal: teljesen friss (üres users collection-ű)
|
||||||
|
# adatbázisnál létrehozza ezt a fiókot, egyébként (ha már van user)
|
||||||
|
# ártalmatlanul kihagyja — nem írja felül a jelszót utólag. Generálj egyedi,
|
||||||
|
# erős jelszót (pl. jelszókezelővel), NE ossz meg értéket a staginggel; a
|
||||||
|
# hiányzó két érték esetén a deploy.sh csak kihagyja ezt a lépést.
|
||||||
|
ADMIN_EMAIL=admin@mozdit.hu
|
||||||
|
ADMIN_PASSWORD=changeme
|
||||||
|
|
||||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||||
NEXT_PUBLIC_SITE_URL=https://mozdit.hu
|
NEXT_PUBLIC_SITE_URL=https://mozdit.hu
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ MONGO_ROOT_PASSWORD=changeme
|
|||||||
# environmenttel.
|
# environmenttel.
|
||||||
PAYLOAD_SECRET=changeme
|
PAYLOAD_SECRET=changeme
|
||||||
|
|
||||||
|
# Payload admin — ismert, biztosan létező admin fiók (MITHOME-97). A
|
||||||
|
# deploy.sh minden deploy után meghívja a Payload "first-register" REST
|
||||||
|
# endpointját ezekkel az adatokkal: teljesen friss (üres users collection-ű)
|
||||||
|
# adatbázisnál létrehozza ezt a fiókot, egyébként (ha már van user)
|
||||||
|
# ártalmatlanul kihagyja — nem írja felül a jelszót utólag. Generálj egyedi,
|
||||||
|
# erős jelszót (pl. jelszókezelővel); a hiányzó két érték esetén a
|
||||||
|
# deploy.sh csak kihagyja ezt a lépést, nem hibázik el.
|
||||||
|
ADMIN_EMAIL=admin@mozdit.hu
|
||||||
|
ADMIN_PASSWORD=changeme
|
||||||
|
|
||||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||||
NEXT_PUBLIC_SITE_URL=https://stage.mozdit.hu
|
NEXT_PUBLIC_SITE_URL=https://stage.mozdit.hu
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,12 @@ fi
|
|||||||
echo "🔑 Környezeti változók betöltése ($ENV_FILE)..."
|
echo "🔑 Környezeti változók betöltése ($ENV_FILE)..."
|
||||||
|
|
||||||
# WHY: a --env-file kapcsoló csak a compose változó-helyettesítését táplálja;
|
# WHY: a --env-file kapcsoló csak a compose változó-helyettesítését táplálja;
|
||||||
# a shell nem látja belőle az APP_PORT-ot, ezért a healthcheckhez expliciten kiolvassuk.
|
# a shell nem látja belőle ezeket az értékeket, ezért a healthcheckhez és az
|
||||||
APP_PORT_VALUE="$(grep -E '^APP_PORT=' "$ENV_FILE" | tail -n 1 | cut -d= -f2- | tr -d '[:space:]' | tr -d '"' | tr -d "'")"
|
# admin-seedeléshez expliciten kiolvassuk.
|
||||||
|
env_value() {
|
||||||
|
grep -E "^$1=" "$ENV_FILE" | tail -n 1 | cut -d= -f2- | tr -d '[:space:]' | tr -d '"' | tr -d "'"
|
||||||
|
}
|
||||||
|
APP_PORT_VALUE="$(env_value APP_PORT)"
|
||||||
|
|
||||||
# 3. Docker konténerek újraépítése és indítása
|
# 3. Docker konténerek újraépítése és indítása
|
||||||
echo "🐳 Build és indítás..."
|
echo "🐳 Build és indítás..."
|
||||||
@@ -53,15 +57,61 @@ docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up --build --force-recr
|
|||||||
# 4. Healthcheck
|
# 4. Healthcheck
|
||||||
echo "⏳ Healthcheck (max 60s)..."
|
echo "⏳ Healthcheck (max 60s)..."
|
||||||
HEALTH_URL="http://localhost:${APP_PORT_VALUE:-$DEFAULT_PORT}/api/health"
|
HEALTH_URL="http://localhost:${APP_PORT_VALUE:-$DEFAULT_PORT}/api/health"
|
||||||
|
HEALTHY=0
|
||||||
for i in $(seq 1 30); do
|
for i in $(seq 1 30); do
|
||||||
if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
|
if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
|
||||||
echo "✅ Healthcheck OK: $HEALTH_URL"
|
echo "✅ Healthcheck OK: $HEALTH_URL"
|
||||||
echo "✅ Deploy sikeres: [$ENV]"
|
HEALTHY=1
|
||||||
exit 0
|
break
|
||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$HEALTHY" -ne 1 ]; then
|
||||||
echo "❌ Healthcheck sikertelen: $HEALTH_URL"
|
echo "❌ Healthcheck sikertelen: $HEALTH_URL"
|
||||||
docker compose -f "$COMPOSE_FILE" logs app --tail 50
|
docker compose -f "$COMPOSE_FILE" logs app --tail 50
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Payload admin felhasználó biztosítása (MITHOME-97 follow-up)
|
||||||
|
#
|
||||||
|
# WHY: minden friss adatbázisú deploy (első staging/prod indítás, vagy egy
|
||||||
|
# volume-törlés utáni újrakezdés) a Payload "Create first user" képernyőjét
|
||||||
|
# mutatná — valaki ott manuálisan hozná létre a saját fiókját, ami könnyen
|
||||||
|
# elmarad vagy elfelejtődik, és ismeretlen/inkonzisztens admin-hozzáférést
|
||||||
|
# eredményez környezetenként. Payload REST API-ja egy beépített
|
||||||
|
# `POST /<usersCollection>/first-register` endpointot ad erre — DE csakis
|
||||||
|
# akkor enged bármit létrehozni, ha a `users` collection még teljesen üres
|
||||||
|
# (0 dokumentum); ha már van akár egy felhasználó is, 403 Forbidden-t ad.
|
||||||
|
# Ez pont idempotenssé teszi: minden deploy után lefuttatjuk, első alkalommal
|
||||||
|
# létrehozza az ismert admin fiókot ADMIN_EMAIL/ADMIN_PASSWORD alapján,
|
||||||
|
# utána minden további deploy-on ártalmatlanul 403-at kap és kihagyja.
|
||||||
|
ADMIN_EMAIL_VALUE="$(env_value ADMIN_EMAIL)"
|
||||||
|
ADMIN_PASSWORD_VALUE="$(env_value ADMIN_PASSWORD)"
|
||||||
|
if [ -z "$ADMIN_EMAIL_VALUE" ] || [ -z "$ADMIN_PASSWORD_VALUE" ]; then
|
||||||
|
echo "⚠️ ADMIN_EMAIL/ADMIN_PASSWORD nincs beállítva $ENV_FILE-ban — admin-seedelés kihagyva."
|
||||||
|
echo " (Egy teljesen friss adatbázisnál manuálisan kell létrehozni az első usert /admin alatt.)"
|
||||||
|
else
|
||||||
|
echo "👤 Admin felhasználó biztosítása..."
|
||||||
|
ADMIN_HTTP_CODE="$(curl -sS -o /tmp/mozdit-admin-seed-response.json -w '%{http_code}' \
|
||||||
|
-X POST "http://localhost:${APP_PORT_VALUE:-$DEFAULT_PORT}/api/users/first-register" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data-binary @- <<EOF
|
||||||
|
{"email":"${ADMIN_EMAIL_VALUE}","password":"${ADMIN_PASSWORD_VALUE}"}
|
||||||
|
EOF
|
||||||
|
)"
|
||||||
|
rm -f /tmp/mozdit-admin-seed-response.json
|
||||||
|
case "$ADMIN_HTTP_CODE" in
|
||||||
|
200)
|
||||||
|
echo "✅ Admin felhasználó létrehozva ($ADMIN_EMAIL_VALUE)."
|
||||||
|
;;
|
||||||
|
403)
|
||||||
|
echo "✅ Admin felhasználó már létezik — nincs teendő."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "⚠️ Admin-seedelés váratlan válasza: HTTP $ADMIN_HTTP_CODE (a deploy egyébként sikeres, ez nem állítja meg)."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Deploy sikeres: [$ENV]"
|
||||||
|
|||||||
Reference in New Issue
Block a user