mirror of https://github.com/garrytan/gstack.git
fix(pr-title): handle bare version titles without duplicating the prefix
gstack-pr-title-rewrite.sh anchored both its no-change case match
("v$NEW_VERSION "*) and its prefix-strip sed (/^v…+ /) on a trailing
space, so a title that is a bare version with no description fell through
to the prepend case and got a second prefix:
v1.2.3.4 + "v1.2.3.4" -> "v1.2.3.4 v1.2.3.4" (should be no change)
v1.2.3.4 + "v1.2.3" -> "v1.2.3.4 v1.2.3" (stale prefix kept)
This violated the helper's documented case 1 (no change) and case 2
(replace prefix) and its idempotency contract. It is reachable in CI:
.github/workflows/pr-title-sync.yml feeds the real PR title through the
helper and then `gh pr edit`s the result, so a version-only PR title (the
format ship/CHANGELOG uses for branch-ahead bumps) gets corrupted, and it
never self-heals (the duplicated form then matches case 1).
Match the bare "v$NEW_VERSION" form in the no-change case, strip an
existing prefix at a space OR end-of-string, and emit a bare new prefix
when the title had no description. Adds 3 regression tests (bare correct,
bare different, bare idempotency) that fail on main and pass with the fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cab774cced
commit
ea7e9448d6
|
|
@ -5,10 +5,18 @@
|
|||
# Output: corrected title on stdout.
|
||||
#
|
||||
# Rule: PR titles MUST start with v<NEW_VERSION>. Three cases:
|
||||
# 1. Already starts with "v<NEW_VERSION> " -> no change.
|
||||
# 2. Starts with a different "v<digits and dots> " prefix -> replace prefix.
|
||||
# 1. Already starts with "v<NEW_VERSION>" -> no change.
|
||||
# 2. Starts with a different "v<digits and dots>" prefix -> replace prefix.
|
||||
# 3. No version prefix -> prepend "v<NEW_VERSION> ".
|
||||
#
|
||||
# Each version prefix may be followed by a space (then a description) OR sit at
|
||||
# the end of the title as a bare version with no description (e.g. "v1.2.3", the
|
||||
# format ship/CHANGELOG uses for version-only bumps). Both forms must be handled
|
||||
# in cases 1 and 2, otherwise a bare version falls through to case 3 and gets a
|
||||
# second prefix prepended, e.g. "v1.2.3" -> "v1.2.3.4 v1.2.3". The CI workflow
|
||||
# .github/workflows/pr-title-sync.yml feeds real PR titles through this and then
|
||||
# `gh pr edit`s the result, so the duplicated title would be written back.
|
||||
#
|
||||
# The version-prefix regex matches two or more dot-separated digit segments
|
||||
# (covers v1.2, v1.2.3, v1.2.3.4) so the rule is portable across repos that
|
||||
# use 3-part or 4-part versions, but does NOT strip plain words like
|
||||
|
|
@ -33,12 +41,20 @@ fi
|
|||
|
||||
# Literal prefix match (case statement is glob-quoted by bash, but our
|
||||
# regex-validated NEW_VERSION has no glob metacharacters so this is safe).
|
||||
# Match both "v<NEW_VERSION> <description>" and a bare "v<NEW_VERSION>" title.
|
||||
case "$TITLE" in
|
||||
"v$NEW_VERSION "*)
|
||||
"v$NEW_VERSION "*|"v$NEW_VERSION")
|
||||
printf '%s\n' "$TITLE"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
REST=$(printf '%s' "$TITLE" | sed -E 's/^v[0-9]+(\.[0-9]+)+ //')
|
||||
printf 'v%s %s\n' "$NEW_VERSION" "$REST"
|
||||
# Strip an existing different version prefix whether it is followed by a space
|
||||
# (then a description) or sits at the end of the title (bare version).
|
||||
REST=$(printf '%s' "$TITLE" | sed -E 's/^v[0-9]+(\.[0-9]+)+( |$)//')
|
||||
if [ -n "$REST" ]; then
|
||||
printf 'v%s %s\n' "$NEW_VERSION" "$REST"
|
||||
else
|
||||
# Title was nothing but a (different) version prefix; emit the bare new one.
|
||||
printf 'v%s\n' "$NEW_VERSION"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -24,6 +24,23 @@ describe('gstack-pr-title-rewrite', () => {
|
|||
expect(rewrite('1.2.3.4', 'v1.2.3 feat: foo').stdout).toBe('v1.2.3.4 feat: foo');
|
||||
});
|
||||
|
||||
test('bare correct version (no description): no change, not duplicated', () => {
|
||||
// CHANGELOG/ship uses a version-only title for branch-ahead bumps. It must
|
||||
// stay as-is, not become "v1.2.3.4 v1.2.3.4".
|
||||
expect(rewrite('1.2.3.4', 'v1.2.3.4').stdout).toBe('v1.2.3.4');
|
||||
});
|
||||
|
||||
test('bare different version (no description): replaces, not duplicates', () => {
|
||||
// Must strip the stale prefix even with nothing after it, otherwise CI
|
||||
// writes back "v1.2.3.4 v1.2.3".
|
||||
expect(rewrite('1.2.3.4', 'v1.2.3').stdout).toBe('v1.2.3.4');
|
||||
});
|
||||
|
||||
test('idempotent on a bare version title', () => {
|
||||
const once = rewrite('1.2.3.4', 'v1.2.3').stdout;
|
||||
expect(rewrite('1.2.3.4', once).stdout).toBe(once);
|
||||
});
|
||||
|
||||
test('no version prefix: prepends', () => {
|
||||
expect(rewrite('1.2.3.4', 'feat: foo').stdout).toBe('v1.2.3.4 feat: foo');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue