#!/usr/bin/env bash # pi-devbox-version — show which pi-devbox image build is running. # # WHY THIS EXISTS # The image bakes ground-truth build info into /etc/pi-devbox/build-manifest.json # at `docker build` time (see Dockerfile.variant): the release tag, build date, # source commit, live `pi --version` at build time, and the actual checked-out # commit of every /opt component clone. That answers "what image am I running?" # — but only if you know to go look for the file. This wraps it into one # command, prints it human-first at container start (see entrypoint-user.sh), # and stays available on demand for the rest of the session. # # USAGE # pi-devbox-version human-readable summary (default) # pi-devbox-version --json raw manifest JSON (for scripting) # pi-devbox-version --quiet one-line "release_tag (source_revision)" form # # EXIT STATUS # 0 on success. 1 if the manifest is missing (e.g. an image built before # this file existed, or a non-pi-devbox base) — prints a short notice # to stderr rather than failing silently. set -euo pipefail MANIFEST=/etc/pi-devbox/build-manifest.json MODE="human" case "${1:-}" in --json) MODE="json" ;; --quiet|-q) MODE="quiet" ;; --help|-h) sed -n '2,20p' "$0" | sed 's/^# \?//' exit 0 ;; esac if [ ! -f "$MANIFEST" ]; then echo "pi-devbox-version: no build manifest at $MANIFEST" >&2 echo " (image predates the manifest, or this isn't a pi-devbox image)" >&2 exit 1 fi if ! command -v jq >/dev/null 2>&1; then echo "pi-devbox-version: jq not found; dumping raw manifest instead" >&2 cat "$MANIFEST" exit 0 fi if [ "$MODE" = "json" ]; then cat "$MANIFEST" exit 0 fi release_tag=$(jq -r '.release_tag' "$MANIFEST") build_date=$(jq -r '.build_date' "$MANIFEST") source_rev=$(jq -r '.source_revision' "$MANIFEST") pi_version_baked=$(jq -r '.pi_version' "$MANIFEST") if [ "$MODE" = "quiet" ]; then printf '%s (%s)\n' "$release_tag" "${source_rev:0:7}" exit 0 fi # Live drift check: has `pi` been upgraded since this container was built? # (image is immutable, but a volume-persisted ~/.pi could in theory shadow # the baked binary — this stays honest rather than trusting the manifest # blindly, same "ground truth over intent" spirit as how the manifest # itself is generated in Dockerfile.variant.) pi_version_live="" if command -v pi >/dev/null 2>&1; then pi_version_live=$(pi --version 2>/dev/null | head -n1 | tr -d '\r\n') fi printf 'pi-devbox %s\n' "$release_tag" printf ' built: %s (source %s)\n' "$build_date" "${source_rev:0:12}" if [ -n "$pi_version_live" ] && [ "$pi_version_live" != "$pi_version_baked" ]; then printf ' pi: %s \033[33m(baked as %s — drift detected)\033[0m\n' "$pi_version_live" "$pi_version_baked" else printf ' pi: %s\n' "${pi_version_live:-$pi_version_baked}" fi printf ' components:\n' jq -r '.components | to_entries[] | select(.value != null) | " \(.key): \(.value[0:12])"' "$MANIFEST"