Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No next version #895

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 39 additions & 36 deletions pontos/release/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from dataclasses import dataclass
from enum import IntEnum, auto
from pathlib import Path
from typing import Optional, SupportsInt
from typing import Literal, Optional, SupportsInt, Union

import httpx

Expand Down Expand Up @@ -49,7 +49,7 @@ class ReleaseInformation:
last_release_version: Optional[Version]
release_version: Version
git_release_tag: str
next_version: Version
next_version: Optional[Version]

def write_github_output(self):
with ActionIO.out() as output:
Expand All @@ -58,7 +58,7 @@ def write_github_output(self):
)
output.write("release-version", self.release_version)
output.write("git-release-tag", self.git_release_tag)
output.write("next-version", self.next_version)
output.write("next-version", self.next_version or "")


class CreateReleaseReturnValue(IntEnum):
Expand Down Expand Up @@ -142,7 +142,7 @@ async def async_run( # type: ignore[override]
versioning_scheme: VersioningScheme,
release_type: ReleaseType,
release_version: Optional[Version],
next_version: Optional[Version],
next_version: Union[Version, Literal[False], None],
git_signing_key: str,
git_remote_name: Optional[str],
git_tag_prefix: Optional[str],
Expand Down Expand Up @@ -170,7 +170,9 @@ async def async_run( # type: ignore[override]
release_version: Optional release version to use. If not set the
to be released version will be determined from the project.
next_version: Optional version to set after the release.
If not set the next development version will be set.
If set to None the next development version will be set.
If set to False the version will not be changed after the
release. Default is to update to the next development version.
git_signing_key: A GPG key ID to use for creating signatures.
git_remote_name: Name of the git remote to use.
git_tag_prefix: An optional prefix to use for creating a git tag
Expand Down Expand Up @@ -315,49 +317,50 @@ async def async_run( # type: ignore[override]
self.print_error(str(e))
return CreateReleaseReturnValue.CREATE_RELEASE_ERROR

if not next_version:
if next_version is None:
next_version = calculator.next_dev_version(release_version)

if update_project:
try:
updated = project.update_version(next_version)
self.terminal.ok(
f"Updated version after release to {next_version}"
)
except VersionError as e:
self.print_error(
f"Error while updating version after release. {e}"
)
return (
CreateReleaseReturnValue.UPDATE_VERSION_AFTER_RELEASE_ERROR
)

for f in updated.changed_files:
self.terminal.info(f"Adding changes of {f}")
self.git.add(f)

# check if files have been modified and create a commit
status = list(self.git.status())
if status:
commit_msg = f"""Automatic adjustments after release
if next_version:
if update_project:
try:
updated = project.update_version(next_version)
self.terminal.ok(
f"Updated version after release to {next_version}"
)
except VersionError as e:
self.print_error(
f"Error while updating version after release. {e}"
)
return (
CreateReleaseReturnValue.UPDATE_VERSION_AFTER_RELEASE_ERROR
)

for f in updated.changed_files:
self.terminal.info(f"Adding changes of {f}")
self.git.add(f)

# check if files have been modified and create a commit
status = list(self.git.status())
if status:
commit_msg = f"""Automatic adjustments after release

* Update to version {next_version}
"""

self.terminal.info("Committing changes after release")
self.git.commit(
commit_msg, verify=False, gpg_signing_key=git_signing_key
)
self.terminal.info("Committing changes after release")
self.git.commit(
commit_msg, verify=False, gpg_signing_key=git_signing_key
)

if not local:
self.terminal.info("Pushing changes")
self.git.push(follow_tags=True, remote=git_remote_name)
if not local:
self.terminal.info("Pushing changes")
self.git.push(follow_tags=True, remote=git_remote_name)

self.release_information = ReleaseInformation(
last_release_version=last_release_version,
release_version=release_version,
git_release_tag=git_version,
next_version=next_version,
next_version=next_version or None,
)
if ActionIO.has_output():
self.release_information.write_github_output()
Expand Down
13 changes: 11 additions & 2 deletions pontos/release/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,23 @@ def parse_args(args) -> Tuple[Optional[str], Optional[str], Namespace]:
'released version. Examples: "1.2", "2", "22.4"',
)

create_parser.add_argument(
next_version_group = create_parser.add_mutually_exclusive_group()

next_version_group.add_argument(
"--next-version",
help=(
"Sets the next version in project definition "
"after the release. Default: set to next dev version"
),
)

next_version_group.add_argument(
"--no-next-version",
help="Don't set a next version after the release.",
dest="next_version",
action="store_false",
)

create_parser.add_argument(
"--git-remote-name",
help="The git remote name to push the commits and tag to",
Expand Down Expand Up @@ -178,7 +187,7 @@ def parse_args(args) -> Tuple[Optional[str], Optional[str], Namespace]:
)
create_parser.add_argument(
"--github-pre-release",
help="Enforce uploading a release as GitHub " "pre-release. ",
help="Enforce uploading a release as GitHub pre-release. ",
action="store_true",
)

Expand Down
94 changes: 94 additions & 0 deletions tests/release/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -2360,6 +2360,100 @@ def test_release_enforce_github_release(

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_no_next_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",
"--no-next-version",
]
)

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),
],
)
command_mock.update_version.assert_has_calls(
[
call(release_version, force=False),
],
)

self.assertEqual(
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(Path("MyProject.conf"))])
git_instance_mock.commit.assert_has_calls(
[
call(
"Automatic release to 0.0.2",
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:
Expand Down
20 changes: 20 additions & 0 deletions tests/release/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,26 @@ def test_next_version(self):

self.assertEqual(args.next_version, PEP440Version("1.2.3"))

def test_no_next_version(self):
_, _, args = parse_args(
["create", "--no-next-version", "--release-type", "patch"]
)

self.assertFalse(args.next_version)

def test_next_version_conflict(self):
with self.assertRaises(SystemExit), redirect_stderr(StringIO()):
parse_args(
[
"create",
"--release-type",
"patch",
"--no-next-version",
"--next-verson",
"1.2.3",
]
)

def test_release_type(self):
_, _, args = parse_args(["create", "--release-type", "patch"])

Expand Down