Skip to content

Commit

Permalink
Add release next version command
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed Apr 28, 2021
1 parent 53c3175 commit 0295331
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 6 deletions.
10 changes: 10 additions & 0 deletions docs/usage/cli_changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Manipulate `CHANGELOG.md` file, extracting relevant information.
Used within the [package](cli_package) and [release](cli_release) commands to populate the `metadata.txt` and the GitHub Release description.

It also provides two keywords `next` and `latest` instead of using a version number when creating a zip.

## Command help

```bash
Expand All @@ -25,6 +27,14 @@ The `CHANGELOG.md` file must follow the convention [Keep A Changelog](https://ke
- Extract the `CHANGELOG.md` content and copy it into the `changelog` section within plugin `metadata.txt`
- Extract the `n` latest versions from `CHANGELOG.md` into `metadata.txt`
- Get the latest version release note
- When packaging or releasing, you can use these keywords :
- `latest` will make a package of the latest tag described in the changelog file.
- `next` will make a package of the possible smallest higher tag :
- `3.4.0` -> `3.4.1-alpha`
- `3.4.0-alpha` -> `3.4.1-alpha.1`
- `3.4.0-alpha1` -> `3.4.1-alpha2`

Be careful when you use the `next` command. It is designed to make a package which is not based on a specific version (on CI mainly). You should be careful with the tag you are creating if you have some packages delivered as well with the `next` command otherwise QGIS Plugin manager might not warn users about possible new release.

## Examples

Expand Down
40 changes: 35 additions & 5 deletions qgispluginci/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
)
from qgispluginci.parameters import Parameters
from qgispluginci.translation import Translation
from qgispluginci.utils import configure_file, parse_tag, replace_in_file
from qgispluginci.utils import add_in_file, configure_file, parse_tag, replace_in_file


def create_archive(
Expand Down Expand Up @@ -101,6 +101,20 @@ def create_archive(
"version={}".format(release_version),
)

# Git SHA1
add_in_file(
"{}/metadata.txt".format(parameters.plugin_path),
"git_sha1={}".format(repo.head.object.hexsha),
)

# Date/time in UTC
add_in_file(
"{}/metadata.txt".format(parameters.plugin_path),
"date_time={}".format(
datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
),
)

# set the plugin as experimental on a pre-release
if is_prerelease:
replace_in_file(
Expand Down Expand Up @@ -372,6 +386,25 @@ def upload_plugin_to_osgeo(username: str, password: str, archive: str):
sys.exit(1)


def check_release_keywords(release_version: str) -> str:
""" Check if we are releasing some special version shortcut. """
if release_version not in ("latest", "next"):
return release_version

parser = ChangelogParser()
if not parser.has_changelog():
raise Exception(
"Not possible to determine the latest tag without a changelog file."
)

if release_version == "latest":
return parser.latest_version()

# Next tags
latest_version = parse_tag(parser.latest_version())
return latest_version.next_version().version


def release(
parameters: Parameters,
release_version: str,
Expand Down Expand Up @@ -414,10 +447,7 @@ def release(
disable_submodule_update
If omitted, a git submodule is updated. If specified, git submodules will not be updated/initialized before packaging.
"""

if release_version == "latest":
parser = ChangelogParser()
release_version = parser.latest_version()
release_version = check_release_keywords(release_version)

if transifex_token is not None:
tr = Translation(
Expand Down
9 changes: 9 additions & 0 deletions qgispluginci/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ def replace_in_file(file_path: str, pattern, new: str, encoding: str = "utf8"):
f.write(content)


def add_in_file(file_path: str, new_line: str, encoding: str = "utf8"):
""" Add a line in a file. """
with open(file_path, "r", encoding=encoding) as f:
content = f.read()
content += "{}\n".format(new_line)
with open(file_path, "w", encoding=encoding) as f:
f.write(content)


def configure_file(source_file: str, dest_file: str, replace: dict):
with open(source_file, "r", encoding="utf-8") as f:
content = f.read()
Expand Down
33 changes: 33 additions & 0 deletions qgispluginci/version_note.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,36 @@ def version(self) -> str:
return f"{self.major}.{self.minor}.{self.patch}-{self.prerelease}"
else:
return f"{self.major}.{self.minor}.{self.patch}"

def increment_pre_release(self) -> str:
""" Increment the pre-release string. """
items = self.prerelease.split(".")

numbers = "".join([i for i in self.prerelease if i.isdigit()])

if len(items) == 1:
if numbers:
return f"{self.prerelease[0:-len(numbers)]}{int(numbers) + 1}"
else:
return f"{self.prerelease}.1"

return f"{items[0]}.{int(numbers) + 1}"

def next_version(self) -> NamedTuple:
""" Increment the pre-release string or the patch. """
# "pre" is not supported by QGIS
# https://github.com/qgis/QGIS/blob/master/python/pyplugin_installer/version_compare.py
if not self.prerelease:
return VersionNote(
major=self.major,
minor=self.minor,
patch=str(int(self.patch) + 1),
prerelease="alpha",
)

return VersionNote(
major=self.major,
minor=self.minor,
patch=self.patch,
prerelease=self.increment_pre_release(),
)
30 changes: 29 additions & 1 deletion test/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from qgispluginci.changelog import ChangelogParser
from qgispluginci.exceptions import GithubReleaseNotFound
from qgispluginci.parameters import DASH_WARNING, Parameters
from qgispluginci.release import release
from qgispluginci.release import check_release_keywords, release
from qgispluginci.translation import Translation
from qgispluginci.utils import replace_in_file

Expand Down Expand Up @@ -179,6 +179,34 @@ def test_release_changelog(self):
f"changelog detection failed in release: {data}",
)

def test_release_latest(self):
""" Test releasing the latest version. """
release(self.parameters, "latest")
archive_name = self.parameters.archive_name(
self.parameters.plugin_path, check_release_keywords("latest")
)
with ZipFile(archive_name, "r") as zip_file:
data = zip_file.read("qgis_plugin_CI_testing/metadata.txt")
self.assertEqual(
data.find(b"version=latest"), -1
) # Version is the one in __about__.py
self.assertGreater(data.find(b"git_sha1="), 0)
self.assertGreater(data.find(b"date_time="), 0)

def test_release_next(self):
""" Test releasing the next version. """
release(self.parameters, "next")
archive_name = self.parameters.archive_name(
self.parameters.plugin_path, check_release_keywords("next")
)
with ZipFile(archive_name, "r") as zip_file:
data = zip_file.read("qgis_plugin_CI_testing/metadata.txt")
self.assertEqual(
data.find(b"version=next"), -1
) # Version is the one in __about__.py
self.assertGreater(data.find(b"git_sha1="), 0)
self.assertGreater(data.find(b"date_time="), 0)


if __name__ == "__main__":
unittest.main()
16 changes: 16 additions & 0 deletions test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ def test_version_note_from_tag(self):
self.assertIsNone(version.prerelease)
self.assertFalse(version.is_prerelease)

def test_next_version(self):
""" Test to guess the next version. """
self.assertEqual(parse_tag("10.1.0").next_version().version, "10.1.1-alpha")
self.assertEqual(
parse_tag("10.1.0-beta").next_version().version, "10.1.0-beta.1"
)
self.assertEqual(
parse_tag("10.1.0-beta1").next_version().version, "10.1.0-beta2"
)
self.assertEqual(
parse_tag("10.1.0-beta.2").next_version().version, "10.1.0-beta.3"
)
self.assertEqual(
parse_tag("10.1.0-rc.10").next_version().version, "10.1.0-rc.11"
)


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

0 comments on commit 0295331

Please sign in to comment.