Skip to content
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

Add a command to read and update (i.e., bump) the project version, e.g., uv version #6298

Open
cauebs opened this issue Aug 21, 2024 · 48 comments · May be fixed by #7248
Open

Add a command to read and update (i.e., bump) the project version, e.g., uv version #6298

cauebs opened this issue Aug 21, 2024 · 48 comments · May be fixed by #7248
Labels
enhancement New feature or improvement to existing functionality projects Related to project management capabilities

Comments

@cauebs
Copy link

cauebs commented Aug 21, 2024

✅ Both Rye and Poetry have this, and it's quite useful both...

  • to avoid manually incrementing the version number (and potentially making a mistake there with the digits),
  • and to have this field on the pyproject.toml file serve as the single source of truth for a project's version, easily accessible (via uv) in CI workflows, etc.

🛑 The latter is where my personal interests lie: I have a CI workflow that tags and deploys releases when the version is bumped, currently using Poetry for it. I don't really want to pull in an additional tool to parse the project specs, so it's currently keeping me from considering migrating to uv.

📜 My proposal is replacing the current functionality of the version subcommand with this, since uv's version can already be accessed via the -V | --version option, and other project management currently exist as "root" subcommands.

ℹ️ I'm willing to give this one a go myself if maintainers greenlight the proposal.

@zanieb zanieb added enhancement New feature or improvement to existing functionality projects Related to project management capabilities labels Aug 21, 2024
@JonZeolla
Copy link

JonZeolla commented Aug 22, 2024

Would maintaining version identifiers outside of pyproject.toml be considered out of scope for uv? For instance, updating something like a __version__ in a src/package/__init__.py?

Or, even better, support a dynamic version like hatch does with a

[project]
dynamic = ["version"]

[tool.hatch.version]
path = "src/package/__init__.py"

@DeadNews
Copy link

It's most convenient to me to have git tag based versioning:

https://github.com/mtkennerly/poetry-dynamic-versioning

I would love to have this functionality.

@raayu83
Copy link

raayu83 commented Aug 29, 2024

Would also love to see this... I'm currently using poetry-version-plugin in versioned projects and want to switch them to uv

@menzenski
Copy link

Also very interested in this feature. This kind of read/update version command seems very common (not only Poetry but npm, etc) and it'd make migration to uv from other tools that much more straightforward.

Would maintaining version identifiers outside of pyproject.toml be considered out of scope for uv? For instance, updating something like a version in a src/package/init.py?

@JonZeolla I've used PDM's dynamic versioning in the past (which is essentially the same as the Hatch example you provide) but have found it kind of annoying in practice. IMO it's preferable to have the version in pyproject.toml be the source of truth. That version can be exposed in the Python package using importlib.metadata.version:

[tool.poetry]
name = "my-package"
version = "1,2,3"
# my_package/__init__.py

from importlib.metadata import version

__version__ = version("my_package")

@raayu83
Copy link

raayu83 commented Sep 5, 2024

Personally I also like the idea of basing the version on the current git tag when using together with CI/CD.
In that case it would be great if there was a command to set the version in pyproject.toml to the value of the git tag.

@HenriBlacksmith
Copy link

Personally I also like the idea of basing the version on the current git tag when using together with CI/CD.

In that case it would be great if there was a command to set the version in pyproject.toml to the value of the git tag.

Covering what bump-my-version (and previously bumpversion) do would cover that (including customizing the git tag and commit message format)

An interesting addition would be to have a way to trigger a custom
script to bump the CHANGELOGs like a hook to a python script.

An even better but probably too opinionated option could be to add a CHANGELOG management system (like changie) but it might be out of scope of uv?

@phi-friday
Copy link

phi-friday commented Sep 7, 2024

For others who need this.

uvx --from=toml-cli toml set --toml-path=pyproject.toml project.version $VERSION

I'm using it like this in github action.

VERSION=$(uvx dunamai from any --no-metadata --style pep440)
uvx --from=toml-cli toml set --toml-path=pyproject.toml project.version $VERSION
uv build

@nrbnlulu nrbnlulu linked a pull request Sep 10, 2024 that will close this issue
@daviewales
Copy link

Consider how poetry does it: https://python-poetry.org/docs/cli#version

My workflow looks like this:

# Show current version
poetry version

# Bump version
poetry version minor

# Add a git tag with a matching version to what's in pyproject.toml
git tag "v$(poetry version -s)"

Poetry tries to be clever to avoid needing an option to specify whether you are auto-bumping or manually setting a version:

The new version should be a valid PEP 440 string or a valid bump rule: patch, minor, major, prepatch, preminor, premajor, prerelease

This assumes that no-one will ever want to use one of those strings as a version, but that seems like a reasonably safe assumption.

@pkucmus
Copy link

pkucmus commented Sep 12, 2024

With hatch even when you have the version set as dynamic and red from an example __about__.py module and you bump hatch version $(git describe --broken --tags --always --dirty) (that what I do on build in CI/CD) it will actually change the python module. Which is kinda nice.

@phi-friday
Copy link

With hatch even when you have the version set as dynamic and red from an example __about__.py module and you bump hatch version $(git describe --broken --tags --always --dirty) (that what I do on build in CI/CD) it will actually change the python module. Which is kinda nice.

Using uvx hatch version ... is mostly fine, but I can't use it when it's a stub only package because there is no *.py.

@david-waterworth
Copy link

I'd love to see something like this as well - I currently use python-semantic-version but that uses SemVer rather than PEP440 - which causes a few minor issues such as not being able to parse tags that are valid PEP440 but not SemVer git tags (i.e. tags we added before migrating to PSV). It also has a nice CHANGELOG generation module, and the ability to generate release or dev version based on branch name (main vs feature). Version bumping rules are based on commit message parsing (i.e. if message starts with feat: bump minor version, if fix: bump patch etc.). As part of the PSV build process, all files that are modified (i.e. pyproject.toml, version.py) are staged, committed and pushed. The commit is also tagged with the version. You can then filter by the commit message in your CI pipeline to prevent infinite recursion.

@zanieb
Copy link
Member

zanieb commented Oct 14, 2024

As a workaround, I use this in my project:

sed -i -e "s/0.0.0/${GITHUB_REF#refs/*/}/" pyproject.toml

https://github.com/astral-sh/packse/blob/70abfe8f64a9746452c02cb514942f879c7eaccc/.github/workflows/release.yaml#L34-L36

@struckchure
Copy link

As a workaround, I use this in my project:

sed -i -e "s/0.0.0/${GITHUB_REF#refs/*/}/" pyproject.toml

https://github.com/astral-sh/packse/blob/70abfe8f64a9746452c02cb514942f879c7eaccc/.github/workflows/release.yaml#L34-L36

Exactly what I did, I just wasn't comfortable w/ it

rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Use the just runner in CI to avoid differing invocations in the
  project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Use the just runner in CI to avoid differing invocations in the
  project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Use the just runner in CI to avoid differing invocations in the
  project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
rumpelsepp added a commit to Fraunhofer-AISEC/gallia that referenced this issue Dec 19, 2024
- Use justfile instead of Makefile, since the release script can be
  integrated natively: `just release patch`. Might be possible to even
  include this in pyproject.toml since `uv` will provide a task runner
  (astral-sh/uv#5903) that might be based on
  just.

- Adjust the linting checks in the CI to run against the whole project.

- Use the just runner in CI to avoid differing invocations in the
  project.

- Add commitizen for bumping the release. This was provided by poetry in
  the past. I make too many mistakes without a tool here. In the future,
  this will be covered by uv as well: astral-sh/uv#6298

- next… let's try to release a dev release and let's have a look if the
  pipeline works correctly.
@leandrodamascena
Copy link

Hello uv team!

The "uv version" feature for updating project versions is crucial for projects with frequent alpha/dev releases. Currently, Poetry's simple command poetry version prerelease --short makes this very easy. The lack of a similar feature in uv is preventing us from replacing poetry with uv, as managing versions via scripts is impractical for fast release cycles.

Is there a roadmap or timeline for implementing this functionality in uv?

Thanks

@tipanverella
Copy link

The simplest solution I can envision is to run:

  • uvx poetry version
  • uvx poetry version patch
  • uvx poetry version minor
  • uvx poetry version major

@mirkolenz
Copy link

mirkolenz commented Jan 11, 2025

To update the version, I use the following workaround:

sed -i 's/^version = ".*"$/version = "NEW_VERSION"/' pyproject.toml && uv lock

@Kavan72
Copy link

Kavan72 commented Jan 15, 2025

The uv version command already exists, so I need to come up with a design to either phase that out in favor this functionality or choose a new command name.

Basically, that part isn't trivial and we're doing a lot of other things.

One option could be to change uv version to uv self version, as uv version currently displays the version of the installed uv on the system. after

uv version 
uv version patch
.....

There’s a rule to keep in mind: if you want to create something new, you may need to break something old.

@mardiros
Copy link

@Kavan72

One option could be to change uv version to uv self version, as uv version currently displays the version of the installed uv on the system. after

I completely agree, note that:

𝝿 uv self --version
uv-self 0.5.18 (27d1bad55 2025-01-11)

@bw-matthew
Copy link

You can read the pyproject file and print the version with the following:

uv run --python 3.12 -- \
    python -c '
import tomllib, pathlib
file = pathlib.Path("pyproject.toml")
metadata = tomllib.loads(file.read_text())
print(metadata["project"]["version"])
'

Need to use a python version that has tomllib (i.e. 3.11 or greater).

@engeir
Copy link

engeir commented Jan 22, 2025

Expanding on the answer in #6298 (comment), the following bash script can both print and increment versions:

#!/usr/bin/env bash

v="$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)"
if [ -z "$1" ]; then
  echo "$v"
  exit 0
fi
uvx --from bump2version bumpversion --allow-dirty --current-version "$v" "$1" pyproject.toml

Further, if you use mise, you may get tab-completion with the following task (run as mise run bump or with mise run aliased to mr, mr bump):

# .mise.toml
[tasks.bump]
description = "Bump the python package version. Takes one argument: `major`, `minor` or `patch`."
quiet = true
usage = '''
arg "[semver]" help="The SemVer name that should be incremented." {
  choices "major" "minor" "patch"
}
'''
run = """
#!/usr/bin/env bash

v="$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)"
if [ -z {{arg(name="semver")}} ]; then
  echo "$v"
  exit 0
fi
uvx --from bump2version bumpversion --allow-dirty --current-version "$v" {{arg(name="semver")}} pyproject.toml
"""

@thclark
Copy link

thclark commented Jan 26, 2025

Inspired by one of the comments above, here's my GitHub action for getting version which is a workaround for at least one small chunk of the functionality being discussed here:

      - name: Install uv
        uses: astral-sh/setup-uv@v5

      - name: Get package version
        id: version
        run: |
          VERSION=$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)
          echo "package_version=$VERSION" >> $GITHUB_OUTPUT

@Kavan72
Copy link

Kavan72 commented Feb 5, 2025

@zanieb Any updates on this? Almost everyone who uses UV as a package manager needs this feature 😁.

@jake-dunn
Copy link

jake-dunn commented Feb 5, 2025

We've managed to get (what I think everyone else means by) this behaviour using setuptools_scm with uv:

https://pypi.org/project/setuptools-scm/
Explicilty in the pyproject.toml:

[project]
dynamic = ["version"]

[tool.setuptools_scm]

[build-system]
requires = ["setuptools>=64", "setuptools_scm>=8"]
build-backend = "setuptools.build_meta"

Hopefully this is helpful. Python packaging and distribution seems to be much more complex than I hoped.

@OverkillGuy
Copy link

Another alternative, for those who feel this is the last feature missing from uv to move over:
Accept that we don't care about current version as much as bumping, and

replace the package bumping command with `bump-my-version`.

Docs: https://callowayproject.github.io/bump-my-version/

Configured for your particular repo via pyproject.toml.

In my case:

[tool.bumpversion]
allow_dirty = false
commit = true
message = "Bump to version v{new_version}"
tag = true
tag_message = "Release v{new_version}"
setup_hooks = ["make"]  # Run 'make' as validation before starting

[[tool.bumpversion.files]]
filename = "pyproject.toml"
search = 'version = "{current_version}"'
replace = 'version = "{new_version}"'

[[tool.bumpversion.files]]
filename = "CHANGELOG.md"
search = "## [Unreleased]"
replace = "## [Unreleased]\n\n## v{new_version} - {now:%Y-%m-%d}"

Running it via:

bump-my-version bump patch

This does:

  • Update the actual version in pyproject.toml with semver meaning
  • Inserts the latest version marker + date in changelog's unreleased section
  • Commits the result with a specific message
  • Git tags the new version with specific message
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ The project uses semantic versioning (see [semver](https://semver.org)).

 ## [Unreleased]

+## v0.1.1 - 2025-02-06
+
 ### Fixed
 - No longer crashing on the bad thing

 ## v0.1.0 - 2025-01-20

 ### Added
diff --git a/pyproject.toml b/pyproject.toml
index eec4d73..d64caef 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3,7 +3,7 @@ name = "redis_backend"
 description = "A cool project"
 authors = ["..."]
 readme = "README.md"
-version = "0.1.0"
+version = "0.1.1"

So I call
make release BUMP=minor,
which runs this magic in Makefile

# Make a release commit + tag, creating Changelog entry
# Set BUMP variable to any of supported (major, minor, patch)
# See 'bump-my-version show-bump' for options
# Variable BUMP defaults to 'patch' (v1.2.3 -> v1.2.4)
.PHONY: release
BUMP=patch
release:
	uvx bump-my-version bump ${BUMP}

And to remind ourselves of the patterns, we can print the possible future versions:

$  uvx bump-my-version show-bump
0.1.1 ── bump ─┬─ major ─ 1.0.0
               ├─ minor ─ 0.2.0
               ╰─ patch ─ 0.1.2

I hope others like me will feel this is good enough to be unblocked, and move their life over to uv, and Be Happy.

... but I'd still love to get this natively in uv if we can ;)

@kwaegel
Copy link

kwaegel commented Feb 10, 2025

There are a number of workarounds posted so far, but I'll add one more to the list.

Target workflow.

  • Package version is automatically derived from the last Git tag.
  • make version prints the current package version.
  • make next-version $PART prints the next version, with the {major, minor, patch} sections incremented. This is used to create a new tag when CI merges an appropriately tagged PR.

Implementation:

  • I used the uv-dynamic-versioning plugin, which works with the hatchling build backend. Seems like it's intended to be a drop-in replacement for poetry-dynamic-versioning. This causes uv build to build package files with the correct version.
  • To print the current version, I use the dunamai CLI directly:
.PHONY: version
version:
	@uv run dunamai from git --bump --style pep440
  • To bump the version, using bump-my-version seemed like a moderately heavyweight dependency, so I ended up using the dunamai API directly from a tiny Python script called from the Makefile:
.PHONY: next-version
## Compute the next package version, using NEXT={major|minor|patch}
next-version:
	#@uv run bump-my-version show new_version --increment $(NEXT)  # Alternative
	@uv run python next_version.py $(NEXT)

next_version.py:

import sys
from dunamai import Version
bump_type = sys.argv[1]
index = {"major": 0, "minor": 1, "patch": 2}[bump_type]
version = Version.from_git(strict=True)
bumped_version = version.bump(index=index).serialize(format="{major}.{minor}.{patch}")
print(bumped_version)

Keeping my fingers crossed that this only needs to be a "temporary" workaround, but I'm not going to let it stop me from migrating some of our legacy build systems over to uv.

@Blindstars
Copy link

+1 - Would use this all day long in replacement of poetry version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement to existing functionality projects Related to project management capabilities
Projects
None yet
Development

Successfully merging a pull request may close this issue.