mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 20:36:23 +08:00
fix(scripts): use case-sensitive match for acronym retention in PS branch names (#3130)
The branch-name generator keeps a short (<3 char) word only when it appears in uppercase in the description, treating it as an acronym (the comment says as much). The bash script uses a case-sensitive grep for this, but the PowerShell script used -match, which is case-insensitive by default. As a result every short non-stop word was retained on PowerShell even when lowercase, so the same description produced different branch names across the two shells (e.g. 'go AI now' -> 001-go-ai-now on PS vs 001-ai-now on bash). Switch to -cmatch so the check is case-sensitive and the two shells agree. Adds parity tests covering a dropped lowercase short word and a kept uppercase acronym.
This commit is contained in:
@@ -111,8 +111,11 @@ function Get-BranchName {
|
||||
# Keep words that are length >= 3 OR appear as uppercase in original (likely acronyms)
|
||||
if ($word.Length -ge 3) {
|
||||
$meaningfulWords += $word
|
||||
} elseif ($Description -match "\b$($word.ToUpper())\b") {
|
||||
# Keep short words if they appear as uppercase in original (likely acronyms)
|
||||
} elseif ($Description -cmatch "\b$($word.ToUpper())\b") {
|
||||
# Keep short words only if they appear as uppercase in original (likely
|
||||
# acronyms). Use -cmatch so the comparison is case-sensitive, matching the
|
||||
# bash script's case-sensitive grep; -match would be case-insensitive and
|
||||
# would keep every short word.
|
||||
$meaningfulWords += $word
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,6 +869,52 @@ class TestPowerShellDryRun:
|
||||
assert "DRY_RUN" not in data, f"DRY_RUN should not be in normal JSON: {data}"
|
||||
|
||||
|
||||
# ── Short-Word / Acronym Branch-Name Tests ──────────────────────────────────
|
||||
|
||||
|
||||
def _branch_from_output(stdout: str) -> str | None:
|
||||
for line in stdout.splitlines():
|
||||
if line.startswith("BRANCH_NAME:"):
|
||||
return line.split(":", 1)[1].strip()
|
||||
return None
|
||||
|
||||
|
||||
SHORT_WORD_CASES = [
|
||||
# description, expected branch — "go" (lowercase short word) is dropped,
|
||||
# "AI" (uppercase short word / acronym) is kept, "now" (>=3 chars) is kept.
|
||||
("go AI now", "001-ai-now"),
|
||||
# A short word that is lowercase everywhere is dropped entirely.
|
||||
("go to the pub", "001-pub"),
|
||||
]
|
||||
|
||||
|
||||
@requires_bash
|
||||
class TestShortWordRetentionBash:
|
||||
"""A short word is kept only when it appears in uppercase (an acronym)."""
|
||||
|
||||
@pytest.mark.parametrize("description,expected", SHORT_WORD_CASES)
|
||||
def test_short_word_retention(self, git_repo: Path, description: str, expected: str):
|
||||
result = run_script(git_repo, "--dry-run", description)
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert _branch_from_output(result.stdout) == expected
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _has_pwsh(), reason="pwsh not available")
|
||||
class TestShortWordRetentionPowerShell:
|
||||
"""PowerShell must match bash: a short word is kept only when uppercase.
|
||||
|
||||
Regression guard for the `-match` (case-insensitive) vs `-cmatch`
|
||||
(case-sensitive) divergence — with `-match`, every short non-stop word
|
||||
leaked into the branch name even when it was lowercase.
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("description,expected", SHORT_WORD_CASES)
|
||||
def test_short_word_retention(self, ps_git_repo: Path, description: str, expected: str):
|
||||
result = run_ps_script(ps_git_repo, "-DryRun", description)
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert _branch_from_output(result.stdout) == expected
|
||||
|
||||
|
||||
# ── GIT_BRANCH_NAME Override Tests ──────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user