Skip to content

Scmversion #3606

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Scmversion #3606

wants to merge 2 commits into from

Conversation

behrmann
Copy link
Contributor

This commit changes the versioning scheme of non-release versions of mkosi to
align with the standard Python version scheme [1]. Unfortunately this scheme is
not fully compatible with the UAPI group version format specification.

Concretely, this changes

26~devel

to

25.3.post1.dev244+g0eac3718

The used format ensures that for prereleases the following inequalities still
hold

25.3 < 25.3.post1.dev244+g0eac3718 < 25.4 < 26

Usage of this new format has the following benefits:

  1. It is compatible with PyPI and allows publishing mkosi there in the future

  2. Since it contains the number of commits since the last tag as well as part
    of the commit hash in the "local part" of the version, it becomes easier for
    bug reporters to show the version they are on no matter how mkosi has been
    installed.

  3. The version no longer needs to be managed manually.

The current implementation moves the version from mkosi/sandbox.py to a new
file _version.py that obtains the version either via importlib metadata (in
case mkosi has been installed) or by calling setuptools-scm directly, to
support the bin/ shims. Since the version is no longer available in
mkosi/sandbox.py, it passed as an environment variable for scripts.

[1] https://packaging.python.org/en/latest/specifications/version-specifiers/

@behrmann behrmann force-pushed the scmversion branch 2 times, most recently from 9a58e59 to 8f491df Compare March 20, 2025 17:52
Copy link
Contributor

@septatrix septatrix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the version fallback should happen in the bin/ scripts directly (i.e. they would set the env var) if that is the only way we encourage people to use it without installing it?

@septatrix
Copy link
Contributor

Also, what happens when people have installed (an older version) of mkosi via pip (or their distro) but call a local mkosi clone via the bin/ wrappers?

@behrmann behrmann force-pushed the scmversion branch 4 times, most recently from 28d7843 to 7fbc3be Compare March 20, 2025 20:48
@behrmann
Copy link
Contributor Author

Also, what happens when people have installed (an older version) of mkosi via pip (or their distro) but call a local mkosi clone via the bin/ wrappers?

Good catch, added a check for that.

@behrmann
Copy link
Contributor Author

Maybe the version fallback should happen in the bin/ scripts directly (i.e. they would set the env var) if that is the only way we encourage people to use it without installing it?

I think it's nicer to have it in the module, since it gives the power of both a proper language as well as making it unnecessery to implement this multiple times.

@behrmann behrmann force-pushed the scmversion branch 2 times, most recently from 6729251 to 6efdd7a Compare March 21, 2025 10:57
This should make it easier to install all necessary tools for development.
@behrmann behrmann marked this pull request as ready for review April 4, 2025 13:16
@behrmann
Copy link
Contributor Author

behrmann commented Apr 4, 2025

I've tested this with for mkosi, mkosi-addon, mkosi-initrd and mkosi-sandbox

  • called as Python modules while in the repo
  • via the shims while in the repo
  • via the shims with a different working directory
  • via the shims symlinked into PATH
  • installed in a virtual environment generated with the standard library and installed via pip
  • installed in a virtual environment generated with the standard library and installed via pip as an editable install
  • installed in a virtual environment generated with uv and installed via uv pip
  • installed in a virtual environment generated with uv and installed via uf pip as an editable install
  • running the modules from an unpacked tarball
  • running the shims from an unpacked tarball
  • running a zipapp

All of them with a distribution mkosi installed and not installed. All output a version like 25.3.post1.dev244+g293af6b3.d20250404 except for the tarballs, which show the version from the static file.

@behrmann behrmann force-pushed the scmversion branch 4 times, most recently from e759d2b to a98652e Compare April 5, 2025 17:34
This commit changes the versioning scheme of non-release versions of mkosi to
align with the standard Python version scheme [1]. Unfortunately this scheme is
not fully compatible with the UAPI group version format specification.

Concretely, this changes

    26~devel

to

    25.3.post1.dev244+g0eac3718

The used format ensures that for prereleases the following inequalities still
hold

    25.3 < 25.3.post1.dev244+g0eac3718 < 25.4 < 26

Usage of this new format has the following benefits:

1. It is compatible with PyPI and allows publishing mkosi there in the future

2. Since it contains the number of commits since the last tag as well as part
   of the commit hash in the "local part" of the version, it becomes easier for
   bug reporters to show the version they are on no matter how mkosi has been
   installed.

3. The version no longer needs to be managed in multiple places.

The current implementation moves the version from mkosi/sandbox.py to a new
file _version.py that obtains the version either via importlib metadata (in
case mkosi has been installed) or by calling setuptools-scm directly, to
support the bin/ shims. Since the version is no longer available in
mkosi/sandbox.py, it passed as an environment variable for scripts.

[1] https://packaging.python.org/en/latest/specifications/version-specifiers/
Comment on lines +43 to +62
def version_from_git() -> Optional[str]:
try:
p = subprocess.run(
["git", "describe"],
cwd=Path(__file__).parent.parent,
check=True,
text=True,
capture_output=True,
)
# output has form like v25.3-244-g8f491df9 when not on a tag, else just the tag
tag, *rest = p.stdout.strip().split("-")
tag = tag.lstrip("v")
if rest:
numcommits, commit = rest
return f"{tag}.post1.dev{numcommits}+{commit}.d{datetime.datetime.now():%Y%m%d}"

# we are exactly on a tag
return tag
except (subprocess.CalledProcessError, NotADirectoryError, FileNotFoundError):
return None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this completely goes against the convention we adopted in systemd to have the devel version be of the next version we've developing, which is fundamentally incompatible with git describe since that will always return the latest tag which is the previous version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To document the current state for others:

We're a bit between the rock of UAPI version format spec and the hard place of Python's public version identifiers.

Both are compatible as far as the set of allowed characters for Python's scheme is (mostly) subset (disregarding the local part divided by + and the epoch divided by !, but systemd-analyze compare-version will happily treat them as separators, so that's fine), unfortunately the semantics are different. Whereas the UAPI spec follows RPM an .deb and has sigils that raise or lower a version, allowing not having to keep state and being able to compare version strings character by character, Python has multicharater substrings like .dev or .rc that take their place.

Using a version scheme anchored on the last release and counting commits since, allows to fit into both schemes, as described above, since this will hold

25 < 25.3 < 25.3.post1.dev244+g0eac3718 < 25.4 < 26

Unfortunately, there is no way to construct a version starting with the next release number, that compares smaller than that release under both the UAPI version spec and Python's, e.g. 26rc244 would compare smaller than 26 in under Python's scheme, but compares larger under the UAPI scheme, simply because it is shorter.

@behrmann behrmann marked this pull request as draft April 8, 2025 14:48
@behrmann behrmann marked this pull request as ready for review May 12, 2025 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants