From 89db22f1eb84e25b8a78d3784f06e1b801554ebe Mon Sep 17 00:00:00 2001 From: Tero Halla-aho Date: Sun, 14 Dec 2025 00:33:46 +0200 Subject: [PATCH] Add helper to show latest registry image and deployed versions --- deploy/README.md | 1 + scripts/check-versions.sh | 96 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 scripts/check-versions.sh diff --git a/deploy/README.md b/deploy/README.md index 31da2fe..8d0608a 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -20,6 +20,7 @@ Deploy commands - Test: `./deploy/deploy-test.sh` - Staging (default): `./deploy/deploy-staging.sh` or `TARGET=staging ./deploy/deploy.sh` - Prod: `./deploy/deploy-prod.sh` +- Check running versions vs registry: `./scripts/check-versions.sh` (needs docker + registry creds and kubeconfig). Notes - Ensure `deploy/.last-image` exists (run `deploy/build.sh` first). diff --git a/scripts/check-versions.sh b/scripts/check-versions.sh new file mode 100755 index 0000000..e4195d4 --- /dev/null +++ b/scripts/check-versions.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Helper: print registry "latest" tag digest and show which image each environment is running. +# - Uses docker manifest inspect to read digests. +# - Uses kubectl to read the deployed container image per namespace. +# - Relies on deploy/env.sh for registry/repo/namespaces; will load secrets for registry auth if available. +# +# Usage: ./scripts/check-versions.sh + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +# shellcheck source=/dev/null +source "$ROOT_DIR/deploy/env.sh" + +# Load secrets (for REGISTRY_USERNAME/PASSWORD) if present. +if [[ -f "$ROOT_DIR/scripts/load-secrets.sh" ]]; then + # shellcheck source=/dev/null + source "$ROOT_DIR/scripts/load-secrets.sh" >/dev/null 2>&1 || true +fi + +# Prefer repo kubeconfig if none set. +if [[ -z "${KUBECONFIG:-}" && -f "$ROOT_DIR/creds/kubeconfig.yaml" ]]; then + export KUBECONFIG="$ROOT_DIR/creds/kubeconfig.yaml" +fi + +login_registry() { + if [[ -n "${REGISTRY_USERNAME:-}" && -n "${REGISTRY_PASSWORD:-}" ]]; then + docker login "$REGISTRY" -u "$REGISTRY_USERNAME" -p "$REGISTRY_PASSWORD" >/dev/null 2>&1 || true + fi +} + +manifest_digest() { + local image="$1" + local out + out="$( + { docker manifest inspect "$image" 2>/dev/null | python3 - <<'PY' +import json,sys +try: + raw=sys.stdin.read().strip() + if not raw: + raise SystemExit + data=json.loads(raw) +except Exception: + raise SystemExit +# Prefer amd64 manifest when multi-arch. +if "manifests" in data: + m=[m for m in data["manifests"] if m.get("platform",{}).get("architecture")=="amd64"] + if not m: + m=data["manifests"] + if m: + print(m[0].get("digest","")) +elif "config" in data and "digest" in data["config"]: + print(data["config"]["digest"]) +PY + } || true + )" + echo "$out" +} + +get_deployed_image() { + local namespace="$1" + kubectl -n "$namespace" get deploy "$DEPLOYMENT_NAME" -o jsonpath='{.spec.template.spec.containers[?(@.name=="'"$DEPLOYMENT_NAME"'")].image}' 2>/dev/null || true + echo +} + +login_registry + +LATEST_IMAGE="${REGISTRY}/${REGISTRY_REPO}:latest" +LATEST_DIGEST="$(manifest_digest "$LATEST_IMAGE")" + +echo "Registry latest: $LATEST_IMAGE" +echo " digest: ${LATEST_DIGEST:-n/a (docker unavailable or unauthorized)}" +if [[ -f "$ROOT_DIR/deploy/.last-image" ]]; then + echo "Local last built: $(cat "$ROOT_DIR/deploy/.last-image")" +fi +echo + +for row in "testing:$TEST_NAMESPACE" "staging:$STAGING_NAMESPACE" "prod:$PROD_NAMESPACE"; do + env_name="${row%%:*}" + ns="${row##*:}" + img="$(get_deployed_image "$ns")" + if [[ -z "$img" ]]; then + echo "Env $env_name ($ns): no image found (missing deploy?)" + continue + fi + digest="$(manifest_digest "$img")" + match="no" + if [[ -n "$LATEST_DIGEST" && -n "$digest" && "$LATEST_DIGEST" == "$digest" ]]; then + match="yes" + fi + echo "Env $env_name ($ns):" + echo " image: $img" + echo " digest: ${digest:-n/a}" + echo " matches latest: $match" +done