fix: refuse release PRs that strand target fragments #255
1 changed files with 37 additions and 0 deletions
|
|
@ -33,6 +33,12 @@ set -euo pipefail
|
|||
# no '## ' heading, and changelog_section extracts the body below HEAD's
|
||||
# heading — so the date HEAD stamped into its heading never enters the
|
||||
# comparison, and a date difference can never masquerade as a prose one.
|
||||
#
|
||||
# This guard narrows, but cannot close, the target-movement window: it sees a
|
||||
# fragment present when CI reads the target ref, but one can still land after
|
||||
# the final run and before merge. Requiring release PRs to be up to date with
|
||||
# their target branch before merge is the repository setting that closes that
|
||||
# residual window (#253).
|
||||
|
||||
base_ref="${1:-${CHANGELOG_ASSEMBLED_BASE:-origin/main}}"
|
||||
changelog="${2:-${CHANGELOG:-CHANGELOG.md}}"
|
||||
|
|
@ -169,6 +175,37 @@ frag_count="$(printf '%s' "$base_frags" | grep -c . || true)"
|
|||
|
||||
failures=0
|
||||
|
||||
# Refusal: the target branch gained a fragment after this release PR's merge
|
||||
# base, so the ceremony could not have consumed it. Merging this tree would
|
||||
# strand that fragment for the next release and misattribute when it shipped.
|
||||
stranded=""
|
||||
while IFS= read -r -d '' entry; do
|
||||
meta="${entry%%$'\t'*}"
|
||||
path="${entry#*$'\t'}"
|
||||
otype="$(printf '%s\n' "$meta" | awk '{ print $2 }')"
|
||||
name="${path##*/}"
|
||||
case "$otype:$name" in
|
||||
blob:README.md) ;;
|
||||
blob:*.md)
|
||||
if ! printf '%s' "$base_frags" | grep -Fxq "$path"; then
|
||||
stranded="${stranded} ${path}"$'\n'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < <(git ls-tree -z "$base_ref" -- "$dir/")
|
||||
if [ -n "$stranded" ]; then
|
||||
{
|
||||
echo "changelog-assembled: fragment(s) on target '$base_ref' were not consumed by this release PR:"
|
||||
echo
|
||||
printf '%s' "$stranded"
|
||||
echo
|
||||
echo " Merging now would strand these entries for the next release and"
|
||||
echo " misattribute when they shipped."
|
||||
echo " Fix: rebase onto the target head and re-run bin/changelog-assemble '$ver'."
|
||||
} >&2
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
|
||||
# Refusal: a fragment the ceremony consumed is still present on HEAD. The
|
||||
# ceremony deletes exactly what it assembles (#112) — a fragment that
|
||||
# survives its own release sits in the directory and is assembled AGAIN
|
||||
|
|
|
|||
Loading…
Reference in a new issue