Files
bztmon-site/scripts/bump-digest.sh
T
jwright 1c87af560d ci(bump-digest): force-push the ephemeral deploy branch (idempotent re-runs)
Re-running the same commit collided with the prior run's deploy/<sha> branch
(non-fast-forward reject). The branch is a disposable deploy artifact; main is
the protected human-merge gate, so force-push is safe and makes re-runs work.
2026-06-17 23:33:34 +10:00

80 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Open a digest-bump PR against the PRIVATE home-ops repo after an image is pushed.
# Called by CI (.gitea/workflows/deploy.yml) after scripts/build-image.sh push.
#
# Least-privilege: uses a deploy key scoped to ONLY home-ops, and a token that can
# open a PR. It NEVER pushes to main — main is branch-protected, human-merged.
#
# Required env (CI secrets):
# HOME_OPS_SSH_KEY - private deploy key with write to home-ops only
# GITEA_API - e.g. https://gitea.bztmon.org/api/v1 (PRIVATE instance)
# GITEA_TOKEN - token that can create a PR on home-ops
# Optional:
# HOME_OPS_REPO_SSH - default ssh://git@10.0.11.241:22/jwrong96/home-ops.git
# MANIFEST - path within home-ops to patch
set -euo pipefail
REGISTRY="${REGISTRY:-git.bztmon.com}"
IMAGE="${IMAGE:-jwright/bztmon-site}"
HOME_OPS_REPO_SSH="${HOME_OPS_REPO_SSH:-ssh://git@10.0.11.241:22/jwrong96/home-ops.git}"
MANIFEST="${MANIFEST:-kubernetes/apps/bztmon-site/bztmon-site.yaml}"
GITEA_API="${GITEA_API:-https://gitea.bztmon.org/api/v1}"
TAG="$(git rev-parse --short HEAD)"
DIGEST_FILE="${DIGEST_FILE:-${TMPDIR:-/tmp}/bztmon-site-$(id -un).digest}"
DIGEST="$(cat "${DIGEST_FILE}")"
REF="${REGISTRY}/${IMAGE}:${TAG}@${DIGEST}"
echo ">> new image ref: ${REF}"
# --- SSH for the home-ops deploy key --------------------------------------
export GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new"
KEYFILE="$(mktemp)"; trap 'rm -f "$KEYFILE"' EXIT
printf '%s\n' "${HOME_OPS_SSH_KEY}" > "$KEYFILE"; chmod 600 "$KEYFILE"
export GIT_SSH_COMMAND="ssh -i ${KEYFILE} -o StrictHostKeyChecking=accept-new"
WORK="$(mktemp -d)"
git clone --depth 1 "${HOME_OPS_REPO_SSH}" "${WORK}/home-ops"
cd "${WORK}/home-ops"
BRANCH="deploy/bztmon-site-${TAG}"
git switch -c "${BRANCH}"
# Replace the image: line for our image (matches any current tag@digest).
sed -i -E "s#(^\s*image:\s*)${REGISTRY}/${IMAGE}.*#\1${REF}#" "${MANIFEST}"
git --no-pager diff -- "${MANIFEST}"
git config user.name "bztmon-site CI"
git config user.email "ci@bztmon.com"
git commit -am "bztmon-site: deploy ${TAG}"
# Force-push: the deploy branch name is deterministic (per-commit), so a RE-RUN of the same
# commit would otherwise hit a non-fast-forward reject ("fetch first") against the stale branch
# from the prior run. The branch is an ephemeral, disposable deploy artifact (main is the gate,
# protected, human-merged) → force is safe and makes re-runs idempotent.
git push --force origin "${BRANCH}"
# --- PR (never auto-merge; BEST-EFFORT) ------------------------------------
# The branch push above IS the deploy artifact — the rollout is ready regardless of the PR.
# Opening the PR is pure convenience and must NEVER hang or fail the job. (It used to: a
# no-timeout curl to the PRIVATE Gitea API tripped split-horizon DNS from the runner and hung
# the step for ~10min before failing the whole run.) So: bound the curl, treat any failure as
# non-fatal, and always exit 0 — a green run means "image built + bump branch pushed".
# NB: dedicated var name (NOT GITEA_TOKEN) — Gitea auto-injects GITEA_TOKEN into every job.
PR_URL="https://gitea.bztmon.org/jwrong96/home-ops/compare/main...${BRANCH}"
if [[ -n "${HOMEOPS_PR_TOKEN:-}" ]]; then
if curl -fsS --connect-timeout 10 --max-time 30 -X POST "${GITEA_API}/repos/jwrong96/home-ops/pulls" \
-H "Authorization: token ${HOMEOPS_PR_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"bztmon-site: deploy ${TAG}\",\"body\":\"Automated digest bump.\\n\\nImage: \`${REF}\`\\n\\nMerge to roll out via ArgoCD.\"}"; then
echo ">> PR opened for ${BRANCH}"
else
echo ">> WARNING: PR auto-open failed/unreachable (non-fatal) — branch is pushed, open it manually:"
echo ">> ${PR_URL}"
fi
else
echo ">> branch ${BRANCH} pushed (image ${REF})."
echo ">> open the PR to roll out: ${PR_URL}"
fi
# The deploy artifact (the bump branch) is pushed — the optional PR step never reds the run.
exit 0