em dashes out of skeleton copy (titles use ' - ', prose reworded); split hardening after review: poll errors name the failing repo, failed release is not retried until a new commit, link-content checks all three dirs, editor write-access note, two-repo unit descriptions and comments

This commit is contained in:
2026-09-03 19:41:56 +02:00
parent 13f945fbf3
commit 751fd0ec79
21 changed files with 54 additions and 42 deletions
+4
View File
@@ -65,6 +65,10 @@ missing). Everything else runs inside containers.
10. **[R]** Verify: `curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/`
and `journalctl --user -u ctao-portal-build -n 20` (shows measured build times).
Editor accounts need WRITE access to `ctao/content` (Gitea → repo →
Collaborators, or a team) — public read alone lets them sign in but every
save fails.
## CMS sign-in (Sveltia ↔ Gitea OAuth)
- Gitea OAuth2 app (PKCE, `confidential_client=false`, no secret) with
+13 -8
View File
@@ -43,18 +43,22 @@ head_of() {
code_sha=$(head_of "$CODE_REPO")
content_sha=$(head_of "$CONTENT_REPO")
# Gitea down/unreachable is a transient, not a unit failure — exit 0 quietly
# instead of painting the journal red every 10 s.
for sha in "$code_sha" "$content_sha"; do
if [[ ! "$sha" =~ ^[0-9a-f]{40}$ ]]; then
echo "poll failed (gitea unreachable?) — skipping this tick"
exit 0
fi
done
# instead of painting the journal red every 10 s. Name the repo: a 404 here
# also means "repo/branch missing or renamed", not just "Gitea down".
[[ "$code_sha" =~ ^[0-9a-f]{40}$ ]] || { echo "poll failed for $CODE_REPO@$BRANCH (gitea down, or repo/branch missing) — skipping"; exit 0; }
[[ "$content_sha" =~ ^[0-9a-f]{40}$ ]] || { echo "poll failed for $CONTENT_REPO@$BRANCH (gitea down, or repo/branch missing) — skipping"; exit 0; }
release="${code_sha:0:12}-${content_sha:0:12}" # code+content pin the release
# Skip only if this pair is both recorded AND still present in releases/
# (a deleted release dir must trigger a rebuild, not an eternal skip).
[[ "$release" == "$(cat "$BASE/state/last-built" 2>/dev/null)" \
&& -d "$BASE/releases/$release" ]] && exit 0
# A release that already failed is not retried until either repo moves —
# otherwise one bad commit (e.g. broken frontmatter) turns into a full
# rebuild every 10 s on a shared VM. The failure is loud once, then quiet.
if [[ "$release" == "$(cat "$BASE/state/last-failed" 2>/dev/null)" ]]; then
echo "skipping $release — build failed before; push a fix to retry"
exit 0
fi
echo "building code=$code_sha content=$content_sha"
t0=$(date +%s)
@@ -106,7 +110,8 @@ podman run --rm --network="$BUILD_NETNS" --memory=1g \
npm run build
rm -rf "../releases/$RELEASE"
cp -a dist "../releases/$RELEASE"
'
' || { echo "$release" > "$BASE/state/last-failed"; echo "BUILD FAILED for $release (see above) — will not retry until a new commit"; exit 1; }
rm -f "$BASE/state/last-failed"
# --- 3. Atomic publish: symlink flip via rename(2) — no half-published moment.
# mv -T is GNU (the target host is Rocky); when testing on macOS put a
+1 -1
View File
@@ -4,7 +4,7 @@
# activate a service that is still running.
[Unit]
Description=CTAO portal demo — rebuild if the content repo has new commits
Description=CTAO portal demo — rebuild if the code or content repo has new commits
[Service]
Type=oneshot
+1 -1
View File
@@ -6,7 +6,7 @@
# OnBootSec covers reboot. Enable: systemctl --user enable --now ctao-portal-build.timer
[Unit]
Description=CTAO portal demo — poll the content repo every 10 s
Description=CTAO portal demo — poll the code and content repos every 10 s
[Timer]
OnActiveSec=5