Skip to content

jjmaestro/bazel_version_utils

Repository files navigation

version_utils logo

version_utils

pre-commit CI

Bazel module to work with version schemes and version requirement specifications.

It currently supports semantic versions and Postgres versions, as well as semantic version requirement specifications such as NPM-style node-semver Ranges syntax.

Ideally, it will eventually expand to support additional versions (e.g. Debian versions and Debian version requirements).

📦 Install

First, make sure you are running Bazel with Bzlmod. Then, add the module as a dependency in your MODULE.bazel:

bazel_dep(name = "version_utils", version = "<VERSION>")

Non-registry overrides

If you need to use a specific commit or version tag from the repo instead of a version from the registry, add a non-registry override in your MODULE.bazel file, e.g. archive_override:

REF = "v<VERSION>"  # NOTE: can be a repo tag or a commit hash

archive_override(
    module_name = "version_utils",
    integrity = "",  # TODO: copy the SRI hash that Bazel prints when fetching
    strip_prefix = "bazel_version_utils-%s" % REF.strip("v"),
    urls = ["https://github.com/jjmaestro/bazel_version_utils/archive/%s.tar.gz" % REF],
)

NOTE: integrity is intentionally empty so Bazel will warn and print the SRI hash of the downloaded artifact. Leaving it empty is a security risk. Always verify the contents of the downloaded artifact, copy the printed hash and update MODULE.bazel accordingly.

🚀 Getting Started

version

This package provides extensions to work with different version schemes. It currently supports two version schemes: semantic versions and Postgres versions.

example: semantic versions

A semantic version can be created by parsing a string:

load("@version_utils//version:semver.bzl", "semver")

version = semver.parse("1.0.2-alpha+build.2025-01-15")

print(version.major, version.minor, version.patch)
# 1 0 2

print(version.prerelease)
# ("alpha",)

print(version.build)
# ("build", "2025-01-15")

print(version.to_str())
# 1.0.2-alpha+build.2025-01-15

It can also be created by specifying its named fields:

version = semver.new(major = 1, minor = 0, patch = 2)

print(version.major, version.minor, version.patch)
# 1 0 2

version = semver.new(major = 1, minor = 0)
# Error in fail: Invalid semantic version minor/patch value: None

Working with versions

Versions can be compared:

v1 = semver.parse('0.1.1')
v2 = semver.parse('0.1.2')
v3 = semver.parse('0.1.1-alpha.1')

res = v1.lt(v2)
print(res)
# True

res = v1.gt(v3)
print(res)
# True

res = v1.le(v3)
print(res)
# False

Versions can be incremented ("bumped") in any of their version fields:

version = semver.parse('1.0.0+build')

bumped = version.bump("patch")
print(bumped.to_str())
# 1.0.1

bumped = version.bump("minor")
print(bumped.to_str())
# 1.1.0

bumped = version.bump("major")
print(bumped.to_str())
# 2.0.0

and can be truncated up to any of their version fields:

version = semver.parse('1.2.3-pre.1+build.1')

truncated = version.truncate("build")
print(truncated.to_str())
# 1.2.3-pre.1+build.1

truncated = version.truncate("prerelease")
print(truncated.to_str())
# 1.2.3-pre.1

truncated = version.truncate("patch")
print(truncated.to_str())
# 1.2.3

truncated = version.truncate("minor")
print(truncated.to_str())
# 1.1.0

truncated = version.truncate("major")
print(truncated.to_str())
# 1.0.0

spec: Version Requirement Specifications

This package provides a spec extension to work with version requirement specifications.

It currently supports two syntaxes:

To begin, create a new Spec struct:

load("@version_utils//spec:spec.bzl", "spec")

simple = spec.new(">=0.1.0,<0.4.0")

npm = spec.new(">=0.1.0 <0.3.0", syntax = spec.SYNTAX.NPM)

The Spec struct has three methods:

  • spec.match: checks whether the given version satisfies the version requirement specification:
version = semver.parse("0.2.0")

print(simple.match(version))
# True

version = semver.parse("0.4.0")

print(simple.match(version))
# False
  • spec.filter: filters the versions in the iterable of versions that match the version requirements:
versions = [semver.parse("0.%d.0" % i) for i in range(6)]

for v in simple.filter(versions):
    print(v.to_str())
# 0.1.0
# 0.2.0
# 0.3.0

for v in npm.filter(versions):
    print(v.to_str())
# 0.1.0
# 0.2.0
  • spec.select: selects the highest version from an iterable of versions that matches the version requirements:
versions = [semver.parse("0.%d.0" % i) for i in range(6)]

v = npm.select(versions)

print(v.to_str())
# 0.2.0

📄 Docs

For more details about each component, check the documentation:

💡 Contributing

Please feel free to open issues and PRs, contributions are always welcome! See CONTRIBUTING.md for more info on how to work with this repo.

🫶 Acknowledgements

This Bazel module began as a Starlark port of python-semanticversion. Credit and thanks to its original author, @rbarrois!

About

Bazel module to work with version schemes and version requirement specifications

Resources

License

Stars

Watchers

Forks

Packages

No packages published