open_notebook/scripts/check_updates.sh
dschlueter 4805fe75ed Pin images by digest; add update, smoke-test and status scripts
Goal: at every session start, run exactly the application the repo says — and be able
to move to a new upstream release deliberately, with a way back.

The old setup (v1-latest + pull_policy: always) was unreliable in both directions.
`docker compose up -d` silently pulled a new application, including an irreversible
SurrealDB schema migration, while a reboot (restart: always) or `docker compose start`
kept running the old image without pulling anything. The running version was effectively
unpredictable.

Note v1-latest tracks releases, not main: the current image (v1.10.0, 2026-06-18) IS the
latest release — the repo being "ahead" is unreleased code, which is explicitly not
wanted here. So this is about guaranteeing and detecting, not catching up.

- docker-compose.yml: both images pinned by digest, pull_policy: missing.
- scripts/check_updates.sh: reports running version/digest vs the latest release and
  registry digest. Changes nothing; meant for the session-start ritual.
- scripts/update_stack.sh: resolve new digest -> stop -> back up surreal_data,
  notebook_data and docker-compose.yml -> repin -> start -> smoke test -> roll back data
  AND compose file if the smoke test fails. The data backup is the point: the app migrates
  the DB on startup and an older app cannot read a migrated DB, so a bad update would
  otherwise be a one-way door. tar runs inside a container because the data dirs are
  root-owned and the host user cannot restore over them.
- scripts/smoke_test.sh: checks what actually breaks here, not just "does it start".
  Every local adaptation leans on upstream internals and can break silently: the
  prompts/podcast directory mount masks the image's directory (a new template upstream
  would be invisible), config/content_core.yaml freezes content-core's defaults (because
  CCORE_CONFIG_PATH replaces rather than merges), and the env-var workarounds depend on
  current content-core/esperanto/podcast_creator behaviour. So it verifies those
  assumptions explicitly, plus API, TTS audio, STT and a real YouTube transcript.

Both scripts read the digest from the lfnovo/open_notebook line specifically. A naive
"first sha256 in the file" grep matches surrealdb (listed first) — caught while testing:
check_updates.sh falsely reported an update, and update_stack.sh would have rewritten the
database image instead of the application.

Verified: smoke test green against the current stack, and red (exit 1) when failures are
injected (dead TTS port, removed template variable). Backup/restore mechanics exercised
separately: 44 MB in 3.3s, restore yields 13 DB files and 91 notebook files. The update
path itself cannot be exercised end to end until a newer image exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 14:12:31 +02:00

57 lines
2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Zeigt, ob es ein neues Open-Notebook-Release gibt. Aendert NICHTS.
#
# Gedacht fuer den Sitzungsstart: Du siehst, worauf du laeufst und ob etwas Neues da
# ist — und entscheidest selbst, wann du migrierst (./scripts/update_stack.sh).
# Bewusst kein Auto-Update: ein Image-Update migriert die Datenbank und kann unsere
# Anpassungen brechen (siehe scripts/smoke_test.sh).
set -uo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO"
TAG="lfnovo/open_notebook:v1-latest"
# Gezielt aus der open_notebook-Zeile: ein blindes grep auf den ersten Digest der Datei
# erwischt surrealdb (steht weiter oben) und vergleicht dann Aepfel mit Birnen.
pinned="$(grep -oP 'lfnovo/open_notebook\S*@\Ksha256:[0-9a-f]+' docker-compose.yml | head -1)"
running_ver="$(docker compose exec -T open_notebook grep -m1 '^version' /app/pyproject.toml 2>/dev/null |
grep -oP '(?<=")[^"]+' || echo '?')"
echo "Laeuft gerade"
echo " Version : ${running_ver}"
echo " Digest : ${pinned:-(nicht gepinnt!)}"
echo
echo "Verfuegbar"
latest_rel="$(curl -sf -m 10 https://api.github.com/repos/lfnovo/open-notebook/releases/latest |
python3 -c "import json,sys;d=json.load(sys.stdin);print(d['tag_name'],'vom',d['published_at'][:10])" 2>/dev/null)"
echo " Release : ${latest_rel:-(GitHub nicht erreichbar)}"
remote="$(docker buildx imagetools inspect "$TAG" --format '{{.Manifest.Digest}}' 2>/dev/null)"
if [ -z "$remote" ]; then
echo " Image : (Registry nicht erreichbar)"
exit 0
fi
echo " Image : $remote"
echo
if [ "$remote" = "$pinned" ]; then
echo "Du laeufst auf dem aktuellen Release. Nichts zu tun."
exit 0
fi
cat <<EOF
NEUES IMAGE VERFUEGBAR.
gepinnt : $pinned
neu : $remote
Update mit Backup, Rauchtest und Rollback:
./scripts/update_stack.sh
Vorher lohnt ein Blick in die Release-Notes — vor allem auf Aenderungen an den
Podcast-Vorlagen, an content-core und an der Datenbank:
https://github.com/lfnovo/open-notebook/releases
EOF
exit 0