From 48c0ffb11d12ea266b3a653633a257ccfa5d17fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Morosi?= Date: Wed, 27 Nov 2024 09:18:13 +0100 Subject: [PATCH 1/3] Add dev1 to VERSION file --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 937387f..4b3ec9b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -22.3 +22.3.dev1 From 585213204be2ae34012fb658c0c086682bc7949f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Morosi?= Date: Wed, 27 Nov 2024 12:15:26 +0100 Subject: [PATCH 2/3] Bump minor version So the new versioning using the number of commits doesn't mess up with the old one using the date --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4b3ec9b..2c34300 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -22.3.dev1 +22.4.dev1 From 8f066c9bc0c144b8e1544786e9043b733460f7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Morosi?= Date: Wed, 27 Nov 2024 15:12:59 +0100 Subject: [PATCH 3/3] Add script to build the wheel That script will correctly set the version according to the number of commits since the most recent tag --- .gitlab-ci.yml | 4 +- build_wheel.py | 151 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 build_wheel.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 092fc53..dc6f0d7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -223,9 +223,7 @@ upload-python-registry: - !reference [.linux-image, before_script] - python -m pip install twine script: - - CURRENT_DATE=$(date +"%Y%m%d%H%M") - - sed -i "s|[0-9][0-9.]*|&.${CURRENT_DATE}|" VERSION - - python -m pip wheel . -q --no-deps -C--python-tag=py3 -w build + - python build_wheel.py --update - python -m twine upload --skip-existing --repository-url https://${CI_SERVER_HOST}:${CI_SERVER_PORT}/api/v4/projects/202/packages/pypi build/*.whl diff --git a/build_wheel.py b/build_wheel.py new file mode 100644 index 0000000..007217e --- /dev/null +++ b/build_wheel.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +"""Build the wheel. + +dev1 in the version of the package is automatically replaced by the number +of commits since the last tagged version. + +A tag v..0 is automatically added to the commit if the major +or minor version changes. +""" +from __future__ import annotations +import sys +from pathlib import Path +import re +import tomllib + +from e3.main import Main +from e3.os.process import Run +from e3.log import getLogger + +logger = getLogger("build_wheel") + +ROOT_DIR = Path(__file__).parent + + +def run(cmd: list[str], fail_ok: bool | None = None) -> Run: + """Print a command, run it, and print the result. + + :param cmd: the command + :param fail_ok: allow the command to fail + :return: the Run instance + """ + logger.info(f"$ {' '.join(cmd)}") + p = Run(cmd, cwd=ROOT_DIR) + if p.status != 0 and not fail_ok: + logger.error(p.out) + sys.exit(1) + + logger.info(p.out) + return p + + +def main() -> None: + """Entrypoint.""" + main = Main() + + parser = main.argument_parser + parser.description = "Build the wheel" + parser.add_argument( + "--update", + action="store_true", + help="Tag the commit in case of version change", + ) + parser.add_argument( + "--last-tag", + help="Provide the last tagged version", + ) + + main.parse_args() + assert main.args + + # Find and read version file + with open(ROOT_DIR / "pyproject.toml", "rb") as f: + version_config = tomllib.load(f)["tool"]["setuptools"]["dynamic"]["version"] + + version_path = ROOT_DIR / ( + version_config["file"] + if "file" in version_config + else f'src/{version_config["attr"].replace(".", "/")}.py' + ) + with open(version_path) as f: + version_content = f.read() + + # Extract the . part. + # We will replace the dev1 part by the number of commits since the most + # recent tagged version + match = re.match(r"(?P\d+\.\d+)\.dev1", version_content) + if not match: + logger.error(f"No ..dev1 version found in {version_path.name}") + sys.exit(1) + + logger.info("Version is {}.dev1".format(version := match.group("version"))) + + # Find previous version from the most recent tag + tagged_version = main.args.last_tag + if not tagged_version: + # Need to unshallow the clone so we get the list of tags. + # That command can fail for an already complete clone + run(["git", "fetch", "--unshallow", "--tags"], fail_ok=True) + # Describe the most recent tag + p = run(["git", "describe", "--tags"]) + tagged_version = p.out + + # Format is v..(-)? with commits omitted if + # the current commit is also the one tagged + match = re.match( + r"v(?P\d+\.\d+)\.\d+(\-(?P\d+))?", tagged_version + ) + if not match: + logger.error( + "Expected v..(-)? " + f"format for tag {tagged_version}" + ) + sys.exit(1) + + # tagged_version_commits is None only if the current commit is also the one tagged + # so there is 0 commits since that tag + tagged_version_commits = match.group("commits") + version_patch = tagged_version_commits if tagged_version_commits is not None else 0 + logger.info( + "Tagged version {} commit(s) ago is {}".format( + version_patch, tagged_version := match.group("version") + ) + ) + + # Tag the commit with ..0 in case of version change. + # Don't tag if there's already a tag (tagged_version_commits is None) + if ( + main.args.update + and tagged_version_commits is not None + and version != tagged_version + ): + run(["git", "tag", f"v{version}.0"]) + + # Replace dev1 in the version file. + logger.info(f"Set version to {version}.{version_patch}") + with open(version_path, "w") as f: + f.write(version_content.replace("dev1", str(version_patch))) + + try: + # Build the wheel + run( + [ + sys.executable, + "-m", + "pip", + "wheel", + ".", + "-q", + "--no-deps", + "-C--python-tag=py3", + "-w", + "build", + ] + ) + finally: + # Revert change to version file + run(["git", "restore", str(version_path)], fail_ok=True) + + +if __name__ == "__main__": + main()