Skip to content

Commit

Permalink
Add options for non-Python projects
Browse files Browse the repository at this point in the history
Adds the '--current-version' option to the 'semverup'
command and the '--add-all' flag to 'publish' to avoid
needing to use Python package specific files like
'_version.py' or 'pyproject.toml'.

Signed-off-by: Eva Millán <[email protected]>
  • Loading branch information
evamillan committed Oct 6, 2023
1 parent ccf6754 commit 66932e8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 22 deletions.
39 changes: 24 additions & 15 deletions release_tools/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
help="Do not remove changelog entries from the repository.")
@click.option('--remote-branch', 'remote_branch', default="master",
help="Remote branch to push. Default 'master'.")
def publish(version, author, remote, only_push, no_cleanup, remote_branch):
@click.option('--add-all', is_flag=True,
help="Add all changed files to the release commit.")
def publish(version, author, remote, only_push, no_cleanup, remote_branch, add_all):
"""Publish a new release.
This script will generate a new release in the repository.
Expand All @@ -71,6 +73,10 @@ def publish(version, author, remote, only_push, no_cleanup, remote_branch):
When '--no-cleanup' argument is specified, do not remove changelog
entries.
By default, the release commit will include the version, pyproject,
release notes, news and authors files. To add all changed files to
the release commit use the `--add-all` flag.
VERSION: version of the new release.
AUTHOR: author of the new release (e.g. John Smith <[email protected]>)
Expand All @@ -88,7 +94,7 @@ def publish(version, author, remote, only_push, no_cleanup, remote_branch):
if not only_push:
if not no_cleanup:
remove_unreleased_changelog_entries(project)
add_release_files(project, version)
add_release_files(project, version, add_all)
commit(project, version, author)

if remote:
Expand Down Expand Up @@ -126,28 +132,31 @@ def rollback_add_release_files(project):
pass


def add_release_files(project, version):
def add_release_files(project, version, add_all):
"""Add to the repository all the files needed to publish a release."""

click.echo("Adding files to the release commit...", nl=False)

# Add version file
version_file = project.version_file
if add_all:
project.repo.add('-A')
else:
# Add version file
version_file = project.version_file

if not version_file:
rollback_add_release_files(project)
raise click.ClickException("version file not found")
if not version_file:
rollback_add_release_files(project)
raise click.ClickException("version file not found")

project.repo.add(version_file)
project.repo.add(version_file)

# Add pyproject.toml file
pyproject_file = project.pyproject_file
# Add pyproject.toml file
pyproject_file = project.pyproject_file

if not pyproject_file:
rollback_add_release_files(project)
raise click.ClickException("pyproject file not found")
if not pyproject_file:
rollback_add_release_files(project)
raise click.ClickException("pyproject file not found")

project.repo.add(pyproject_file)
project.repo.add(pyproject_file)

# Add release notes file
notes_file = os.path.join(project.releases_path, version + '.md')
Expand Down
27 changes: 20 additions & 7 deletions release_tools/semverup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
help="Increase only the defined version.")
@click.option('--pre-release', is_flag=True,
help="Create a new release candidate version.")
def semverup(dry_run, bump_version, pre_release):
@click.option('--current-version',
help="Use the given version instead of the version file.")
def semverup(dry_run, bump_version, pre_release, current_version):
"""Increment version number following semver specification.
This script will bump up the version number of a package in a
Expand All @@ -67,6 +69,10 @@ def semverup(dry_run, bump_version, pre_release):
properly, the script will get the type of every unreleased change
stored under 'releases/unreleased' directory.
If you don't want to use the version number stored in '_version.py',
use '--current-version=<VERSION NUMBER>' with the one you would like
to use.
Additionally, 'pyproject' file will also be updated. Take into
account this file must be tracked by the repository.
Expand Down Expand Up @@ -95,12 +101,17 @@ def semverup(dry_run, bump_version, pre_release):
except RepositoryError as e:
raise click.ClickException(e)

# Get the current version number
version_file = find_version_file(project)
current_version = read_version_number(version_file)

# Get the pyproject file
pyproject_file = find_pyproject_file(project)
if current_version:
try:
current_version = semver.parse_version_info(current_version)
except ValueError:
msg = "version number '{}' is not a valid semver string"
msg = msg.format(current_version)
raise click.ClickException(msg)
else:
# Get the current version number
version_file = find_version_file(project)
current_version = read_version_number(version_file)

# Determine the new version and produce the output
if bump_version:
Expand All @@ -109,6 +120,8 @@ def semverup(dry_run, bump_version, pre_release):
new_version = determine_new_version_number(project, current_version, pre_release)

if not dry_run:
# Get the pyproject file
pyproject_file = find_pyproject_file(project)
write_version_number(version_file, new_version)
write_version_number_pyproject(pyproject_file,
new_version)
Expand Down
12 changes: 12 additions & 0 deletions releases/unreleased/options-for-non-python-projects.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Options for non-Python projects
category: added
author: Eva Millán <[email protected]>
issue: null
notes: >
Add the `--current-version=VERSION_NUMBER` argument to
the `semverup` command to avoid looking for the version
in a `_version.py` file.
To include all changed files in the release commit, eg.
a `project.json` file where the version was changed
manually, add the `--add-all` flag to the `publish` command.
50 changes: 50 additions & 0 deletions tests/test_semverup.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
MOCK_REPOSIORY_ERROR = (
"Error: mock repository error"
)
INVALID_CURRENT_VERSION = (
r"Error: version number 'invalid' is not a valid semver string"
)


class TestSemVerUp(unittest.TestCase):
Expand Down Expand Up @@ -879,6 +882,53 @@ def test_get_next_version(self):
bump_version=case[1],
do_prerelease=case[2])

@unittest.mock.patch('release_tools.semverup.Project')
def test_current_version_arg(self, mock_project):
"""Check whether it uses the given --current-version instead of version file"""

runner = click.testing.CliRunner(mix_stderr=False)

with runner.isolated_filesystem() as fs:
version_file = os.path.join(fs, '_version.py')
mock_project.return_value.version_file = version_file

project_file = os.path.join(fs, 'pyproject.toml')
mock_project.return_value.pyproject_file = project_file

dirpath = os.path.join(fs, 'releases', 'unreleased')
mock_project.return_value.unreleased_changes_path = dirpath

self.setup_files(version_file, project_file, "0.1.0")
self.setup_unreleased_entries(dirpath)

# Run the script command
result = runner.invoke(semverup.semverup, args=['--current-version=2.0.0', '--dry-run'])
self.assertEqual(result.exit_code, 0)
self.assertEqual(result.stdout, "2.1.0\n")

@unittest.mock.patch('release_tools.semverup.Project')
def test_current_version_invalid_format(self, mock_project):
"""Check whether it fails when --current-version has an invalid format"""

runner = click.testing.CliRunner(mix_stderr=False)

with runner.isolated_filesystem() as fs:
version_file = os.path.join(fs, '_version.py')
mock_project.return_value.version_file = version_file

dirpath = os.path.join(fs, 'releases', 'unreleased')
mock_project.return_value.unreleased_changes_path = dirpath

self.setup_version_file(version_file, "0.1.0")
self.setup_unreleased_entries(dirpath)

# Run the script command
result = runner.invoke(semverup.semverup, args=['--current-version=invalid'])
self.assertEqual(result.exit_code, 1)

lines = result.stderr.split('\n')
self.assertRegex(lines[-2], INVALID_CURRENT_VERSION)


if __name__ == '__main__':
unittest.main()

0 comments on commit 66932e8

Please sign in to comment.