GRM-34: fix: skip commit when version file unchanged in release.py
This commit is contained in:
+22
-9
@@ -116,10 +116,21 @@ def update_init_version(new_version: str) -> None:
|
|||||||
f.write(updated)
|
f.write(updated)
|
||||||
|
|
||||||
|
|
||||||
def create_release_commit(new_version: str) -> None:
|
def create_release_commit(new_version: str) -> bool:
|
||||||
"""Stage version file and create a release commit."""
|
"""Stage version file and create a release commit.
|
||||||
|
|
||||||
|
Returns True if a commit was created, False if there were no changes
|
||||||
|
(e.g., version file already at the target version).
|
||||||
|
"""
|
||||||
run_cmd(["git", "add", INIT_FILE])
|
run_cmd(["git", "add", INIT_FILE])
|
||||||
|
# Check if there are staged changes
|
||||||
|
status = run_cmd(["git", "diff", "--cached", "--quiet"], check=False)
|
||||||
|
if status.returncode == 0:
|
||||||
|
# No staged changes — version file already at target
|
||||||
|
click.echo(_("Version file already at v{version}, skipping commit.", version=new_version))
|
||||||
|
return False
|
||||||
run_cmd(["git", "commit", "-m", f"chore(release): prepare for v{new_version}"])
|
run_cmd(["git", "commit", "-m", f"chore(release): prepare for v{new_version}"])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def create_and_push_tag(new_version: str, changelog: str, dry_run: bool) -> None:
|
def create_and_push_tag(new_version: str, changelog: str, dry_run: bool) -> None:
|
||||||
@@ -179,13 +190,15 @@ def main(dry_run: bool) -> None:
|
|||||||
update_init_version(new_version)
|
update_init_version(new_version)
|
||||||
click.echo(_("Updated version in {init}", init=INIT_FILE))
|
click.echo(_("Updated version in {init}", init=INIT_FILE))
|
||||||
|
|
||||||
# Create release commit
|
# Create release commit (may be skipped if version unchanged)
|
||||||
create_release_commit(new_version)
|
committed = create_release_commit(new_version)
|
||||||
click.echo(_("Created release commit."))
|
if committed:
|
||||||
|
click.echo(_("Created release commit."))
|
||||||
# Push commit to master
|
# Push commit to master
|
||||||
run_cmd(["git", "push", "origin", "master"])
|
run_cmd(["git", "push", "origin", "master"])
|
||||||
click.echo(_("Pushed release commit to master."))
|
click.echo(_("Pushed release commit to master."))
|
||||||
|
else:
|
||||||
|
click.echo(_("Skipping commit push — version unchanged."))
|
||||||
|
|
||||||
# Create and push tag
|
# Create and push tag
|
||||||
create_and_push_tag(new_version, changelog, dry_run)
|
create_and_push_tag(new_version, changelog, dry_run)
|
||||||
|
|||||||
@@ -137,11 +137,23 @@ class TestUpdateInitVersion:
|
|||||||
class TestCreateReleaseCommit:
|
class TestCreateReleaseCommit:
|
||||||
@patch("scripts.release.run_cmd")
|
@patch("scripts.release.run_cmd")
|
||||||
def test_commits(self, mock_run_cmd: MagicMock) -> None:
|
def test_commits(self, mock_run_cmd: MagicMock) -> None:
|
||||||
create_release_commit("0.2.0")
|
# git diff --cached --quiet returns 1 (changes exist)
|
||||||
|
mock_run_cmd.return_value = MagicMock(returncode=1, stdout="", stderr="")
|
||||||
|
result = create_release_commit("0.2.0")
|
||||||
|
assert result is True
|
||||||
calls = [c.args[0] for c in mock_run_cmd.call_args_list]
|
calls = [c.args[0] for c in mock_run_cmd.call_args_list]
|
||||||
assert ["git", "add", "src/gitea_runner_manager/__init__.py"] in calls
|
assert ["git", "add", "src/gitea_runner_manager/__init__.py"] in calls
|
||||||
assert ["git", "commit", "-m", "chore(release): prepare for v0.2.0"] in calls
|
assert ["git", "commit", "-m", "chore(release): prepare for v0.2.0"] in calls
|
||||||
|
|
||||||
|
@patch("scripts.release.run_cmd")
|
||||||
|
def test_skips_when_no_changes(self, mock_run_cmd: MagicMock) -> None:
|
||||||
|
# git diff --cached --quiet returns 0 (no changes)
|
||||||
|
mock_run_cmd.return_value = MagicMock(returncode=0, stdout="", stderr="")
|
||||||
|
result = create_release_commit("0.1.0")
|
||||||
|
assert result is False
|
||||||
|
calls = [c.args[0] for c in mock_run_cmd.call_args_list]
|
||||||
|
assert ["git", "commit", "-m", "chore(release): prepare for v0.1.0"] not in calls
|
||||||
|
|
||||||
|
|
||||||
class TestCreateAndPushTag:
|
class TestCreateAndPushTag:
|
||||||
@patch("scripts.release.run_cmd")
|
@patch("scripts.release.run_cmd")
|
||||||
@@ -258,7 +270,7 @@ class TestMain:
|
|||||||
|
|
||||||
@patch.dict("os.environ", {})
|
@patch.dict("os.environ", {})
|
||||||
@patch("scripts.release.create_and_push_tag")
|
@patch("scripts.release.create_and_push_tag")
|
||||||
@patch("scripts.release.create_release_commit")
|
@patch("scripts.release.create_release_commit", return_value=True)
|
||||||
@patch("scripts.release.update_init_version")
|
@patch("scripts.release.update_init_version")
|
||||||
@patch("scripts.release.get_changelog", return_value="changelog")
|
@patch("scripts.release.get_changelog", return_value="changelog")
|
||||||
@patch("scripts.release.get_latest_tag", return_value="v0.1.0")
|
@patch("scripts.release.get_latest_tag", return_value="v0.1.0")
|
||||||
@@ -284,3 +296,31 @@ class TestMain:
|
|||||||
mock_update_init.assert_called_once_with("0.2.0")
|
mock_update_init.assert_called_once_with("0.2.0")
|
||||||
mock_commit.assert_called_once_with("0.2.0")
|
mock_commit.assert_called_once_with("0.2.0")
|
||||||
mock_tag.assert_called_once_with("0.2.0", "changelog", False)
|
mock_tag.assert_called_once_with("0.2.0", "changelog", False)
|
||||||
|
|
||||||
|
@patch.dict("os.environ", {})
|
||||||
|
@patch("scripts.release.create_and_push_tag")
|
||||||
|
@patch("scripts.release.create_release_commit", return_value=False)
|
||||||
|
@patch("scripts.release.update_init_version")
|
||||||
|
@patch("scripts.release.get_changelog", return_value="changelog")
|
||||||
|
@patch("scripts.release.get_latest_tag", return_value="v0.1.0")
|
||||||
|
@patch("scripts.release.get_bumped_version", return_value="0.1.0")
|
||||||
|
@patch("scripts.release.has_unreleased_changes", return_value=True)
|
||||||
|
@patch("scripts.release.run_cmd")
|
||||||
|
def test_full_flow_no_commit(
|
||||||
|
self,
|
||||||
|
mock_run_cmd: MagicMock,
|
||||||
|
mock_has: MagicMock,
|
||||||
|
mock_bumped: MagicMock,
|
||||||
|
mock_latest: MagicMock,
|
||||||
|
mock_changelog: MagicMock,
|
||||||
|
mock_update_init: MagicMock,
|
||||||
|
mock_commit: MagicMock,
|
||||||
|
mock_tag: MagicMock,
|
||||||
|
) -> None:
|
||||||
|
"""When version is unchanged, skip commit but still tag."""
|
||||||
|
mock_run_cmd.return_value = MagicMock(returncode=0, stdout="master\n", stderr="")
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, [])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "Skipping commit push" in result.output
|
||||||
|
mock_tag.assert_called_once_with("0.1.0", "changelog", False)
|
||||||
|
|||||||
Reference in New Issue
Block a user