Big visual overhaul docker compsoe file etc
Some checks failed
CI / test-and-quality (push) Failing after 4m4s
Some checks failed
CI / test-and-quality (push) Failing after 4m4s
This commit is contained in:
15
infra/env/.env.dev.example
vendored
Normal file
15
infra/env/.env.dev.example
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
DJANGO_SECRET_KEY=change-me-dev
|
||||
DJANGO_DEBUG=true
|
||||
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
|
||||
DB_ENGINE=django.db.backends.mysql
|
||||
DB_NAME=wpp_dev
|
||||
DB_USER=wpp_dev
|
||||
DB_PASSWORD=wpp_dev
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3307
|
||||
TEST_DB_NAME=wpp_test
|
||||
CHANNEL_REDIS_HOST=127.0.0.1
|
||||
CHANNEL_REDIS_PORT=6380
|
||||
USE_SPA_UI=false
|
||||
WPP_SPA_ASSET_BASE=http://localhost:4200/browser
|
||||
WPP_SPA_ASSET_VERSION=dev
|
||||
3
infra/env/.env.prod.example
vendored
3
infra/env/.env.prod.example
vendored
@@ -10,3 +10,6 @@ DB_PORT=3306
|
||||
TEST_DB_NAME=
|
||||
CHANNEL_REDIS_HOST=127.0.0.1
|
||||
CHANNEL_REDIS_PORT=6379
|
||||
USE_SPA_UI=false
|
||||
WPP_SPA_ASSET_BASE=/static/frontend/angular/browser
|
||||
WPP_SPA_ASSET_VERSION=prod-dev
|
||||
|
||||
3
infra/env/.env.staging.example
vendored
3
infra/env/.env.staging.example
vendored
@@ -10,3 +10,6 @@ DB_PORT=3306
|
||||
TEST_DB_NAME=
|
||||
CHANNEL_REDIS_HOST=127.0.0.1
|
||||
CHANNEL_REDIS_PORT=6379
|
||||
USE_SPA_UI=false
|
||||
WPP_SPA_ASSET_BASE=/static/frontend/angular/browser
|
||||
WPP_SPA_ASSET_VERSION=staging-dev
|
||||
|
||||
3
infra/env/.env.test.example
vendored
3
infra/env/.env.test.example
vendored
@@ -10,3 +10,6 @@ DB_PORT=3306
|
||||
TEST_DB_NAME=wpp_test
|
||||
CHANNEL_REDIS_HOST=127.0.0.1
|
||||
CHANNEL_REDIS_PORT=6379
|
||||
USE_SPA_UI=false
|
||||
WPP_SPA_ASSET_BASE=/static/frontend/angular/browser
|
||||
WPP_SPA_ASSET_VERSION=test-dev
|
||||
|
||||
@@ -9,6 +9,18 @@ Staging-miljø for WPP i Proxmox LXC, så release-klar kode kan deployes og smok
|
||||
- Service: wpp-staging.service
|
||||
- Health endpoint: GET /healthz
|
||||
- Database: MySQL (staging må ikke bruge SQLite, issue #133)
|
||||
- Aktuel MVP UI-path: legacy host/player UI (`USE_SPA_UI=false`)
|
||||
|
||||
## MVP env-kontrakt
|
||||
Staging skal mindst have følgende release-relevante env vars sat:
|
||||
|
||||
- `DB_ENGINE=django.db.backends.mysql`
|
||||
- `CHANNEL_REDIS_HOST` + `CHANNEL_REDIS_PORT`
|
||||
- `USE_SPA_UI=false`
|
||||
- `WPP_SPA_ASSET_BASE=/static/frontend/angular/browser`
|
||||
- `WPP_SPA_ASSET_VERSION=<release-tag eller sha>`
|
||||
|
||||
`USE_SPA_UI=true` er ikke del af den primære MVP release-gate. Det hører til separat cutover-verifikation.
|
||||
|
||||
## Verifikation
|
||||
Kør fra devops-shell med Proxmox-adgang:
|
||||
@@ -24,6 +36,23 @@ Forventet:
|
||||
|
||||
Smoke-suite skriver nu et gameplay-artifact som JSON under `/opt/wpp-staging/app/artifacts/smoke/` (kan overrides via `ARTIFACT_DIR`/`ARTIFACT_FILE`).
|
||||
|
||||
Før manuel UI-smoke anbefales følgende bootstrap på staging-app'en:
|
||||
|
||||
python manage.py bootstrap_mvp
|
||||
|
||||
Det sikrer en host-bruger og aktiv demo-kategori/spørgsmål uden ad hoc admin-oprettelse.
|
||||
|
||||
For den automatiske MVP bootstrap + smoke artifact flow bruges den kanoniske kommando:
|
||||
|
||||
./infra/staging/run_mvp_smoke.sh
|
||||
|
||||
Kommandoen kører i staging-CT via Proxmox, loader staging-env, kører `bootstrap_mvp`, og derefter `smoke_staging --artifact ...`.
|
||||
Som default håndhæver den MVP-pathen `USE_SPA_UI=false`. Brug kun `ALLOW_SPA_CUTOVER=1` ved separat SPA-cutover.
|
||||
|
||||
For release-lignende "én kommando" execution bruges wrapperen:
|
||||
|
||||
./infra/staging/deploy_and_smoke_staging.sh [ref] [artifact-path]
|
||||
|
||||
Efter deploy validerer scriptet, at `DB_ENGINE` ikke er `django.db.backends.sqlite3` før migrations køres.
|
||||
|
||||
Deploy-scriptet bruger en release-candidate mappe og promoverer først til `/opt/wpp-staging/app` efter succesfuld `migrate`. Det reducerer schema/code drift ved afbrudte deploys (issue #130) og understøtter release-readiness gate (issue #90).
|
||||
@@ -35,6 +64,10 @@ Officiel kommando:
|
||||
|
||||
./infra/staging/deploy_staging.sh [ref]
|
||||
|
||||
Anbefalet release-wrapper:
|
||||
|
||||
./infra/staging/deploy_and_smoke_staging.sh [ref] [artifact-path]
|
||||
|
||||
Scriptet bruger default PROXMOX_HOST=proxmox-lan og kører sudo -n pct exec på hosten.
|
||||
|
||||
Eksempler:
|
||||
@@ -42,9 +75,25 @@ Eksempler:
|
||||
./infra/staging/deploy_staging.sh
|
||||
./infra/staging/deploy_staging.sh v0.3.0
|
||||
PROXMOX_HOST=proxmox-prod ./infra/staging/deploy_staging.sh main
|
||||
./infra/staging/deploy_and_smoke_staging.sh main
|
||||
./infra/staging/deploy_and_smoke_staging.sh v0.3.0 /opt/wpp-staging/app/artifacts/smoke/release-smoke.json
|
||||
|
||||
## Smoke (canonical execution context)
|
||||
MVP smoke skal køres via Proxmox host over SSH, ligesom deploy:
|
||||
|
||||
./infra/staging/run_mvp_smoke.sh
|
||||
|
||||
Eksempler:
|
||||
|
||||
./infra/staging/run_mvp_smoke.sh
|
||||
./infra/staging/run_mvp_smoke.sh /opt/wpp-staging/app/artifacts/smoke/manual-smoke.json
|
||||
PROXMOX_HOST=proxmox-prod CT_ID=222 ./infra/staging/run_mvp_smoke.sh
|
||||
ALLOW_SPA_CUTOVER=1 ./infra/staging/run_mvp_smoke.sh
|
||||
|
||||
## Policy-kobling
|
||||
Før deploy:
|
||||
1. Bekræft at tester ikke er aktiv (ingen aktiv smoke-run).
|
||||
2. Deploy til staging skal lykkes.
|
||||
3. Først derefter må release-tag oprettes (se docs/RELEASE_POLICY.md).
|
||||
2. Kør helst `./infra/staging/deploy_and_smoke_staging.sh` for release-kandidater.
|
||||
3. Hvis wrapper ikke bruges: deploy til staging og kør derefter `./infra/staging/run_mvp_smoke.sh`.
|
||||
4. Bekræft MVP UI-smoke på legacy UI (`/lobby/ui/host` + `/lobby/ui/player`).
|
||||
5. Først derefter må release-tag oprettes (se docs/RELEASE_POLICY.md).
|
||||
|
||||
18
infra/staging/deploy_and_smoke_staging.sh
Executable file
18
infra/staging/deploy_and_smoke_staging.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REF_NAME="${1:-main}"
|
||||
ARTIFACT_FILE="${2:-}"
|
||||
|
||||
echo "[release] deploy + smoke start REF=${REF_NAME}"
|
||||
|
||||
"${SCRIPT_DIR}/deploy_staging.sh" "${REF_NAME}"
|
||||
|
||||
if [[ -n "${ARTIFACT_FILE}" ]]; then
|
||||
"${SCRIPT_DIR}/run_mvp_smoke.sh" "${ARTIFACT_FILE}"
|
||||
else
|
||||
"${SCRIPT_DIR}/run_mvp_smoke.sh"
|
||||
fi
|
||||
|
||||
echo "[release] deploy + smoke OK REF=${REF_NAME}"
|
||||
97
infra/staging/run_mvp_smoke.sh
Executable file
97
infra/staging/run_mvp_smoke.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CT_ID="${CT_ID:-143}"
|
||||
PROXMOX_HOST="${PROXMOX_HOST:-proxmox-lan}"
|
||||
APP_DIR="${APP_DIR:-/opt/wpp-staging/app}"
|
||||
ARTIFACT_FILE="${1:-${ARTIFACT_FILE:-}}"
|
||||
ARTIFACT_DIR_ARG="${ARTIFACT_DIR:-}"
|
||||
BASE_URL_ARG="${BASE_URL:-}"
|
||||
ISSUE_ON_FAIL="${ISSUE_ON_FAIL:-1}"
|
||||
RUN_BOOTSTRAP_MVP="${RUN_BOOTSTRAP_MVP:-1}"
|
||||
BOOTSTRAP_MVP_ARGS="${BOOTSTRAP_MVP_ARGS:-}"
|
||||
ALLOW_SPA_CUTOVER="${ALLOW_SPA_CUTOVER:-0}"
|
||||
ENV_FILE_ARG="${ENV_FILE:-}"
|
||||
GITEA_BASE_ARG="${GITEA_BASE:-}"
|
||||
GITEA_REPO_ARG="${GITEA_REPO:-}"
|
||||
GITEA_USER_ARG="${GITEA_USER:-}"
|
||||
GITEA_TOKEN_ARG="${GITEA_TOKEN:-}"
|
||||
|
||||
echo "[smoke] host=${PROXMOX_HOST} CT_ID=${CT_ID} APP_DIR=${APP_DIR}"
|
||||
if [[ -n "${ARTIFACT_FILE}" ]]; then
|
||||
echo "[smoke] artifact=${ARTIFACT_FILE}"
|
||||
fi
|
||||
|
||||
ssh "${PROXMOX_HOST}" sudo -n /usr/sbin/pct exec "${CT_ID}" -- bash -s -- \
|
||||
"${APP_DIR}" \
|
||||
"${ARTIFACT_FILE}" \
|
||||
"${ARTIFACT_DIR_ARG}" \
|
||||
"${BASE_URL_ARG}" \
|
||||
"${ISSUE_ON_FAIL}" \
|
||||
"${RUN_BOOTSTRAP_MVP}" \
|
||||
"${BOOTSTRAP_MVP_ARGS}" \
|
||||
"${ALLOW_SPA_CUTOVER}" \
|
||||
"${ENV_FILE_ARG}" \
|
||||
"${GITEA_BASE_ARG}" \
|
||||
"${GITEA_REPO_ARG}" \
|
||||
"${GITEA_USER_ARG}" \
|
||||
"${GITEA_TOKEN_ARG}" <<'REMOTE'
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="$1"
|
||||
ARTIFACT_FILE="$2"
|
||||
ARTIFACT_DIR_ARG="$3"
|
||||
BASE_URL_ARG="$4"
|
||||
ISSUE_ON_FAIL="$5"
|
||||
RUN_BOOTSTRAP_MVP="$6"
|
||||
BOOTSTRAP_MVP_ARGS="$7"
|
||||
ALLOW_SPA_CUTOVER="$8"
|
||||
ENV_FILE_ARG="$9"
|
||||
GITEA_BASE_ARG="${10}"
|
||||
GITEA_REPO_ARG="${11}"
|
||||
GITEA_USER_ARG="${12}"
|
||||
GITEA_TOKEN_ARG="${13}"
|
||||
|
||||
SCRIPT_PATH="${APP_DIR}/infra/staging/smoke_suite.sh"
|
||||
if [[ ! -f "${SCRIPT_PATH}" ]]; then
|
||||
echo "[smoke] ERROR: missing script ${SCRIPT_PATH}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ENV_VARS=(
|
||||
"APP_DIR=${APP_DIR}"
|
||||
"ISSUE_ON_FAIL=${ISSUE_ON_FAIL}"
|
||||
"RUN_BOOTSTRAP_MVP=${RUN_BOOTSTRAP_MVP}"
|
||||
"BOOTSTRAP_MVP_ARGS=${BOOTSTRAP_MVP_ARGS}"
|
||||
"ALLOW_SPA_CUTOVER=${ALLOW_SPA_CUTOVER}"
|
||||
)
|
||||
|
||||
if [[ -n "${ARTIFACT_FILE}" ]]; then
|
||||
ENV_VARS+=("ARTIFACT_FILE=${ARTIFACT_FILE}")
|
||||
fi
|
||||
if [[ -n "${ARTIFACT_DIR_ARG}" ]]; then
|
||||
ENV_VARS+=("ARTIFACT_DIR=${ARTIFACT_DIR_ARG}")
|
||||
fi
|
||||
if [[ -n "${BASE_URL_ARG}" ]]; then
|
||||
ENV_VARS+=("BASE_URL=${BASE_URL_ARG}")
|
||||
fi
|
||||
if [[ -n "${ENV_FILE_ARG}" ]]; then
|
||||
ENV_VARS+=("ENV_FILE=${ENV_FILE_ARG}")
|
||||
fi
|
||||
if [[ -n "${GITEA_BASE_ARG}" ]]; then
|
||||
ENV_VARS+=("GITEA_BASE=${GITEA_BASE_ARG}")
|
||||
fi
|
||||
if [[ -n "${GITEA_REPO_ARG}" ]]; then
|
||||
ENV_VARS+=("GITEA_REPO=${GITEA_REPO_ARG}")
|
||||
fi
|
||||
if [[ -n "${GITEA_USER_ARG}" ]]; then
|
||||
ENV_VARS+=("GITEA_USER=${GITEA_USER_ARG}")
|
||||
fi
|
||||
if [[ -n "${GITEA_TOKEN_ARG}" ]]; then
|
||||
ENV_VARS+=("GITEA_TOKEN=${GITEA_TOKEN_ARG}")
|
||||
fi
|
||||
|
||||
runuser -u wpp -- env "${ENV_VARS[@]}" bash "${SCRIPT_PATH}"
|
||||
REMOTE
|
||||
|
||||
echo "[smoke] OK: staging MVP smoke complete"
|
||||
@@ -4,6 +4,9 @@ set -euo pipefail
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8000}"
|
||||
APP_DIR="${APP_DIR:-/opt/wpp-staging/app}"
|
||||
ISSUE_ON_FAIL="${ISSUE_ON_FAIL:-1}"
|
||||
RUN_BOOTSTRAP_MVP="${RUN_BOOTSTRAP_MVP:-1}"
|
||||
BOOTSTRAP_MVP_ARGS="${BOOTSTRAP_MVP_ARGS:-}"
|
||||
ALLOW_SPA_CUTOVER="${ALLOW_SPA_CUTOVER:-0}"
|
||||
|
||||
fail() {
|
||||
local message="$1"
|
||||
@@ -50,10 +53,36 @@ PY
|
||||
echo "[smoke] healthz check: ${BASE_URL}/healthz"
|
||||
curl -fsS "${BASE_URL}/healthz" >/dev/null || { SMOKE_FAIL_MESSAGE="healthz check failed" fail "healthz check failed"; }
|
||||
|
||||
ENV_FILE="${ENV_FILE:-/etc/wpp/staging.env}"
|
||||
resolve_env_file() {
|
||||
if [[ -n "${ENV_FILE:-}" ]]; then
|
||||
if [[ -f "${ENV_FILE}" ]]; then
|
||||
printf '%s\n' "${ENV_FILE}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
local candidate
|
||||
for candidate in \
|
||||
/opt/wpp-staging/.env.staging \
|
||||
/opt/wpp-staging/.env \
|
||||
/opt/wpp-staging/env/wpp_staging.env \
|
||||
/opt/wpp-staging/secrets/wpp_staging.env \
|
||||
/etc/wpp/staging.env
|
||||
do
|
||||
if [[ -f "${candidate}" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
ENV_FILE="$(resolve_env_file)" || { SMOKE_FAIL_MESSAGE="staging env file not found" fail "staging env file not found"; }
|
||||
echo "[smoke] env file: ${ENV_FILE}"
|
||||
|
||||
run_manage() {
|
||||
local cmd="$1"
|
||||
(
|
||||
cd "${APP_DIR}"
|
||||
if [[ -f "${ENV_FILE}" ]]; then
|
||||
@@ -62,18 +91,37 @@ run_manage() {
|
||||
source "${ENV_FILE}"
|
||||
set +a
|
||||
fi
|
||||
.venv/bin/python manage.py ${cmd}
|
||||
.venv/bin/python manage.py "$@"
|
||||
)
|
||||
}
|
||||
|
||||
echo "[smoke] migration consistency check"
|
||||
run_manage "migrate --check --noinput" || { SMOKE_FAIL_MESSAGE="schema drift: unapplied migrations in staging" fail "schema drift: unapplied migrations in staging"; }
|
||||
run_manage migrate --check --noinput || { SMOKE_FAIL_MESSAGE="schema drift: unapplied migrations in staging" fail "schema drift: unapplied migrations in staging"; }
|
||||
|
||||
if [[ "${ALLOW_SPA_CUTOVER}" != "1" ]]; then
|
||||
echo "[smoke] MVP UI mode check (expect USE_SPA_UI=false)"
|
||||
run_manage shell -c "from django.conf import settings; import sys; print('USE_SPA_UI=' + ('true' if settings.USE_SPA_UI else 'false')); sys.exit(0 if not settings.USE_SPA_UI else 1)" \
|
||||
|| { SMOKE_FAIL_MESSAGE="USE_SPA_UI=true is outside the canonical MVP smoke path" fail "USE_SPA_UI=true is outside the canonical MVP smoke path"; }
|
||||
else
|
||||
echo "[smoke] SPA cutover override enabled (ALLOW_SPA_CUTOVER=1)"
|
||||
fi
|
||||
|
||||
if [[ "${RUN_BOOTSTRAP_MVP}" == "1" ]]; then
|
||||
echo "[smoke] bootstrap MVP host + demo questions"
|
||||
if [[ -n "${BOOTSTRAP_MVP_ARGS}" ]]; then
|
||||
# shellcheck disable=SC2206
|
||||
bootstrap_args=(${BOOTSTRAP_MVP_ARGS})
|
||||
run_manage bootstrap_mvp "${bootstrap_args[@]}" || { SMOKE_FAIL_MESSAGE="manage.py bootstrap_mvp failed" fail "manage.py bootstrap_mvp failed"; }
|
||||
else
|
||||
run_manage bootstrap_mvp || { SMOKE_FAIL_MESSAGE="manage.py bootstrap_mvp failed" fail "manage.py bootstrap_mvp failed"; }
|
||||
fi
|
||||
fi
|
||||
|
||||
ARTIFACT_DIR="${ARTIFACT_DIR:-${APP_DIR}/artifacts/smoke}"
|
||||
ARTIFACT_FILE="${ARTIFACT_FILE:-${ARTIFACT_DIR}/smoke-$(date -u +%Y%m%dT%H%M%SZ).json}"
|
||||
|
||||
echo "[smoke] gameplay flow via management command"
|
||||
run_manage "smoke_staging --artifact ${ARTIFACT_FILE}" || { SMOKE_FAIL_MESSAGE="manage.py smoke_staging failed" fail "manage.py smoke_staging failed"; }
|
||||
run_manage smoke_staging --artifact "${ARTIFACT_FILE}" || { SMOKE_FAIL_MESSAGE="manage.py smoke_staging failed" fail "manage.py smoke_staging failed"; }
|
||||
|
||||
echo "[smoke] artifact: ${ARTIFACT_FILE}"
|
||||
echo "[smoke] OK"
|
||||
|
||||
Reference in New Issue
Block a user