diff --git a/pontos/git/git.py b/pontos/git/git.py index 497ba840..cc2ae1c1 100644 --- a/pontos/git/git.py +++ b/pontos/git/git.py @@ -19,7 +19,15 @@ from enum import Enum from os import PathLike, fspath from pathlib import Path -from typing import Collection, Iterable, Iterator, List, Optional, Union +from typing import ( + Collection, + Iterable, + Iterator, + List, + Optional, + Sequence, + Union, +) from pontos.errors import PontosError from pontos.git.status import StatusEntry, parse_git_status @@ -384,7 +392,7 @@ def list_tags( def add( self, - files: Union[str, PathLike[str], list[Union[PathLike[str], str]]], + files: Union[str, PathLike[str], Sequence[Union[PathLike[str], str]]], ) -> None: """ Add files to the git staging area diff --git a/pontos/release/create.py b/pontos/release/create.py index 998f88cb..f9420691 100644 --- a/pontos/release/create.py +++ b/pontos/release/create.py @@ -114,7 +114,11 @@ def _create_changelog( ) async def _create_release( - self, release_version: Version, token: str, release_text: str + self, + release_version: Version, + token: str, + release_text: str, + github_pre_release: bool, ) -> None: github = GitHubAsyncRESTApi(token=token) @@ -126,7 +130,7 @@ async def _create_release( git_version, name=f"{self.project} {release_version}", body=release_text, - prerelease=release_version.is_pre_release, + prerelease=release_version.is_pre_release or github_pre_release, ) async def async_run( # type: ignore[override] @@ -146,6 +150,7 @@ async def async_run( # type: ignore[override] local: Optional[bool] = False, release_series: Optional[str] = None, update_project: bool = True, + github_pre_release: bool = False, ) -> CreateReleaseReturnValue: """ Create a release @@ -177,6 +182,8 @@ async def async_run( # type: ignore[override] release_series: Optional release series to use. For example: "1.2", "2", "23". update_project: Update version in project files. + github_pre_release: Enforce uploading a release as a GitHub pre + release """ git_signing_key = ( git_signing_key @@ -296,7 +303,12 @@ async def async_run( # type: ignore[override] try: self.terminal.info(f"Creating release for {release_version}") - await self._create_release(release_version, token, release_text) + await self._create_release( + release_version, + token, + release_text, + github_pre_release, + ) self.terminal.ok(f"Created release {release_version}") except httpx.HTTPStatusError as e: @@ -385,4 +397,5 @@ def create_release( local=args.local, release_series=args.release_series, update_project=args.update_project, + github_pre_release=args.github_pre_release, ) diff --git a/pontos/release/parser.py b/pontos/release/parser.py index 9dd5d747..524bd3ee 100644 --- a/pontos/release/parser.py +++ b/pontos/release/parser.py @@ -176,6 +176,11 @@ def parse_args(args) -> Tuple[Optional[str], Optional[str], Namespace]: action=BooleanOptionalAction, default=True, ) + create_parser.add_argument( + "--github-pre-release", + help="Enforce uploading a release as GitHub " "pre-release. ", + action="store_true", + ) sign_parser = subparsers.add_parser( "sign", help="Create signatures for an existing release" diff --git a/pontos/version/commands/_command.py b/pontos/version/commands/_command.py index 706d9140..39d653b9 100644 --- a/pontos/version/commands/_command.py +++ b/pontos/version/commands/_command.py @@ -29,7 +29,9 @@ class VersionCommand(ABC): project_file_name: str - def __init__(self, versioning_scheme: VersioningScheme) -> None: + def __init__( + self, versioning_scheme: Union[VersioningScheme, type[VersioningScheme]] + ) -> None: self.project_file_path = Path.cwd() / self.project_file_name self.versioning_scheme = versioning_scheme diff --git a/tests/release/test_create.py b/tests/release/test_create.py index 64917029..0ec2eacc 100644 --- a/tests/release/test_create.py +++ b/tests/release/test_create.py @@ -19,10 +19,10 @@ import unittest from contextlib import contextmanager -from dataclasses import dataclass, field +from dataclasses import dataclass from datetime import datetime from pathlib import Path -from typing import Iterable, Optional, Union +from typing import Iterable, Iterator, Optional, Union from unittest.mock import AsyncMock, MagicMock, call, patch from httpx import HTTPStatusError, Request, Response @@ -55,8 +55,8 @@ def str_or_list(values: Union[str, Iterable[str]]) -> Iterable[str]: @contextmanager def setup_go_project( - *, current_version: str, tags: Union[str, Iterable[str]] = None -) -> Path: + *, current_version: str, tags: Union[str, Iterable[str], None] = None +) -> Iterator[Path]: with temp_git_repository() as tmp_git: git = Git(tmp_git) @@ -182,12 +182,12 @@ def test_release_version( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -212,7 +212,7 @@ def test_release_version( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -230,12 +230,12 @@ def test_release_version( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -288,12 +288,12 @@ def test_initial_release_version( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -316,7 +316,7 @@ def test_initial_release_version( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -334,12 +334,12 @@ def test_initial_release_version( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -392,12 +392,12 @@ def test_release_patch( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -422,7 +422,7 @@ def test_release_patch( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -439,12 +439,12 @@ def test_release_patch( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -498,12 +498,12 @@ def test_release_calendar( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -526,7 +526,7 @@ def test_release_calendar( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -544,12 +544,12 @@ def test_release_calendar( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -604,12 +604,12 @@ def test_release_minor( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -634,7 +634,7 @@ def test_release_minor( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -651,12 +651,12 @@ def test_release_minor( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -709,12 +709,12 @@ def test_release_major( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -739,7 +739,7 @@ def test_release_major( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -756,12 +756,12 @@ def test_release_major( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -814,12 +814,12 @@ def test_release_alpha( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -842,7 +842,7 @@ def test_release_alpha( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -859,12 +859,12 @@ def test_release_alpha( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -919,12 +919,12 @@ def test_release_beta( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -947,7 +947,7 @@ def test_release_beta( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -964,12 +964,12 @@ def test_release_beta( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -1024,12 +1024,12 @@ def test_release_release_candidate( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -1052,7 +1052,7 @@ def test_release_release_candidate( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1069,12 +1069,12 @@ def test_release_release_candidate( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_has_calls( - [call("MyProject.conf"), call("MyProject.conf")] + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] ) git_instance_mock.commit.assert_has_calls( [ @@ -1143,7 +1143,7 @@ def test_no_project_settings( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual( @@ -1194,7 +1194,7 @@ def test_no_update_project( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1205,8 +1205,8 @@ def test_no_update_project( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) git_instance_mock.add.assert_not_called() @@ -1261,7 +1261,7 @@ def test_no_last_release_version( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual( @@ -1299,7 +1299,7 @@ def test_no_release_error( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual(released, CreateReleaseReturnValue.NO_RELEASE_VERSION) @@ -1329,7 +1329,7 @@ def test_has_tag( released = create_release( terminal=mock_terminal(), error_terminal=mock_terminal(), - token=token, + token=token, # type: ignore[arg-type] args=args, ) @@ -1375,7 +1375,7 @@ def test_update_version_error( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_mock.return_value.push.assert_not_called() @@ -1423,12 +1423,12 @@ def test_github_create_release_failure( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -1459,7 +1459,7 @@ def test_github_create_release_failure( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual( @@ -1469,7 +1469,7 @@ def test_github_create_release_failure( git_instance_mock.push.assert_called_once_with( follow_tags=True, remote=None ) - git_instance_mock.add.assert_called_once_with("MyProject.conf") + git_instance_mock.add.assert_called_once_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_once_with( "Automatic release to 0.0.1", verify=False, gpg_signing_key="1234" ) @@ -1478,8 +1478,8 @@ def test_github_create_release_failure( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) @patch("pontos.release.create.Git", autospec=True) @@ -1512,7 +1512,7 @@ def test_update_version_after_release_error( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionError("An error"), ] @@ -1538,7 +1538,7 @@ def test_update_version_after_release_error( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_called_once_with( @@ -1553,11 +1553,11 @@ def test_update_version_after_release_error( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) - git_instance_mock.add.assert_called_once_with("MyProject.conf") + git_instance_mock.add.assert_called_once_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_once_with( "Automatic release to 0.0.1", verify=False, gpg_signing_key="1234" ) @@ -1599,12 +1599,12 @@ def test_release_to_specific_git_remote( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -1634,7 +1634,7 @@ def test_release_to_specific_git_remote( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1645,8 +1645,8 @@ def test_release_to_specific_git_remote( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) command_mock.update_version.assert_has_calls( @@ -1656,7 +1656,7 @@ def test_release_to_specific_git_remote( ], ) - git_instance_mock.add.assert_called_with("MyProject.conf") + git_instance_mock.add.assert_called_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_with( "Automatic adjustments after release\n\n" "* Update to version 0.0.2.dev1\n", @@ -1698,12 +1698,12 @@ def test_release_without_git_prefix( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -1731,7 +1731,7 @@ def test_release_without_git_prefix( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1742,8 +1742,8 @@ def test_release_without_git_prefix( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) command_mock.update_version.assert_has_calls( @@ -1753,7 +1753,7 @@ def test_release_without_git_prefix( ], ) - git_instance_mock.add.assert_called_with("MyProject.conf") + git_instance_mock.add.assert_called_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_with( "Automatic adjustments after release\n\n" "* Update to version 0.0.2.dev1\n", @@ -1792,12 +1792,12 @@ def test_release_github_api( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -1829,7 +1829,7 @@ def test_release_github_api( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1854,7 +1854,7 @@ def test_release_github_api( ], ) - git_instance_mock.add.assert_called_with("MyProject.conf") + git_instance_mock.add.assert_called_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_with( "Automatic adjustments after release\n\n" "* Update to version 0.0.2.dev1\n", @@ -1893,12 +1893,12 @@ def test_release_github_api_pre_release( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -1930,7 +1930,7 @@ def test_release_github_api_pre_release( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_has_calls( @@ -1955,7 +1955,7 @@ def test_release_github_api_pre_release( ], ) - git_instance_mock.add.assert_called_with("MyProject.conf") + git_instance_mock.add.assert_called_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_with( "Automatic adjustments after release\n\n" "* Update to version 0.0.1a1+dev1\n", @@ -2001,7 +2001,7 @@ def test_release_with_go_project( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual(released, CreateReleaseReturnValue.SUCCESS) @@ -2021,8 +2021,8 @@ def test_release_with_go_project( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", "A Changelog"), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", False), ) self.assertEqual(released, CreateReleaseReturnValue.SUCCESS) @@ -2053,12 +2053,12 @@ def test_release_with_changelog( VersionUpdate( previous=current_version, new=release_version, - changed_files=["project.conf"], + changed_files=[Path("project.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["project.conf", "version.lang"], + changed_files=[Path("project.conf"), Path("version.lang")], ), ] git_instance_mock: MagicMock = git_mock.return_value @@ -2110,7 +2110,7 @@ def test_release_with_changelog( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.list_tags.assert_called_once_with() @@ -2134,15 +2134,19 @@ def test_release_with_changelog( ) self.assertEqual( - create_release_mock.await_args.args[1:], - (release_version, "foo", expected_changelog), + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", expected_changelog, False), ) git_instance_mock.tag.assert_called_once_with( "v0.0.2", gpg_key_id="1234", message="Automatic release to 0.0.2" ) git_instance_mock.add.assert_has_calls( - [call("project.conf"), call("project.conf"), call("version.lang")] + [ + call(Path("project.conf")), + call(Path("project.conf")), + call(Path("version.lang")), + ] ) git_instance_mock.commit.assert_has_calls( [ @@ -2191,12 +2195,12 @@ def test_release_local( VersionUpdate( previous=current_version, new=release_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), VersionUpdate( previous=release_version, new=next_version, - changed_files=["MyProject.conf"], + changed_files=[Path("MyProject.conf")], ), ] create_changelog_mock.return_value = "A Changelog" @@ -2223,7 +2227,7 @@ def test_release_local( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) git_instance_mock.push.assert_not_called() @@ -2237,7 +2241,7 @@ def test_release_local( ] ) - git_instance_mock.add.assert_called_with("MyProject.conf") + git_instance_mock.add.assert_called_with(Path("MyProject.conf")) git_instance_mock.commit.assert_called_with( "Automatic adjustments after release\n\n" "* Update to version 0.0.2.dev1\n", @@ -2250,14 +2254,120 @@ def test_release_local( self.assertEqual(released, CreateReleaseReturnValue.SUCCESS) + @patch("pontos.release.create.Git", autospec=True) + @patch("pontos.release.create.get_last_release_version", autospec=True) + @patch( + "pontos.release.create.CreateReleaseCommand._create_release", + autospec=True, + ) + @patch( + "pontos.release.create.CreateReleaseCommand._create_changelog", + autospec=True, + ) + @patch("pontos.release.create.Project._gather_commands", autospec=True) + def test_release_enforce_github_release( + self, + gather_commands_mock: MagicMock, + create_changelog_mock: MagicMock, + create_release_mock: AsyncMock, + get_last_release_version_mock: MagicMock, + git_mock: MagicMock, + ): + current_version = PEP440Version("0.0.1") + release_version = PEP440Version("0.0.2") + next_version = PEP440Version("1.0.0.dev1") + command_mock = MagicMock(spec=GoVersionCommand) + gather_commands_mock.return_value = [command_mock] + create_changelog_mock.return_value = "A Changelog" + get_last_release_version_mock.return_value = current_version + command_mock.update_version.side_effect = [ + VersionUpdate( + previous=current_version, + new=release_version, + changed_files=[Path("MyProject.conf")], + ), + VersionUpdate( + previous=release_version, + new=next_version, + changed_files=[Path("MyProject.conf")], + ), + ] + git_instance_mock: MagicMock = git_mock.return_value + git_instance_mock.status.return_value = [ + StatusEntry("M MyProject.conf") + ] + + _, token, args = parse_args( + [ + "release", + "--project", + "foo", + "--release-type", + "patch", + "--next-version", + "1.0.0.dev1", + "--github-pre-release", + ] + ) + + with temp_git_repository(): + released = create_release( + terminal=mock_terminal(), + error_terminal=mock_terminal(), + args=args, + token=token, # type: ignore[arg-type] + ) + + git_instance_mock.push.assert_has_calls( + [ + call(follow_tags=True, remote=None), + call(follow_tags=True, remote=None), + ], + ) + command_mock.update_version.assert_has_calls( + [ + call(release_version, force=False), + call(next_version, force=False), + ], + ) + + self.assertEqual( + create_release_mock.await_args.args[1:], # type: ignore[union-attr] + (release_version, "foo", "A Changelog", True), + ) + + git_instance_mock.add.assert_has_calls( + [call(Path("MyProject.conf")), call(Path("MyProject.conf"))] + ) + git_instance_mock.commit.assert_has_calls( + [ + call( + "Automatic release to 0.0.2", + verify=False, + gpg_signing_key="1234", + ), + call( + "Automatic adjustments after release\n\n" + "* Update to version 1.0.0.dev1\n", + verify=False, + gpg_signing_key="1234", + ), + ] + ) + git_instance_mock.tag.assert_called_once_with( + "v0.0.2", gpg_key_id="1234", message="Automatic release to 0.0.2" + ) + + self.assertEqual(released, CreateReleaseReturnValue.SUCCESS) + @dataclass class Release: release_type: str + current_version: str expected_release_version: str - tags: list[str] = field(default_factory=list) + tags: Union[str, list[str]] expected_last_release_version: Optional[str] = None - current_version: Optional[str] = None release_series: Optional[str] = None @@ -2351,7 +2461,7 @@ def test_release( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual( @@ -2520,7 +2630,7 @@ def test_release_series( terminal=mock_terminal(), error_terminal=mock_terminal(), args=args, - token=token, + token=token, # type: ignore[arg-type] ) self.assertEqual(released, CreateReleaseReturnValue.SUCCESS) diff --git a/tests/release/test_parser.py b/tests/release/test_parser.py index 1bf5a2ed..bf6a4ab8 100644 --- a/tests/release/test_parser.py +++ b/tests/release/test_parser.py @@ -48,114 +48,120 @@ def test_token(self): self.assertEqual(token, "foo") -class ReleaseParseArgsTestCase(unittest.TestCase): - def test_release_func(self): +class CreateParseArgsTestCase(unittest.TestCase): + def test_create_func(self): + _, _, args = parse_args(["create", "--release-type", "patch"]) + + self.assertEqual(args.func, create_release) + + def test_release_alias(self): _, _, args = parse_args(["release", "--release-type", "patch"]) self.assertEqual(args.func, create_release) def test_default(self): - _, _, args = parse_args(["release", "--release-type", "patch"]) + _, _, args = parse_args(["create", "--release-type", "patch"]) self.assertEqual(args.git_tag_prefix, "v") self.assertEqual(args.space, "greenbone") self.assertFalse(args.local) + self.assertFalse(args.github_pre_release) def test_git_remote_name(self): _, _, args = parse_args( - ["release", "--git-remote-name", "foo", "--release-type", "patch"] + ["create", "--git-remote-name", "foo", "--release-type", "patch"] ) self.assertEqual(args.git_remote_name, "foo") def test_git_signing_key(self): _, _, args = parse_args( - ["release", "--git-signing-key", "123", "--release-type", "patch"] + ["create", "--git-signing-key", "123", "--release-type", "patch"] ) self.assertEqual(args.git_signing_key, "123") def test_git_tag_prefix(self): _, _, args = parse_args( - ["release", "--git-tag-prefix", "a", "--release-type", "patch"] + ["create", "--git-tag-prefix", "a", "--release-type", "patch"] ) self.assertEqual(args.git_tag_prefix, "a") _, _, args = parse_args( - ["release", "--git-tag-prefix", "", "--release-type", "patch"] + ["create", "--git-tag-prefix", "", "--release-type", "patch"] ) self.assertEqual(args.git_tag_prefix, "") _, _, args = parse_args( - ["release", "--git-tag-prefix", "--release-type", "patch"] + ["create", "--git-tag-prefix", "--release-type", "patch"] ) self.assertEqual(args.git_tag_prefix, "") def test_space(self): _, _, args = parse_args( - ["release", "--space", "foo", "--release-type", "patch"] + ["create", "--space", "foo", "--release-type", "patch"] ) self.assertEqual(args.space, "foo") def test_project(self): _, _, args = parse_args( - ["release", "--project", "foo", "--release-type", "patch"] + ["create", "--project", "foo", "--release-type", "patch"] ) self.assertEqual(args.project, "foo") def test_next_version(self): _, _, args = parse_args( - ["release", "--next-version", "1.2.3", "--release-type", "patch"] + ["create", "--next-version", "1.2.3", "--release-type", "patch"] ) self.assertEqual(args.next_version, PEP440Version("1.2.3")) def test_release_type(self): - _, _, args = parse_args(["release", "--release-type", "patch"]) + _, _, args = parse_args(["create", "--release-type", "patch"]) self.assertEqual(args.release_type, ReleaseType.PATCH) - _, _, args = parse_args(["release", "--release-type", "calendar"]) + _, _, args = parse_args(["create", "--release-type", "calendar"]) self.assertEqual(args.release_type, ReleaseType.CALENDAR) - _, _, args = parse_args(["release", "--release-type", "minor"]) + _, _, args = parse_args(["create", "--release-type", "minor"]) self.assertEqual(args.release_type, ReleaseType.MINOR) - _, _, args = parse_args(["release", "--release-type", "major"]) + _, _, args = parse_args(["create", "--release-type", "major"]) self.assertEqual(args.release_type, ReleaseType.MAJOR) - _, _, args = parse_args(["release", "--release-type", "alpha"]) + _, _, args = parse_args(["create", "--release-type", "alpha"]) self.assertEqual(args.release_type, ReleaseType.ALPHA) - _, _, args = parse_args(["release", "--release-type", "beta"]) + _, _, args = parse_args(["create", "--release-type", "beta"]) self.assertEqual(args.release_type, ReleaseType.BETA) _, _, args = parse_args( - ["release", "--release-type", "release-candidate"] + ["create", "--release-type", "release-candidate"] ) self.assertEqual(args.release_type, ReleaseType.RELEASE_CANDIDATE) with self.assertRaises(SystemExit), redirect_stderr(StringIO()): - parse_args(["release", "--release-type", "foo"]) + parse_args(["create", "--release-type", "foo"]) def test_release_type_version_without_release_version(self): with self.assertRaises(SystemExit), redirect_stderr(StringIO()): - parse_args(["release", "--release-type", "version"]) + parse_args(["create", "--release-type", "version"]) _, _, args = parse_args( [ - "release", + "create", "--release-type", "version", "--release-version", @@ -166,21 +172,21 @@ def test_release_type_version_without_release_version(self): self.assertEqual(args.release_version, PEP440Version("1.2.3")) def test_release_version(self): - _, _, args = parse_args(["release", "--release-version", "1.2.3"]) + _, _, args = parse_args(["create", "--release-version", "1.2.3"]) self.assertEqual(args.release_version, PEP440Version("1.2.3")) self.assertEqual(args.release_type, ReleaseType.VERSION) with self.assertRaises(SystemExit), redirect_stderr(StringIO()): - parse_args(["release", "--release-version", "1.2.3", "--patch"]) + parse_args(["create", "--release-version", "1.2.3", "--patch"]) with self.assertRaises(SystemExit), redirect_stderr(StringIO()): - parse_args(["release", "--release-version", "1.2.3", "--calendar"]) + parse_args(["create", "--release-version", "1.2.3", "--calendar"]) with self.assertRaises(SystemExit), redirect_stderr(StringIO()): parse_args( [ - "release", + "create", "--release-version", "1.2.3", "--release-type", @@ -191,7 +197,7 @@ def test_release_version(self): with self.assertRaises(SystemExit), redirect_stderr(StringIO()): parse_args( [ - "release", + "create", "--release-version", "1.2.3", "--release-type", @@ -201,7 +207,7 @@ def test_release_version(self): def test_local(self): _, _, args = parse_args( - ["release", "--local", "--release-type", "patch"] + ["create", "--local", "--release-type", "patch"] ) self.assertTrue(args.local) @@ -209,7 +215,7 @@ def test_local(self): def test_conventional_commits_config(self): _, _, args = parse_args( [ - "release", + "create", "--conventional-commits-config", "foo.toml", "--release-type", @@ -221,28 +227,35 @@ def test_conventional_commits_config(self): def test_release_series(self): _, _, args = parse_args( - ["release", "--release-type", "patch", "--release-series", "22.4"] + ["create", "--release-type", "patch", "--release-series", "22.4"] ) self.assertEqual(args.release_series, "22.4") def test_update_project(self): - _, _, args = parse_args(["release", "--release-type", "patch"]) + _, _, args = parse_args(["create", "--release-type", "patch"]) self.assertTrue(args.update_project) _, _, args = parse_args( - ["release", "--release-type", "patch", "--update-project"] + ["create", "--release-type", "patch", "--update-project"] ) self.assertTrue(args.update_project) _, _, args = parse_args( - ["release", "--release-type", "patch", "--no-update-project"] + ["create", "--release-type", "patch", "--no-update-project"] ) self.assertFalse(args.update_project) + def test_github_pre_release(self): + _, _, args = parse_args( + ["create", "--release-type", "patch", "--github-pre-release"] + ) + + self.assertTrue(args.github_pre_release) + class SignParseArgsTestCase(unittest.TestCase): def test_sign_func(self):