ci: fix deploy checkout (no eval) + workflow_dispatch fallback
All checks were successful
CI / build-and-anchors (push) Successful in 1m50s
SMOKE / smoke (push) Successful in 17s

This commit is contained in:
2026-02-26 18:48:12 +01:00
parent 4dec9e182b
commit 0d5b790e52

View File

@@ -44,21 +44,16 @@ jobs:
set -euo pipefail set -euo pipefail
test -f "$EVENT_JSON" || { echo "❌ Missing $EVENT_JSON"; exit 1; } test -f "$EVENT_JSON" || { echo "❌ Missing $EVENT_JSON"; exit 1; }
# Write /tmp/deploy.env with shell-safe quoting (NO eval)
node --input-type=module <<'NODE' node --input-type=module <<'NODE'
import fs from "node:fs"; import fs from "node:fs";
const ev = JSON.parse(fs.readFileSync(process.env.EVENT_JSON, "utf8")); const ev = JSON.parse(fs.readFileSync(process.env.EVENT_JSON, "utf8"));
const repoObj = ev?.repository || {}; const repoObj = ev?.repository || {};
const cloneUrl = const cloneUrl =
repoObj?.clone_url || repoObj?.clone_url ||
(repoObj?.html_url ? (repoObj.html_url.replace(/\/$/,"") + ".git") : ""); (repoObj?.html_url ? (repoObj.html_url.replace(/\/$/,"") + ".git") : "");
if (!cloneUrl) throw new Error("No repository clone_url/html_url in event.json"); if (!cloneUrl) throw new Error("No repository clone_url/html_url in event.json");
const defaultBranch = repoObj?.default_branch || "main"; const defaultBranch = repoObj?.default_branch || "main";
// On push, act/Gitea usually provides GITHUB_SHA; on workflow_dispatch it may be empty.
const sha = const sha =
(process.env.GITHUB_SHA && String(process.env.GITHUB_SHA).trim()) || (process.env.GITHUB_SHA && String(process.env.GITHUB_SHA).trim()) ||
ev?.after || ev?.after ||
@@ -68,19 +63,14 @@ jobs:
""; "";
const shq = (s) => "'" + String(s).replace(/'/g, "'\\''") + "'"; const shq = (s) => "'" + String(s).replace(/'/g, "'\\''") + "'";
fs.writeFileSync("/tmp/deploy.env", [
const out = [
`REPO_URL=${shq(cloneUrl)}`, `REPO_URL=${shq(cloneUrl)}`,
`DEFAULT_BRANCH=${shq(defaultBranch)}`, `DEFAULT_BRANCH=${shq(defaultBranch)}`,
`SHA=${shq(sha)}` `SHA=${shq(sha)}`
].join("\n") + "\n"; ].join("\n") + "\n");
fs.writeFileSync("/tmp/deploy.env", out);
process.stdout.write(out);
NODE NODE
source /tmp/deploy.env source /tmp/deploy.env
echo "Repo URL: $REPO_URL" echo "Repo URL: $REPO_URL"
echo "Default branch: $DEFAULT_BRANCH" echo "Default branch: $DEFAULT_BRANCH"
echo "SHA: ${SHA:-<empty>}" echo "SHA: ${SHA:-<empty>}"
@@ -93,7 +83,6 @@ jobs:
git fetch --depth 1 origin "$SHA" git fetch --depth 1 origin "$SHA"
git -c advice.detachedHead=false checkout -q FETCH_HEAD git -c advice.detachedHead=false checkout -q FETCH_HEAD
else else
# workflow_dispatch fallback: checkout latest of default branch
git fetch --depth 1 origin "$DEFAULT_BRANCH" git fetch --depth 1 origin "$DEFAULT_BRANCH"
git -c advice.detachedHead=false checkout -q "origin/$DEFAULT_BRANCH" git -c advice.detachedHead=false checkout -q "origin/$DEFAULT_BRANCH"
SHA="$(git rev-parse HEAD)" SHA="$(git rev-parse HEAD)"
@@ -148,6 +137,15 @@ jobs:
docker version docker version
docker compose version docker compose version
# 🔥 KEY FIX: reuse existing compose project name if containers already exist
PROJ="$(docker inspect archicratie-web-blue --format '{{ index .Config.Labels "com.docker.compose.project" }}' 2>/dev/null || true)"
if [[ -z "${PROJ:-}" ]]; then
PROJ="$(docker inspect archicratie-web-green --format '{{ index .Config.Labels "com.docker.compose.project" }}' 2>/dev/null || true)"
fi
if [[ -z "${PROJ:-}" ]]; then PROJ="archicratie-web"; fi
echo "COMPOSE_PROJECT_NAME='$PROJ'" >> /tmp/deploy.env
echo "✅ Using COMPOSE_PROJECT_NAME=$PROJ"
- name: Assert required vars (PUBLIC_GITEA_*) - name: Assert required vars (PUBLIC_GITEA_*)
env: env:
PUBLIC_GITEA_BASE: ${{ vars.PUBLIC_GITEA_BASE }} PUBLIC_GITEA_BASE: ${{ vars.PUBLIC_GITEA_BASE }}
@@ -183,14 +181,20 @@ jobs:
set -euo pipefail set -euo pipefail
source /tmp/deploy.env source /tmp/deploy.env
[[ "${GO:-0}" == "1" ]] || { echo " skipped"; exit 0; } [[ "${GO:-0}" == "1" ]] || { echo " skipped"; exit 0; }
PROJ="${COMPOSE_PROJECT_NAME:-archicratie-web}"
TS="$(date -u +%Y%m%d-%H%M%S)" TS="$(date -u +%Y%m%d-%H%M%S)"
echo "TS='$TS'" >> /tmp/deploy.env echo "TS='$TS'" >> /tmp/deploy.env
docker image tag archicratie-web:blue "archicratie-web:blue.BAK.${TS}" || true docker image tag archicratie-web:blue "archicratie-web:blue.BAK.${TS}" || true
docker image tag archicratie-web:green "archicratie-web:green.BAK.${TS}" || true docker image tag archicratie-web:green "archicratie-web:green.BAK.${TS}" || true
docker compose -f docker-compose.yml build --no-cache web_blue # ✅ use cache (DO NOT --no-cache)
docker compose -f docker-compose.yml up -d --force-recreate web_blue docker compose -p "$PROJ" -f docker-compose.yml build web_blue
# ✅ hard fix: remove existing container if name conflicts
docker rm -f archicratie-web-blue || true
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_blue
curl -fsS "http://127.0.0.1:8081/para-index.json" >/dev/null curl -fsS "http://127.0.0.1:8081/para-index.json" >/dev/null
curl -fsS "http://127.0.0.1:8081/annotations-index.json" >/dev/null curl -fsS "http://127.0.0.1:8081/annotations-index.json" >/dev/null
@@ -213,18 +217,21 @@ jobs:
set -euo pipefail set -euo pipefail
source /tmp/deploy.env source /tmp/deploy.env
[[ "${GO:-0}" == "1" ]] || { echo " skipped"; exit 0; } [[ "${GO:-0}" == "1" ]] || { echo " skipped"; exit 0; }
PROJ="${COMPOSE_PROJECT_NAME:-archicratie-web}"
TS="${TS:-$(date -u +%Y%m%d-%H%M%S)}" TS="${TS:-$(date -u +%Y%m%d-%H%M%S)}"
rollback() { rollback() {
echo "⚠️ rollback green -> previous image tag (best effort)" echo "⚠️ rollback green -> previous image tag (best effort)"
docker image tag "archicratie-web:green.BAK.${TS}" archicratie-web:green || true docker image tag "archicratie-web:green.BAK.${TS}" archicratie-web:green || true
docker compose -f docker-compose.yml up -d --force-recreate web_green || true docker rm -f archicratie-web-green || true
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_green || true
} }
set +e set +e
docker compose -f docker-compose.yml build --no-cache web_green docker compose -p "$PROJ" -f docker-compose.yml build web_green
docker compose -f docker-compose.yml up -d --force-recreate web_green
docker rm -f archicratie-web-green || true
docker compose -p "$PROJ" -f docker-compose.yml up -d --force-recreate --remove-orphans web_green
curl -fsS "http://127.0.0.1:8082/para-index.json" >/dev/null curl -fsS "http://127.0.0.1:8082/para-index.json" >/dev/null
curl -fsS "http://127.0.0.1:8082/annotations-index.json" >/dev/null curl -fsS "http://127.0.0.1:8082/annotations-index.json" >/dev/null