Fix health endpoint, align with the documented manual runbook
The health router is mounted at prefix="/api" in domaindingo's main.py, so /health 404s. Checking it would have failed every deploy and rolled back a perfectly good image. Also adopts three conventions from the vault's DomainDingo Development note: recreate a single named service (--no-deps --force-recreate), validate with compose config --quiet before touching the running container, and write the rollback record in the documented format and location.
This commit is contained in:
+61
-18
@@ -236,14 +236,19 @@ readonly DEPLOY_IMAGE
|
||||
|
||||
# --------------------------------------------- remember what is running now ---
|
||||
|
||||
PREVIOUS_IMAGE="$(
|
||||
container_image="$(docker inspect --format '{{.Image}}' "$CD_CONTAINER" 2>/dev/null || true)"
|
||||
[[ -n "$container_image" ]] && image_digest_ref "$container_image" || true
|
||||
)"
|
||||
readonly PREVIOUS_IMAGE
|
||||
RunningImageId="$(docker inspect --format '{{.Image}}' "${CD_CONTAINER}" 2>/dev/null || true)"
|
||||
PREVIOUS_IMAGE=""
|
||||
PREVIOUS_REVISION=""
|
||||
if [[ -n "${RunningImageId}" ]]; then
|
||||
PREVIOUS_IMAGE="$(image_digest_ref "${RunningImageId}")"
|
||||
PREVIOUS_REVISION="$(docker image inspect \
|
||||
--format '{{index .Config.Labels "org.opencontainers.image.revision"}}' \
|
||||
"${RunningImageId}" 2>/dev/null || true)"
|
||||
fi
|
||||
readonly PREVIOUS_IMAGE PREVIOUS_REVISION
|
||||
|
||||
if [[ -n "$PREVIOUS_IMAGE" ]]; then
|
||||
log "current ${PREVIOUS_IMAGE}"
|
||||
if [[ -n "${PREVIOUS_IMAGE}" ]]; then
|
||||
log "current ${PREVIOUS_IMAGE} (revision ${PREVIOUS_REVISION:0:12})"
|
||||
else
|
||||
log "current (nothing running -- first deploy, or container absent)"
|
||||
fi
|
||||
@@ -251,15 +256,44 @@ fi
|
||||
# ----------------------------------------------------------------- deploy ---
|
||||
|
||||
compose_up() {
|
||||
local image="$1"
|
||||
# `up -d` recreates only what actually changed. `down` is deliberately not
|
||||
# used here: it causes avoidable downtime, and `down -v` would destroy the
|
||||
# data volumes these stacks depend on.
|
||||
( cd "$CD_STACK_DIR" \
|
||||
&& env "${CD_IMAGE_ENV_VAR}=${image}" \
|
||||
"${CD_PULL_POLICY_ENV_VAR}=missing" \
|
||||
timeout "$CD_COMPOSE_TIMEOUT_SECONDS" \
|
||||
docker compose -f "$CD_COMPOSE_FILE" -p "$CD_COMPOSE_PROJECT" up -d --no-build )
|
||||
local Image="$1"
|
||||
# Matches the manual runbook in the vault's "DomainDingo Development" note:
|
||||
# recreate exactly one service, leave its dependencies alone, and never run
|
||||
# `docker compose down` -- that causes avoidable downtime, and `down -v`
|
||||
# would destroy the bind-mounted data these stacks depend on.
|
||||
#
|
||||
# `--pull always` is deliberately absent: the image is already pinned to a
|
||||
# digest and pulled, so there is nothing left to resolve.
|
||||
( cd "${CD_STACK_DIR}" \
|
||||
&& env "${CD_IMAGE_ENV_VAR}=${Image}" \
|
||||
"${CD_PULL_POLICY_ENV_VAR}=never" \
|
||||
timeout "${CD_COMPOSE_TIMEOUT_SECONDS}" \
|
||||
docker compose -f "${CD_COMPOSE_FILE}" -p "${CD_COMPOSE_PROJECT}" \
|
||||
up -d --no-build --no-deps --force-recreate "${CD_COMPOSE_SERVICE}" )
|
||||
}
|
||||
|
||||
compose_validate() {
|
||||
local Image="$1"
|
||||
( cd "${CD_STACK_DIR}" \
|
||||
&& env "${CD_IMAGE_ENV_VAR}=${Image}" \
|
||||
"${CD_PULL_POLICY_ENV_VAR}=never" \
|
||||
docker compose -f "${CD_COMPOSE_FILE}" -p "${CD_COMPOSE_PROJECT}" \
|
||||
config --quiet )
|
||||
}
|
||||
|
||||
# Write the rollback record where the manual runbook looks for it, in the same
|
||||
# format, so an operator following that note can recover from an automated
|
||||
# deploy without knowing this tool exists.
|
||||
write_rollback_record() {
|
||||
local Image="$1" Revision="$2" Dir="${CD_STACK_DIR}/${CD_ROLLBACK_RECORD_DIR}"
|
||||
local Record="${Dir}/${CD_COMPOSE_SERVICE}-rollback-$(date -u +%Y%m%d-%H%M%S).env"
|
||||
|
||||
[[ -d "${Dir}" ]] || { warn "no rollback record directory at ${Dir}"; return 0; }
|
||||
|
||||
( umask 077
|
||||
printf 'DD_ROLLBACK_IMAGE=%s\nDD_ROLLBACK_REVISION=%s\nDD_ROLLBACK_CAPTURED_AT=%s\n' \
|
||||
"${Image}" "${Revision}" "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" > "${Record}" )
|
||||
log "rollback recorded at ${Record}"
|
||||
}
|
||||
|
||||
check_health() {
|
||||
@@ -289,14 +323,23 @@ sys.exit(0 if str(data.get(key, "")).lower() == want.lower() else 1)
|
||||
}
|
||||
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
log "dry run: would run docker compose up -d with ${CD_IMAGE_ENV_VAR}=${DEPLOY_IMAGE}"
|
||||
log "dry run: would recreate service ${CD_COMPOSE_SERVICE} with ${CD_IMAGE_ENV_VAR}=${DEPLOY_IMAGE}"
|
||||
log "dry run: would health-check ${CD_HEALTH_URL}"
|
||||
log "dry run complete -- no changes made"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Catch a broken compose file or a bad interpolation before the running
|
||||
# container is touched.
|
||||
if ! compose_validate "${DEPLOY_IMAGE}"; then
|
||||
notify fail "compose config is invalid for ${SHA:0:12} -- nothing was changed"
|
||||
die "docker compose config failed; the running stack was not touched"
|
||||
fi
|
||||
|
||||
[[ -n "${PREVIOUS_IMAGE}" ]] && write_rollback_record "${PREVIOUS_IMAGE}" "${PREVIOUS_REVISION}"
|
||||
|
||||
log "deploying ${DEPLOY_IMAGE}"
|
||||
if ! compose_up "$DEPLOY_IMAGE"; then
|
||||
if ! compose_up "${DEPLOY_IMAGE}"; then
|
||||
notify fail "docker compose up failed for ${SHA:0:12} -- stack left as-is"
|
||||
die "docker compose up failed"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user