DEVX-43: feat: add publish step to post-merge release job, make publish idempotent

This commit is contained in:
emil
2026-06-24 22:16:37 +00:00
parent 8f7af97335
commit fd0c4de31e
4 changed files with 81 additions and 1 deletions
+43
View File
@@ -162,6 +162,7 @@ class TestMain:
mock_notes: MagicMock,
) -> None:
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
@@ -187,6 +188,7 @@ class TestMain:
) -> None:
"""When no PYPI_TOKEN, publishes to Gitea PyPI registry."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
@@ -209,6 +211,7 @@ class TestMain:
) -> None:
"""--registry-url flag publishes to the specified Gitea registry."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(
@@ -236,6 +239,7 @@ class TestMain:
) -> None:
"""DEVX_PYPI_REGISTRY_URL env var sets the registry URL."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
@@ -256,6 +260,7 @@ class TestMain:
) -> None:
"""When no PYPI_TOKEN and no registry URL, skips publish and creates release only."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo", "--registry-url", ""])
@@ -307,6 +312,7 @@ class TestMain:
self, mock_build: MagicMock, mock_publish: MagicMock, mock_tea_cls: MagicMock, mock_notes: MagicMock
) -> None:
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea.create_release.side_effect = TeaCLIError("server error")
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
@@ -323,6 +329,7 @@ class TestMain:
) -> None:
"""--skip-build skips build_package and PyPI publish, only creates Gitea release."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = []
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo", "--skip-build"])
@@ -330,3 +337,39 @@ class TestMain:
assert "skip" in result.output.lower()
mock_build.assert_not_called()
mock_tea.create_release.assert_called_once()
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
@patch("devx.ci.publish.generate_release_notes", return_value="Release notes")
@patch("devx.ci.publish.TeaCLI")
@patch("devx.ci.publish.publish_to_pypi")
@patch("devx.ci.publish.build_package")
def test_skips_release_creation_when_already_exists(
self, mock_build: MagicMock, mock_publish: MagicMock, mock_tea_cls: MagicMock, mock_notes: MagicMock
) -> None:
"""If the Gitea release already exists, skip creation (idempotent)."""
mock_tea = MagicMock()
mock_tea.list_releases.return_value = [{"tag_name": "v1.0.0"}]
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
assert result.exit_code == 0
assert "already exists" in result.output
mock_tea.create_release.assert_not_called()
@patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"})
@patch("devx.ci.publish.generate_release_notes", return_value="Release notes")
@patch("devx.ci.publish.TeaCLI")
@patch("devx.ci.publish.publish_to_pypi")
@patch("devx.ci.publish.build_package")
def test_proceeds_to_create_when_list_releases_fails(
self, mock_build: MagicMock, mock_publish: MagicMock, mock_tea_cls: MagicMock, mock_notes: MagicMock
) -> None:
"""If list_releases raises TeaCLIError, proceed to create the release."""
mock_tea = MagicMock()
mock_tea.list_releases.side_effect = TeaCLIError("api error")
mock_tea_cls.return_value = mock_tea
runner = CliRunner()
result = runner.invoke(main, ["v1.0.0", "owner/repo"])
assert result.exit_code == 0
assert "Gitea release v1.0.0 created" in result.output
mock_tea.create_release.assert_called_once()