From 7a9a5319acbc646ad2a7ea838a87a3234c7068e5 Mon Sep 17 00:00:00 2001 From: Archicratia Date: Wed, 18 Mar 2026 10:28:13 +0100 Subject: [PATCH] Add ops health manifest to deploy pipeline --- .gitea/workflows/deploy-staging-live.yml | 36 ++++++++++++++++++++++++ .gitignore | 3 +- scripts/write-ops-health.mjs | 20 +++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 scripts/write-ops-health.mjs diff --git a/.gitea/workflows/deploy-staging-live.yml b/.gitea/workflows/deploy-staging-live.yml index 7f8a8e8..112b3b6 100644 --- a/.gitea/workflows/deploy-staging-live.yml +++ b/.gitea/workflows/deploy-staging-live.yml @@ -297,6 +297,19 @@ jobs: docker image tag archicratie-web:blue "archicratie-web:blue.BAK.${TS}" || true docker image tag archicratie-web:green "archicratie-web:green.BAK.${TS}" || true + BUILD_TIME_RAW="$(date '+%Y-%m-%dT%H:%M:%S%z')" + BUILD_TIME="${BUILD_TIME_RAW:0:${#BUILD_TIME_RAW}-2}:${BUILD_TIME_RAW:${#BUILD_TIME_RAW}-2}" + + PUBLIC_OPS_ENV=staging \ + PUBLIC_OPS_UPSTREAM=web_blue \ + PUBLIC_BUILD_SHA="${AFTER}" \ + PUBLIC_BUILD_TIME="${BUILD_TIME}" \ + node scripts/write-ops-health.mjs + + test -f public/__ops/health.json + echo "=== public/__ops/health.json (blue/staging) ===" + cat public/__ops/health.json + docker compose -p "$PROJ" -f docker-compose.yml build web_blue docker rm -f archicratie-web-blue || true docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_blue @@ -306,6 +319,11 @@ jobs: wait_url "http://127.0.0.1:8081/annotations-index.json" "blue annotations-index" wait_url "http://127.0.0.1:8081/pagefind/pagefind.js" "blue pagefind.js" + wait_url "http://127.0.0.1:8081/__ops/health.json" "blue ops health" + + curl -fsS --max-time 6 "http://127.0.0.1:8081/__ops/health.json" \ + | python3 -c 'import sys, json; j=json.load(sys.stdin); print("env=", j.get("env")); print("upstream=", j.get("upstream")); print("buildSha=", j.get("buildSha")); print("builtAt=", j.get("builtAt"))' + CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8081/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)" echo "canonical(blue)=$CANON" echo "$CANON" | grep -q 'https://staging\.archicratie\.trans-hands\.synology\.me/' || { @@ -353,6 +371,19 @@ jobs: docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_green || true } + BUILD_TIME_RAW="$(date '+%Y-%m-%dT%H:%M:%S%z')" + BUILD_TIME="${BUILD_TIME_RAW:0:${#BUILD_TIME_RAW}-2}:${BUILD_TIME_RAW:${#BUILD_TIME_RAW}-2}" + + PUBLIC_OPS_ENV=prod \ + PUBLIC_OPS_UPSTREAM=web_green \ + PUBLIC_BUILD_SHA="${AFTER}" \ + PUBLIC_BUILD_TIME="${BUILD_TIME}" \ + node scripts/write-ops-health.mjs + + test -f public/__ops/health.json + echo "=== public/__ops/health.json (green/prod) ===" + cat public/__ops/health.json + # build/restart green if ! docker compose -p "$PROJ" -f docker-compose.yml build web_green; then echo "❌ build green failed"; rollback; exit 4 @@ -366,6 +397,11 @@ jobs: if ! wait_url "http://127.0.0.1:8082/annotations-index.json" "green annotations-index"; then rollback; exit 4; fi if ! wait_url "http://127.0.0.1:8082/pagefind/pagefind.js" "green pagefind.js"; then rollback; exit 4; fi + if ! wait_url "http://127.0.0.1:8082/__ops/health.json" "green ops health"; then rollback; exit 4; fi + + curl -fsS --max-time 6 "http://127.0.0.1:8082/__ops/health.json" \ + | python3 -c 'import sys, json; j=json.load(sys.stdin); print("env=", j.get("env")); print("upstream=", j.get("upstream")); print("buildSha=", j.get("buildSha")); print("builtAt=", j.get("builtAt"))' + CANON="$(curl -fsS --max-time 6 "http://127.0.0.1:8082/archicrat-ia/chapitre-1/" | grep -oE 'rel="canonical" href="[^"]+"' | head -n1 || true)" echo "canonical(green)=$CANON" echo "$CANON" | grep -q 'https://archicratie\.trans-hands\.synology\.me/' || { diff --git a/.gitignore b/.gitignore index 29b3a0e..42d963f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ public/favicon_io.zip .DS_Store # local temp workspace -.tmp/ \ No newline at end of file +.tmp/ +public/__ops/health.json diff --git a/scripts/write-ops-health.mjs b/scripts/write-ops-health.mjs new file mode 100644 index 0000000..498c3a0 --- /dev/null +++ b/scripts/write-ops-health.mjs @@ -0,0 +1,20 @@ +import fs from "node:fs"; +import path from "node:path"; + +const root = process.cwd(); +const outDir = path.join(root, "public", "__ops"); +const outFile = path.join(outDir, "health.json"); + +const payload = { + service: "archicratie-site", + env: process.env.PUBLIC_OPS_ENV || "unknown", + upstream: process.env.PUBLIC_OPS_UPSTREAM || "unknown", + buildSha: process.env.PUBLIC_BUILD_SHA || "unknown", + builtAt: process.env.PUBLIC_BUILD_TIME || new Date().toISOString(), +}; + +fs.mkdirSync(outDir, { recursive: true }); +fs.writeFileSync(outFile, `${JSON.stringify(payload, null, 2)}\n`, "utf8"); + +console.log(`✅ ops health written: ${outFile}`); +console.log(payload); \ No newline at end of file