Skip to content

Commit 30415ef

Browse files
fix: ap bump leaves CHANGELOG.md ending in one newline and unstages it on rollback
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 75b0ebb commit 30415ef

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

‎src/afterpython/cli/commands/bump.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ def _restore(files: list[str], new_files: list[str]):
6161

6262
_git("restore", "--source=HEAD", "--staged", "--worktree", "--", *files)
6363
for file in new_files:
64-
_git("rm", "--cached", "--quiet", "--ignore-unmatch", "--", file)
64+
# --force, a hook (e.g. end-of-file-fixer) may have changed the file after it was staged
65+
_git("rm", "--cached", "--force", "--quiet", "--ignore-unmatch", "--", file)
6566
(ap.paths.user_path / file).unlink(missing_ok=True)
6667
click.echo(f"↩️ Restored {', '.join(files + new_files)}", err=True)
6768

@@ -101,6 +102,10 @@ def _write_changelog(tag: str):
101102
)
102103
if result.returncode != 0:
103104
raise click.ClickException(f"git-cliff failed:\n{result.stderr.strip()}")
105+
# the blank line after each release also ends up at the end of the file,
106+
# end it with a single newline as end-of-file-fixer wants
107+
path = ap.paths.user_path / CHANGELOG
108+
path.write_text(path.read_text().rstrip("\n") + "\n")
104109

105110

106111
def _is_interactive() -> bool:

‎tests/test_bump_changelog.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,30 @@ def test_changelog_has_no_links_without_github_remote(repo, monkeypatch):
186186
changelog = (repo.user_path / "CHANGELOG.md").read_text()
187187
assert "## [0.1.2] - " in changelog
188188
assert "- Fix Y (#7)" in changelog
189+
190+
191+
def test_changelog_ends_with_single_newline(repo):
192+
_commit(repo, "feat: add X")
193+
_run_bump()
194+
_commit(repo, "feat: add Y")
195+
_run_bump()
196+
changelog = (repo.user_path / "CHANGELOG.md").read_text()
197+
assert changelog.endswith("\n") and not changelog.endswith("\n\n")
198+
199+
200+
def test_rollback_unstages_new_changelog_changed_by_hook(repo):
201+
_commit(repo, "feat: add X")
202+
# a hook that changes the staged CHANGELOG.md and fails, like end-of-file-fixer
203+
hook = repo.user_path / ".git" / "hooks" / "pre-commit"
204+
hook.write_text("#!/bin/sh\necho fixed >> CHANGELOG.md\nexit 1\n")
205+
hook.chmod(0o755)
206+
result = CliRunner().invoke(bump, [])
207+
assert result.exit_code != 0
208+
status = subprocess.run(
209+
["git", "status", "--porcelain"],
210+
cwd=repo.user_path,
211+
capture_output=True,
212+
text=True,
213+
check=True,
214+
).stdout
215+
assert status == ""

0 commit comments

Comments
 (0)