diff --git a/src/devx/ci/publish.py b/src/devx/ci/publish.py index 38b51fa..abc9fd7 100644 --- a/src/devx/ci/publish.py +++ b/src/devx/ci/publish.py @@ -199,7 +199,7 @@ def is_release_commit(tag: str) -> bool: @click.command() @click.argument("tag", required=False) -@click.argument("repo") +@click.argument("repo", required=False) @click.option( "--registry-url", default=None, @@ -223,11 +223,15 @@ def is_release_commit(tag: str) -> bool: ) def main( tag: str | None, - repo: str, + repo: str | None, registry_url: str | None, skip_build: bool, from_tag: bool, ) -> None: + if repo is None: + repo = os.environ.get("GITHUB_REPOSITORY", "") + if not repo: + raise click.ClickException(_("REPO argument is required (or set GITHUB_REPOSITORY env var).")) if from_tag: detected_tag = get_latest_tag() if not detected_tag: diff --git a/src/devx/translations.json b/src/devx/translations.json index a5c64a4..26cbcf4 100644 --- a/src/devx/translations.json +++ b/src/devx/translations.json @@ -1135,6 +1135,14 @@ "ru": "Tag is required (or use --from-tag).", "zh": "Tag is required (or use --from-tag)." }, + "REPO argument is required (or set GITHUB_REPOSITORY env var).": { + "bg": "REPO argument is required (or set GITHUB_REPOSITORY env var).", + "de": "REPO argument is required (or set GITHUB_REPOSITORY env var).", + "en": "REPO argument is required (or set GITHUB_REPOSITORY env var).", + "pl": "Argument REPO jest wymagany (lub ustaw zmiennÄ… GITHUB_REPOSITORY).", + "ru": "REPO argument is required (or set GITHUB_REPOSITORY env var).", + "zh": "REPO argument is required (or set GITHUB_REPOSITORY env var)." + }, "Tag v{version} already existed. Publish workflow should already have been triggered.": { "bg": "Tag v{version} already existed. Publish workflow should already have been triggered.", "de": "Tag v{version} already existed. Publish workflow should already have been triggered.", diff --git a/tests/unit/test_publish.py b/tests/unit/test_publish.py index 755c515..2169d25 100644 --- a/tests/unit/test_publish.py +++ b/tests/unit/test_publish.py @@ -475,6 +475,22 @@ class TestFromTag: assert result.exit_code == 0 assert "No tag found" in result.output + @patch("devx.ci.publish.get_latest_tag", return_value=None) + def test_from_tag_no_repo_uses_env(self, _mock: MagicMock) -> None: + runner = CliRunner() + with patch.dict("os.environ", {"GITHUB_REPOSITORY": "owner/repo"}): + result = runner.invoke(main, ["--from-tag", "--skip-build"]) + assert result.exit_code == 0 + assert "No tag found" in result.output + + @patch("devx.ci.publish.get_latest_tag", return_value=None) + def test_from_tag_no_repo_no_env_raises(self, _mock: MagicMock) -> None: + runner = CliRunner() + with patch.dict("os.environ", {}, clear=True): + result = runner.invoke(main, ["--from-tag", "--skip-build"]) + assert result.exit_code != 0 + assert "REPO argument is required" in result.output + @patch("devx.ci.publish.is_release_commit", return_value=False) @patch("devx.ci.publish.get_latest_tag", return_value="v1.0.0") def test_from_tag_not_release_commit_skips(self, _mock_tag: MagicMock, _mock_rel: MagicMock) -> None: @@ -497,6 +513,20 @@ class TestFromTag: assert result.exit_code == 0 assert "Publishing release v1.0.0" in result.output + @patch("devx.ci.publish.is_release_commit", return_value=True) + @patch("devx.ci.publish.get_latest_tag", return_value="v1.0.0") + def test_from_tag_publishes_no_repo_arg(self, _mock_tag: MagicMock, _mock_rel: MagicMock) -> None: + with patch.dict("os.environ", {"REPO_TOKEN": "fake", "GITHUB_REPOSITORY": "owner/repo"}): + with patch("devx.ci.publish.TeaCLI") as mock_tea_cls: + mock_tea = MagicMock() + mock_tea.list_releases.return_value = [] + mock_tea_cls.return_value = mock_tea + with patch("devx.ci.publish.generate_release_notes", return_value="notes"): + runner = CliRunner() + result = runner.invoke(main, ["--from-tag", "--skip-build"]) + assert result.exit_code == 0 + assert "Publishing release v1.0.0" in result.output + def test_no_tag_no_from_tag_raises(self) -> None: runner = CliRunner() result = runner.invoke(main, ["", "owner/repo", "--skip-build"])