Compare commits
8 Commits
chore/fix-
...
chore/fix-
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e95dc9898 | |||
| 2b612214bb | |||
| 29a6c349aa | |||
|
|
33a227c401 | ||
| 396ad4df7c | |||
|
|
0b39427090 | ||
| 8fcb18cb46 | |||
| 97dd3797d6 |
191
.gitea/workflows/deploy-staging-live.yml
Normal file
191
.gitea/workflows/deploy-staging-live.yml
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
name: Deploy staging+live (annotations)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --dns-result-order=ipv4first
|
||||||
|
DOCKER_API_VERSION: "1.43"
|
||||||
|
COMPOSE_VERSION: "2.29.7"
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: deploy-staging-live-main
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: mcr.microsoft.com/devcontainers/javascript-node:22-bookworm
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Tools sanity
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
git --version
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
|
||||||
|
- name: Checkout (from event.json, no external actions)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
export EVENT_JSON="/var/run/act/workflow/event.json"
|
||||||
|
test -f "$EVENT_JSON" || { echo "❌ Missing $EVENT_JSON"; exit 1; }
|
||||||
|
|
||||||
|
eval "$(node --input-type=module -e 'import fs from "node:fs";
|
||||||
|
const ev = JSON.parse(fs.readFileSync(process.env.EVENT_JSON,"utf8"));
|
||||||
|
const repo =
|
||||||
|
ev?.repository?.clone_url ||
|
||||||
|
(ev?.repository?.html_url ? (ev.repository.html_url.replace(/\/$/,"") + ".git") : "");
|
||||||
|
const sha =
|
||||||
|
ev?.after ||
|
||||||
|
ev?.pull_request?.head?.sha ||
|
||||||
|
ev?.head_commit?.id ||
|
||||||
|
ev?.sha ||
|
||||||
|
"";
|
||||||
|
if (!repo) throw new Error("No repository url in event.json");
|
||||||
|
if (!sha) throw new Error("No sha in event.json");
|
||||||
|
process.stdout.write(`REPO_URL=${JSON.stringify(repo)}\nSHA=${JSON.stringify(sha)}\n`);
|
||||||
|
')"
|
||||||
|
|
||||||
|
echo "Repo URL: $REPO_URL"
|
||||||
|
echo "SHA: $SHA"
|
||||||
|
|
||||||
|
rm -rf .git
|
||||||
|
git init -q
|
||||||
|
git remote add origin "$REPO_URL"
|
||||||
|
git fetch --depth 1 origin "$SHA"
|
||||||
|
git -c advice.detachedHead=false checkout -q FETCH_HEAD
|
||||||
|
git log -1 --oneline
|
||||||
|
|
||||||
|
echo "SHA=$SHA" >> /tmp/deploy.env
|
||||||
|
echo "REPO_URL=$REPO_URL" >> /tmp/deploy.env
|
||||||
|
|
||||||
|
- name: Gate — auto deploy only on annotations/media changes
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /tmp/deploy.env
|
||||||
|
|
||||||
|
# fichiers touchés par CE commit (merge commit inclus)
|
||||||
|
CHANGED="$(git diff-tree --no-commit-id --name-only -r "$SHA" || true)"
|
||||||
|
echo "== changed files =="
|
||||||
|
echo "$CHANGED" | sed -n '1,200p'
|
||||||
|
|
||||||
|
# Gate strict : uniquement annotations + media + le workflow lui-même (si tu veux autoriser)
|
||||||
|
if echo "$CHANGED" | grep -qE '^(src/annotations/|public/media/)'; then
|
||||||
|
echo "GO=1" >> /tmp/deploy.env
|
||||||
|
echo "✅ deploy allowed (annotations/media change detected)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "GO=0" >> /tmp/deploy.env
|
||||||
|
echo "ℹ️ no annotations/media change -> skip deploy"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: Install docker client + docker compose plugin (v2)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /tmp/deploy.env
|
||||||
|
[[ "${GO:-0}" == "1" ]] || { echo "ℹ️ skipped"; exit 0; }
|
||||||
|
|
||||||
|
apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true update
|
||||||
|
apt-get install -y --no-install-recommends ca-certificates curl docker.io
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
mkdir -p /usr/local/lib/docker/cli-plugins
|
||||||
|
curl -fsSL \
|
||||||
|
"https://github.com/docker/compose/releases/download/v${COMPOSE_VERSION}/docker-compose-linux-x86_64" \
|
||||||
|
-o /usr/local/lib/docker/cli-plugins/docker-compose
|
||||||
|
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
|
||||||
|
|
||||||
|
docker version
|
||||||
|
docker compose version
|
||||||
|
|
||||||
|
- name: Assert required vars (PUBLIC_GITEA_*)
|
||||||
|
env:
|
||||||
|
PUBLIC_GITEA_BASE: ${{ vars.PUBLIC_GITEA_BASE }}
|
||||||
|
PUBLIC_GITEA_OWNER: ${{ vars.PUBLIC_GITEA_OWNER }}
|
||||||
|
PUBLIC_GITEA_REPO: ${{ vars.PUBLIC_GITEA_REPO }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /tmp/deploy.env
|
||||||
|
[[ "${GO:-0}" == "1" ]] || { echo "ℹ️ skipped"; exit 0; }
|
||||||
|
|
||||||
|
test -n "${PUBLIC_GITEA_BASE:-}" || { echo "❌ missing repo var PUBLIC_GITEA_BASE"; exit 2; }
|
||||||
|
test -n "${PUBLIC_GITEA_OWNER:-}" || { echo "❌ missing repo var PUBLIC_GITEA_OWNER"; exit 2; }
|
||||||
|
test -n "${PUBLIC_GITEA_REPO:-}" || { echo "❌ missing repo var PUBLIC_GITEA_REPO"; exit 2; }
|
||||||
|
echo "✅ vars OK"
|
||||||
|
|
||||||
|
- name: Build + deploy staging (blue) then smoke
|
||||||
|
env:
|
||||||
|
PUBLIC_GITEA_BASE: ${{ vars.PUBLIC_GITEA_BASE }}
|
||||||
|
PUBLIC_GITEA_OWNER: ${{ vars.PUBLIC_GITEA_OWNER }}
|
||||||
|
PUBLIC_GITEA_REPO: ${{ vars.PUBLIC_GITEA_REPO }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /tmp/deploy.env
|
||||||
|
[[ "${GO:-0}" == "1" ]] || { echo "ℹ️ skipped"; exit 0; }
|
||||||
|
|
||||||
|
# backup tags (best effort)
|
||||||
|
TS="$(date -u +%Y%m%d-%H%M%S)"
|
||||||
|
echo "TS=$TS" >> /tmp/deploy.env
|
||||||
|
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 + restart staging (blue=8081)
|
||||||
|
docker compose build --no-cache web_blue
|
||||||
|
docker compose up -d --force-recreate web_blue
|
||||||
|
|
||||||
|
# smoke staging (local port)
|
||||||
|
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/pagefind/pagefind.js" >/dev/null
|
||||||
|
|
||||||
|
CANON="$(curl -fsS "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/' || {
|
||||||
|
echo "❌ staging canonical mismatch"; exit 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ staging OK"
|
||||||
|
|
||||||
|
- name: Build + deploy live (green) then smoke + rollback if needed
|
||||||
|
env:
|
||||||
|
PUBLIC_GITEA_BASE: ${{ vars.PUBLIC_GITEA_BASE }}
|
||||||
|
PUBLIC_GITEA_OWNER: ${{ vars.PUBLIC_GITEA_OWNER }}
|
||||||
|
PUBLIC_GITEA_REPO: ${{ vars.PUBLIC_GITEA_REPO }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
source /tmp/deploy.env
|
||||||
|
[[ "${GO:-0}" == "1" ]] || { echo "ℹ️ skipped"; exit 0; }
|
||||||
|
|
||||||
|
TS="${TS:-$(date -u +%Y%m%d-%H%M%S)}"
|
||||||
|
|
||||||
|
rollback() {
|
||||||
|
echo "⚠️ rollback green -> previous image tag (best effort)"
|
||||||
|
docker image tag "archicratie-web:green.BAK.${TS}" archicratie-web:green || true
|
||||||
|
docker compose up -d --force-recreate web_green || true
|
||||||
|
}
|
||||||
|
|
||||||
|
set +e
|
||||||
|
docker compose build --no-cache web_green
|
||||||
|
docker compose up -d --force-recreate web_green
|
||||||
|
|
||||||
|
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/pagefind/pagefind.js" >/dev/null
|
||||||
|
|
||||||
|
CANON="$(curl -fsS "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/' || {
|
||||||
|
echo "❌ live canonical mismatch"; rollback; exit 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ live OK"
|
||||||
|
set -e
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 822 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 822 KiB |
21
src/annotations/archicrat-ia/chapitre-4.yml
Normal file
21
src/annotations/archicrat-ia/chapitre-4.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
schema: 1
|
||||||
|
page: archicrat-ia/chapitre-4
|
||||||
|
paras:
|
||||||
|
p-2-31b12529:
|
||||||
|
media:
|
||||||
|
- type: image
|
||||||
|
src: /media/archicrat-ia/chapitre-4/p-2-31b12529/Capture_d_e_cran_2026-02-16_a_13.05.58.png
|
||||||
|
caption: "[Media] p-2-31b12529 — Chapitre 4 — Histoire archicratique des
|
||||||
|
révolutions industrielles"
|
||||||
|
credit: ""
|
||||||
|
ts: 2026-02-25T18:58:32.359Z
|
||||||
|
fromIssue: 115
|
||||||
|
p-7-1da4a458:
|
||||||
|
media:
|
||||||
|
- type: image
|
||||||
|
src: /media/archicrat-ia/chapitre-4/p-7-1da4a458/Capture_d_e_cran_2026-02-16_a_13.05.58.png
|
||||||
|
caption: "[Media] p-7-1da4a458 — Chapitre 4 — Histoire archicratique des
|
||||||
|
révolutions industrielles"
|
||||||
|
credit: ""
|
||||||
|
ts: 2026-02-25T19:11:32.634Z
|
||||||
|
fromIssue: 121
|
||||||
Reference in New Issue
Block a user