diff --git a/.gitea/workflows/deploy-lib.sh b/.gitea/workflows/deploy-lib.sh index d765542..1f0de86 100644 --- a/.gitea/workflows/deploy-lib.sh +++ b/.gitea/workflows/deploy-lib.sh @@ -227,15 +227,19 @@ owned_registry_workloads() { # mark every workload stale forever and restart the whole cluster on every deploy. registry_digest() { local arch - arch="$(kubectl get nodes -o jsonpath='{.items[0].status.nodeInfo.architecture}' 2>/dev/null)" + arch="$(kubectl get nodes -o jsonpath='{.items[0].status.nodeInfo.architecture}' 2>/dev/null || true)" [ -n "$arch" ] || arch=amd64 + # The || true is load-bearing. Every caller runs under set -euo pipefail, and + # pipefail reports the rightmost non-zero stage, so a ref the registry does not + # have would abort the caller at the assignment instead of yielding an empty + # string. The callers check for empty themselves and report it by name. docker manifest inspect "$1" 2>/dev/null \ | jq -r --arg arch "$arch" ' .manifests[]? | select(.platform.os == "linux" and .platform.architecture == $arch) | .digest ' 2>/dev/null \ - | head -1 + | head -1 || true } # Rewrites our own images to immutable digests on the way into the cluster. @@ -644,12 +648,18 @@ stage_apply_k8s() { if [ "${#other_files[@]}" -gt 0 ]; then log "Applying resources (${#other_files[@]} files, our images pinned to digests)" for m in "${other_files[@]}"; do - render_pinned <"$m" | kubectl apply "${prune_opts[@]}" -f - + if ! render_pinned <"$m" | kubectl apply "${prune_opts[@]}" -f -; then + echo "ERROR: apply failed for ${m#"$REPO"/}" >&2 + exit 1 + fi done fi for k in ${KUSTOMIZE_APPS[@]+"${KUSTOMIZE_APPS[@]}"}; do log "Applying kustomize app: ${k#"$REPO"/} (our images pinned to digests)" - kubectl kustomize "$k" | render_pinned | kubectl apply -f - + if ! kubectl kustomize "$k" | render_pinned | kubectl apply -f -; then + echo "ERROR: apply failed for kustomize app ${k#"$REPO"/}" >&2 + exit 1 + fi done if [ -f "$REPO/userbot/k8s/active" ]; then log "userbot panel hook"