Public Access
DEVX-100: fix: retry release push on non-fast-forward with rebase loop
Post-merge / detect-type (push) Successful in 10s
Post-merge / validate-commit-msg (push) Successful in 9s
Post-merge / vikunja (push) Successful in 12s
Post-merge / configure-repo (push) Successful in 11s
Post-merge / sync-wiki (push) Successful in 23s
Post-merge / release (push) Successful in 29s
Post-merge / badges (push) Successful in 30s
Build Images / detect-type (push) Successful in 1m0s
Post-merge / publish (push) Successful in 16s
Build Images / build-and-push (push) Successful in 3m57s
Build Images / cleanup (push) Successful in 2m56s
Post-merge / detect-type (push) Successful in 10s
Post-merge / validate-commit-msg (push) Successful in 9s
Post-merge / vikunja (push) Successful in 12s
Post-merge / configure-repo (push) Successful in 11s
Post-merge / sync-wiki (push) Successful in 23s
Post-merge / release (push) Successful in 29s
Post-merge / badges (push) Successful in 30s
Build Images / detect-type (push) Successful in 1m0s
Post-merge / publish (push) Successful in 16s
Build Images / build-and-push (push) Successful in 3m57s
Build Images / cleanup (push) Successful in 2m56s
This commit was merged in pull request #156.
This commit is contained in:
@@ -1234,6 +1234,153 @@ class TestMain:
|
||||
assert "already existed" in result.output
|
||||
mock_tag.assert_called_once_with("0.2.0", "changelog", False)
|
||||
|
||||
@patch.dict("os.environ", {})
|
||||
@patch("devx.ci.release.verify_tag_consistency", return_value=[])
|
||||
@patch("devx.ci.release.fetch_tags")
|
||||
@patch("devx.ci.release.has_user_facing_changes", return_value=True)
|
||||
@patch("devx.ci.release.run_tests")
|
||||
@patch("devx.ci.release.create_and_push_tag", return_value=True)
|
||||
@patch("devx.ci.release.commit_release_changes", return_value=True)
|
||||
@patch("devx.ci.release.update_changelog")
|
||||
@patch("devx.ci.release.update_init_version")
|
||||
@patch("devx.ci.release.get_changelog", return_value="changelog")
|
||||
@patch("devx.ci.release.get_latest_tag", return_value="v0.1.0")
|
||||
@patch("devx.ci.release.get_bumped_version", return_value="0.2.0")
|
||||
@patch("devx.ci.release.has_unreleased_changes", return_value=True)
|
||||
@patch("devx.ci.release.time.sleep")
|
||||
@patch("devx.ci.release.run_cmd")
|
||||
def test_push_retry_succeeds_after_rebase_failure(
|
||||
self,
|
||||
mock_run_cmd: MagicMock,
|
||||
mock_sleep: MagicMock,
|
||||
mock_has: MagicMock,
|
||||
mock_bumped: MagicMock,
|
||||
mock_latest: MagicMock,
|
||||
mock_changelog: MagicMock,
|
||||
mock_update_init: MagicMock,
|
||||
mock_update_changelog: MagicMock,
|
||||
mock_commit: MagicMock,
|
||||
mock_tag: MagicMock,
|
||||
mock_run_tests: MagicMock,
|
||||
mock_user: MagicMock,
|
||||
mock_ft: MagicMock,
|
||||
mock_vtc: MagicMock,
|
||||
) -> None:
|
||||
"""Push should retry after rebase failure and succeed on second attempt."""
|
||||
ok = MagicMock(returncode=0, stdout="master\n", stderr="")
|
||||
rebase_fail = MagicMock(returncode=1, stdout="", stderr="conflict")
|
||||
rebase_abort = MagicMock(returncode=0, stdout="", stderr="")
|
||||
push_ok = MagicMock(returncode=0, stdout="", stderr="")
|
||||
# git rev-parse → ok, git log -1 → ok (non-release msg)
|
||||
# pull --rebase → fail, rebase --abort → ok
|
||||
# pull --rebase → ok, push → ok
|
||||
mock_run_cmd.side_effect = [ok, ok, rebase_fail, rebase_abort, ok, push_ok]
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [])
|
||||
assert result.exit_code == 0
|
||||
assert "Rebase attempt 1/3 failed" in result.output
|
||||
assert "Pushed release commit to master" in result.output
|
||||
|
||||
@patch.dict("os.environ", {})
|
||||
@patch("devx.ci.release.verify_tag_consistency", return_value=[])
|
||||
@patch("devx.ci.release.fetch_tags")
|
||||
@patch("devx.ci.release.has_user_facing_changes", return_value=True)
|
||||
@patch("devx.ci.release.run_tests")
|
||||
@patch("devx.ci.release.create_and_push_tag", return_value=True)
|
||||
@patch("devx.ci.release.commit_release_changes", return_value=True)
|
||||
@patch("devx.ci.release.update_changelog")
|
||||
@patch("devx.ci.release.update_init_version")
|
||||
@patch("devx.ci.release.get_changelog", return_value="changelog")
|
||||
@patch("devx.ci.release.get_latest_tag", return_value="v0.1.0")
|
||||
@patch("devx.ci.release.get_bumped_version", return_value="0.2.0")
|
||||
@patch("devx.ci.release.has_unreleased_changes", return_value=True)
|
||||
@patch("devx.ci.release.time.sleep")
|
||||
@patch("devx.ci.release.run_cmd")
|
||||
def test_push_fails_after_all_retries(
|
||||
self,
|
||||
mock_run_cmd: MagicMock,
|
||||
mock_sleep: MagicMock,
|
||||
mock_has: MagicMock,
|
||||
mock_bumped: MagicMock,
|
||||
mock_latest: MagicMock,
|
||||
mock_changelog: MagicMock,
|
||||
mock_update_init: MagicMock,
|
||||
mock_update_changelog: MagicMock,
|
||||
mock_commit: MagicMock,
|
||||
mock_tag: MagicMock,
|
||||
mock_run_tests: MagicMock,
|
||||
mock_user: MagicMock,
|
||||
mock_ft: MagicMock,
|
||||
mock_vtc: MagicMock,
|
||||
) -> None:
|
||||
"""Push should fail after 3 unsuccessful rebase attempts."""
|
||||
ok = MagicMock(returncode=0, stdout="master\n", stderr="")
|
||||
rebase_fail = MagicMock(returncode=1, stdout="", stderr="conflict")
|
||||
rebase_abort = MagicMock(returncode=0, stdout="", stderr="")
|
||||
# git rev-parse → ok, git log -1 → ok
|
||||
# 3 attempts: pull --rebase → fail, rebase --abort → ok
|
||||
mock_run_cmd.side_effect = [
|
||||
ok,
|
||||
ok,
|
||||
rebase_fail,
|
||||
rebase_abort, # attempt 1
|
||||
rebase_fail,
|
||||
rebase_abort, # attempt 2
|
||||
rebase_fail,
|
||||
rebase_abort, # attempt 3
|
||||
]
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [])
|
||||
assert result.exit_code != 0
|
||||
assert "Failed to push release commit after 3 attempts" in result.output
|
||||
|
||||
@patch.dict("os.environ", {})
|
||||
@patch("devx.ci.release.verify_tag_consistency", return_value=[])
|
||||
@patch("devx.ci.release.fetch_tags")
|
||||
@patch("devx.ci.release.has_user_facing_changes", return_value=True)
|
||||
@patch("devx.ci.release.run_tests")
|
||||
@patch("devx.ci.release.create_and_push_tag", return_value=True)
|
||||
@patch("devx.ci.release.commit_release_changes", return_value=True)
|
||||
@patch("devx.ci.release.update_changelog")
|
||||
@patch("devx.ci.release.update_init_version")
|
||||
@patch("devx.ci.release.get_changelog", return_value="changelog")
|
||||
@patch("devx.ci.release.get_latest_tag", return_value="v0.1.0")
|
||||
@patch("devx.ci.release.get_bumped_version", return_value="0.2.0")
|
||||
@patch("devx.ci.release.has_unreleased_changes", return_value=True)
|
||||
@patch("devx.ci.release.time.sleep")
|
||||
@patch("devx.ci.release.run_cmd")
|
||||
def test_push_retry_succeeds_after_push_failure(
|
||||
self,
|
||||
mock_run_cmd: MagicMock,
|
||||
mock_sleep: MagicMock,
|
||||
mock_has: MagicMock,
|
||||
mock_bumped: MagicMock,
|
||||
mock_latest: MagicMock,
|
||||
mock_changelog: MagicMock,
|
||||
mock_update_init: MagicMock,
|
||||
mock_update_changelog: MagicMock,
|
||||
mock_commit: MagicMock,
|
||||
mock_tag: MagicMock,
|
||||
mock_run_tests: MagicMock,
|
||||
mock_user: MagicMock,
|
||||
mock_ft: MagicMock,
|
||||
mock_vtc: MagicMock,
|
||||
) -> None:
|
||||
"""Push should retry after push rejection and succeed on second attempt."""
|
||||
ok = MagicMock(returncode=0, stdout="master\n", stderr="")
|
||||
rebase_ok = MagicMock(returncode=0, stdout="", stderr="")
|
||||
push_fail = MagicMock(returncode=1, stdout="", stderr="non-fast-forward")
|
||||
push_ok = MagicMock(returncode=0, stdout="", stderr="")
|
||||
# git rev-parse → ok, git log -1 → ok
|
||||
# attempt 1: pull --rebase → ok, push → fail
|
||||
# attempt 2: pull --rebase → ok, push → ok
|
||||
mock_run_cmd.side_effect = [ok, ok, rebase_ok, push_fail, rebase_ok, push_ok]
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, [])
|
||||
assert result.exit_code == 0
|
||||
assert "Push attempt 1/3 failed" in result.output
|
||||
assert "Pushed release commit to master" in result.output
|
||||
|
||||
@patch.dict("os.environ", {})
|
||||
@patch("devx.ci.release.verify_tag_consistency", return_value=[])
|
||||
@patch("devx.ci.release.fetch_tags")
|
||||
|
||||
Reference in New Issue
Block a user