#!/bin/bash # Artifact command handler — `libreportal artifact ` # --------------------------------------------------------------------------- # Dispatched automatically by cli_initialize.sh (category -> cliHandleArtifactCommands). # # The unified distribution primitive. The READ side (`index`/`applied`) fetches + # verifies the team-signed artifact index (hotfixes today; apps/themes/components # later — all one envelope) and lists what's available/applied; it changes nothing, # so — like `updater check` — it runs directly. The state-changing `apply`/`revert` # verbs route through the TASK system (snapshot → bounded declarative ops → # auto-rollback → History), never a mutating API. See docs/roadmap/updates-and- # distribution.md and cli_artifact_apply.sh. cliHandleArtifactCommands() { local sub="$initial_command2" local id="$initial_command3" # Lazy-loader gap: ensure the read primitives + apply pipeline are defined. # These are new files; the array/manifest regen self-heals them on deploy, # but this covers the window before that. Source CHECKED — a missing/corrupt # file must surface a clear error, not degrade to a bare "command not found". if ! declare -F lpFetchIndex >/dev/null 2>&1; then local _f for _f in source/fetch.sh source/artifacts.sh; do if [[ ! -f "$install_scripts_dir/$_f" ]] || ! source "$install_scripts_dir/$_f"; then isError "artifact: failed to load the read pipeline ($_f) — try: libreportal regen"; return 1 fi done fi if ! declare -F artifactApply >/dev/null 2>&1; then local _af="cli/commands/artifact/cli_artifact_apply.sh" if [[ ! -f "$install_scripts_dir/$_af" ]] || ! source "$install_scripts_dir/$_af"; then isError "artifact: failed to load the apply pipeline ($_af) — try: libreportal regen"; return 1 fi fi case "$sub" in ""|"index"|"list") artifactListIndex ;; "applied") artifactListApplied ;; "apply") if [[ -z "$id" ]]; then isError "Usage: libreportal artifact apply "; return 1; fi if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then artifactApply "$id" else cliTaskRun "libreportal artifact apply $id" "artifact_apply" "$id" "" fi ;; "revert"|"rollback") if [[ -z "$id" ]]; then isError "Usage: libreportal artifact revert "; return 1; fi if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then artifactRevert "$id" else cliTaskRun "libreportal artifact revert $id" "artifact_revert" "$id" "" fi ;; *) cliShowArtifactHelp ;; esac } # List the applied hotfixes (read-only) from the per-id applied records. artifactListApplied() { isHeader "Applied hotfixes" local dir; dir="${containers_dir%/}/libreportal/frontend/data/updater/generated/applied" if ! compgen -G "$dir/*.json" >/dev/null 2>&1; then isSuccessful "0 hotfixes applied." return 0 fi local n=0 f id title app for f in "$dir"/*.json; do n=$((n+1)) if command -v jq >/dev/null 2>&1; then id="$(jq -r '.id' "$f" 2>/dev/null)"; title="$(jq -r '.title // ""' "$f" 2>/dev/null)"; app="$(jq -r '.app // ""' "$f" 2>/dev/null)" echo " • $id${app:+ [$app]} — $title" else echo " • $(basename "$f" .json)" fi done isSuccessful "$n hotfix(es) applied. Revert with: libreportal artifact revert " } # Fetch + verify the signed index and print a human summary. Read-only. artifactListIndex() { isHeader "Artifact index ($(lpReleaseChannel))" local json if ! json="$(lpFetchIndex)"; then isError "Could not fetch or verify the artifact index from $(lpArtifactIndexUrl)." isNotice "Nothing is published yet, or the channel is unreachable. (This is expected before the first index ships.)" return 1 fi local serial generated_at serial="$(_lpJsonNum "$json" index_serial)" generated_at="$(lpIndexTop generated_at "$json")" # Report the ACTUAL signature state — never claim "verified" when the feed was # only accepted because signing isn't activated (dev/placeholder key). if [[ "$LP_INDEX_SIGSTATE" == "verified" ]]; then isNotice "Signed + verified. serial=${serial:-?} generated=${generated_at:-?}" else isNotice "UNSIGNED (signing not activated — dev/placeholder key). serial=${serial:-?} generated=${generated_at:-?}" fi local ids; ids="$(lpIndexArtifactIds "$json")" if [[ -z "$ids" ]]; then isSuccessful "0 artifacts available — the index is empty (nothing to apply)." return 0 fi local n=0 id obj title type sev while IFS= read -r id; do [[ -z "$id" ]] && continue n=$((n + 1)) obj="$(lpArtifactById "$json" "$id")" if [[ -n "$obj" ]]; then title="$(_lpJsonStr "$obj" title)" type="$(_lpJsonStr "$obj" type)" sev="$(_lpJsonStr "$obj" severity)" echo " • [${type:-?}/${sev:-info}] $id — ${title:-}" else echo " • $id" fi done <<< "$ids" isSuccessful "$n artifact(s) available." }