3 Commits

Author SHA1 Message Date
librelad
cdeb2d1658 feat(updater): per-app UPDATE_TYPE, automatic by default
Adds the decision half of the app updater. Detection (P2) and the
snapshot-first apply/revert (P3) were already real, but nothing ever
pressed the button — every update waited for a click.

  CFG_<APP>_UPDATE_TYPE=auto|manual   per app, default auto (33 templates)
  CFG_UPDATER_AUTO=true|false         master switch, default true

updaterAppPolicy resolves the two the way backupResolveStrategy already
resolves backup strategy: the global switch can only make things more
manual. updaterApplyAuto runs at the end of `updater check` and enqueues
the ordinary updater_apply task for each auto app that has an update —
never applies inline, so an automatic update is the same code path, task
log, History entry and Roll back button as a manual one.

Safety: each attempt stamps its target digest under generated/auto/, so a
build that fails is rolled back and then left alone rather than retried on
every scan; in-flight updater tasks are skipped so scans can't stack.

Tracked end to end: updates.json carries each app's resolved update_type,
History entries carry trigger=manual|auto. The WebUI says whether updates
install themselves, chips only the apps that opted out, labels automatic
history, and — since an auto app's pending update needs no decision — keeps
it off the Overview board's "Needs action" view.

Also fixes artifactApplyAuto enqueueing without --detach: it runs inside
the single-threaded task processor's own poll, so following the new task in
the foreground waits for a task that cannot start until it returns.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:22:04 +01:00
librelad
56102ac5c0 feat(updater): P1b — CFG_<APP>_VERSION drives the anchor image tag
Add a `#LIBREPORTAL|<APP>_VERSION_TAG|<current-tag>` sentinel to each app's
anchor (`<slug>-service`) image line, so a `CFG_<APP>_VERSION` config drives
that tag through the existing tagging system — the config becomes the source,
the compose tag is derived (like ports/IPs/domains already are). This is the
"install/pin a specific version" knob.

- Placeholder is the literal current tag (e.g. `31-fpm-alpine`), NOT a `*_DATA`
  token: an unset var leaves the line untouched (inert comment, keeps the real
  tag) and never trips the up_app stale-tag scanner.
- Only the anchor line is tagged (sidecars mariadb/redis/nginx stay
  tracked-by-digest, not user-version-picked). ollama correctly targets
  `ollama/ollama`, not the companion open-webui.
- Untagged anchors normalized to `:latest` (semantic no-op) so they're
  templatable too. The manager (libreportal) is skipped — it updates via its
  release channel, not a docker tag.

32 apps wired. Verified: CFG_NEXTCLOUD_VERSION=32 → `nextcloud:32` (prefix
preserved, idempotent, sidecars untouched); all compose files still valid YAML.
Inert until a version config is set, so no behaviour change on existing installs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-07-17 23:13:57 +01:00
librelad
f4913422fb refactor(catalog): rename the 'marketplace' app to 'libreportal_catalog'
'Marketplace' read as a place to buy things; this is a free, self-hosted app
catalog, so rename the app to LibrePortal Catalog. Slug is libreportal_catalog
(underscore — the slug becomes a CFG_<SLUG>_ prefix and a bash identifier via
declare "${app_name}=i"; a dash would break install). Docker-facing names use
dashes (libreportal-catalog-service / hostname libreportal-catalog), declared
explicitly in the PORT config + compose, not derived from the slug.

- containers/marketplace/ -> containers/libreportal_catalog/ (+ .config, .svg, hook file)
- CFG_MARKETPLACE_* -> CFG_LIBREPORTAL_CATALOG_*, APP_NAME + TITLE + PORT_1 updated
- install hook fn marketplace_install_post_setup -> libreportal_catalog_install_post_setup
- served browse site reworded Marketplace -> Catalog, icon refs updated
- regenerated function_manifest.sh (autoload stub now points at the new file)

Not installed yet, so there is no live config/container/volume to migrate — the
cheapest moment to rename. The client-side registry ('View full page on the
marketplace') wording is a separate subsystem and left unchanged for now.

Signed-off-by: librelad <librelad@digitalangels.vip>

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 20:25:21 +01:00