forked from heavy-duty/ceremony
feat: decide when merge-door releases resume
This commit is contained in:
parent
3104aac6f3
commit
153a408e10
2 changed files with 88 additions and 1 deletions
81
lib/preflight.sh
Executable file
81
lib/preflight.sh
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env bash
|
||||
# lib/preflight.sh — the merge door's resume decision, pure and exhaustively
|
||||
# tested (issue #273).
|
||||
#
|
||||
# A merge-door run creates the tag before the artifact hook and release. A
|
||||
# failed hook or publish therefore leaves a tag but no release. Re-running the
|
||||
# same merge commit must resume after that irreversible step; a published
|
||||
# release or a tag naming another commit must still refuse.
|
||||
#
|
||||
# Pure: no repository or forge reads. The workflow establishes four facts:
|
||||
#
|
||||
# VER the version being released
|
||||
# MERGE_SHA the commit this door would tag
|
||||
# TAG_SHAS object names returned for the direct and peeled tag refs,
|
||||
# newline-separated; empty means the tag is absent
|
||||
# RELEASED yes|no — whether a published release for VER exists
|
||||
#
|
||||
# Output: resume=yes or resume=no on stdout, notices to stdout, refusals to
|
||||
# stderr, return 1 on refusal.
|
||||
#
|
||||
# The decision table (this IS the spec — issue #273):
|
||||
#
|
||||
# | # | RELEASED | TAG_SHAS contains MERGE_SHA | result |
|
||||
# |---|----------|------------------------------|---------------------------|
|
||||
# | 1 | yes | either | REFUSE: already released |
|
||||
# | 2 | no | empty | resume=no: ordinary run |
|
||||
# | 3 | no | yes | resume=yes + resume NOTICE |
|
||||
# | 4 | no | non-empty, no | REFUSE: tag is elsewhere |
|
||||
|
||||
release_preflight() {
|
||||
local tag_sha sha
|
||||
|
||||
if [ -z "${VER:-}" ]; then
|
||||
printf '%s\n' "VER is empty — the caller failed to establish the release version. Refusing to decide — creating nothing." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ -z "${MERGE_SHA:-}" ]; then
|
||||
printf '%s\n' "MERGE_SHA is empty — the caller failed to establish the merge commit. Refusing to decide — creating nothing." >&2
|
||||
return 1
|
||||
fi
|
||||
if [ -z "${RELEASED:-}" ]; then
|
||||
printf '%s\n' "RELEASED is empty — the caller failed to establish whether release '$VER' exists. Refusing to decide — creating nothing." >&2
|
||||
return 1
|
||||
fi
|
||||
case "$RELEASED" in
|
||||
yes | no) ;;
|
||||
*)
|
||||
printf '%s\n' "RELEASED='$RELEASED' — expected yes or no. Refusing to decide — creating nothing." >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Row 1 comes first: deleting a tag under a standing release never makes
|
||||
# that release safe to recreate.
|
||||
if [ "$RELEASED" = yes ]; then
|
||||
printf '%s\n' "release '$VER' already exists — this release already happened; refusing to re-release, creating nothing." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Row 2: an absent tag is the ordinary first run.
|
||||
if [ -z "${TAG_SHAS:-}" ]; then
|
||||
printf '%s\n' 'resume=no'
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Row 3: compare each object name as a whole line. For an annotated tag the
|
||||
# direct ref names the tag object and the peeled ref names MERGE_SHA.
|
||||
while IFS= read -r sha; do
|
||||
if [ "$sha" = "$MERGE_SHA" ]; then
|
||||
printf '%s\n' "NOTICE: tag '$VER' already stands at this merge commit and no release exists — a previous run of this door tagged and then failed to publish. Resuming: the tag is not recreated; the artifact hook and the publish run."
|
||||
printf '%s\n' 'resume=yes'
|
||||
return 0
|
||||
fi
|
||||
done <<<"$TAG_SHAS"
|
||||
|
||||
# Row 4: the first object name is enough to diagnose the conflicting tag;
|
||||
# MERGE_SHA is printed beside it so the operator sees both sides.
|
||||
tag_sha="${TAG_SHAS%%$'\n'*}"
|
||||
printf '%s\n' "tag '$VER' already exists at $tag_sha but this run would tag $MERGE_SHA — a manual tag won the race, or it names a different commit; refusing to re-release, creating nothing. Delete that tag, or re-tag the merge commit." >&2
|
||||
return 1
|
||||
}
|
||||
|
|
@ -18,7 +18,13 @@ FOREIGN_SHA=2222222222222222222222222222222222222222
|
|||
# preflight <VER> <MERGE_SHA> <TAG_SHAS> <RELEASED> — run the pure decision
|
||||
# with exactly the four gathered facts in its environment.
|
||||
preflight() {
|
||||
VER="$1" MERGE_SHA="$2" TAG_SHAS="$3" RELEASED="$4" bash "$PREFLIGHT"
|
||||
(
|
||||
VER="$1" MERGE_SHA="$2" TAG_SHAS="$3" RELEASED="$4"
|
||||
export VER MERGE_SHA TAG_SHAS RELEASED
|
||||
# shellcheck source=lib/preflight.sh
|
||||
. "$PREFLIGHT"
|
||||
release_preflight
|
||||
)
|
||||
}
|
||||
|
||||
preflight_stdout() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue