Skip to content

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

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

Closed
cauebs opened this issue Aug 21, 2024 · 79 comments · Fixed by #12349
Closed

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 · 79 comments · Fixed by #12349
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

@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

@krishan-patel001
Copy link

  1. Do you just need this on release?

No we need this throughout different stages of development.

  1. If so, would your need be served by (as an example) uv release which does a version bump, uv build, and uv publish? As a minor note, if we go this direction we'd definitely need a way to separate version bumps from build for things like committing that change separately, e.g., uv release --prepare --bump-version minor then uv release. The goal here isn't to design the final interface, but explore the concept, so take the examples with a grain of salt.

No, as we bump versions on applications that aren't packages and therefore don't need to be built or published.

  1. Are there other use-cases for changing the version?

Yes, for unique github releases and tracking what version of code broke anything.

  1. When do you need to inspect the version? What do you do with the retrieved version?

We use the package version when creating releases. We don't use uv's version for anything.

  1. Are you currently using uv version to inspect uv's version?
    No
  1. Are you using semver? Are you using calver? How would you expect this to work in a calver project?
    We use semver
  1. How do you currently decide if a version should be patch, minor, or major?

Dependent on if we are doing a breaking change or not.

  1. Do you need to set a specific version number instead of bumping? Why?

To set unique dev versions per developer during development.

@nim65s
Copy link

nim65s commented Mar 5, 2025

  1. Do you just need this on release?

Yes

  1. If so, would your need be served by (as an example) uv release which does a version bump, uv build, and uv publish? As a minor note, if we go this direction we'd definitely need a way to separate version bumps from build for things like committing that change separately, e.g., uv release --prepare --bump-version minor then uv release. The goal here isn't to design the final interface, but explore the concept, so take the examples with a grain of salt.

I would prefer a way to let me tag a release, and let that tag trigger a github action that would build (for multiple OS / arch / python) and publish (throug Trusted Publisher workflow)

  1. Are there other use-cases for changing the version?

No

  1. When do you need to inspect the version? What do you do with the retrieved version?

I need both the current and updated ones to generate a commit which update the version number, date, and diff link in the changelog. I would not have to bake a script for that if uv provided hooks like cargo-release

  1. Are you currently using uv version to inspect uv's version?

No, uv --version seems more natural for that

  1. Are you using semver? Are you using calver? How would you expect this to work in a calver project?

Yes, yes (different projects). eg., given pyproject tool.uv.version-scheme = "YYYY.MINOR" ("semver' could be an alias for "MAJOR.MINOR.PATCH")

uv version # show current
uv version {major,minor,patch,micro} # bump a version component
uv version bump # bump date based components
  1. How do you currently decide if a version should be patch, minor, or major?

breaking changes / new features / any other reason

  1. Do you need to set a specific version number instead of bumping? Why?

No

Do you need to programmatically read or update other pyproject.toml fields? Like project.authors, project.requires-python, build-system, tool.uv.*, etc.

No

@ebits21
Copy link

ebits21 commented Mar 6, 2025

Do you just need this on release?

No

Are there other use-cases for changing the version?

No

When do you need to inspect the version? What do you do with the retrieved version?

Just for my personal knowledge.

Are you currently using uv version to inspect uv's version?

Rarely, as others have said uv —version seems more appropriate.

Are you using semver? Are you using calver? How would you expect this to work in a calver project?

Both. Calver I personally would want it to bump to the current date as yyyy.mm.dd but I’m sure there’s many ways to do this.

How do you currently decide if a version should be patch, minor, or major?

Major: breaking changes / minor: new features / patch: anything else.

Do you need to set a specific version number instead of bumping? Why?

Sometimes but I would just set it manually

Do you need to programmatically read or update other pyproject.toml fields? Like project.authors, project.requires-python, build-system, tool.uv.*, etc.

No

@daviewales
Copy link

This is what my current process looks like with Poetry.
I'd be hoping to replicate something like this with UV.

poetry version # show current version from pyproject.toml (includes project name)
poetry version minor # bump minor version in pyproject.toml
git tag "v$(poetry version -s)" # add git tag with current version from pyproject.toml (-s flag shows only the version number)
  1. I don't just need this on release.
  2. An all-in-one uv release command wouldn't suit my workflow. (For example, my PyPI deployments are automated with GitHub Actions which trigger when I push new version tags. So all I need is a way to bump the version and include it in a git tag.)
  3. I'm not sure what other usecases would be for changing the version?
  4. I sometimes want to interactively view the current version, without needing to inspect the pyproject.toml file. Other times, I want to fetch just the version number to include in a git tag.
  5. I do not use uv version. uv --version and uv -V are sufficient.
  6. I'm using semver. Note for calver that poetry version accepts either a valid PEP 440 version or a valid bump rule. Because the bump rules are not valid PEP 440 versions, this overloading works fine. So, for calver, a poetry user could set the version to the current date with: poetry version $(date +%Y.%m.%d) (This would work for rye version too.)
  7. Most of my projects are still in the 0.1.0 phase of semver, so breaking changes are minor and all other changes are patch. For projects which make it to 1.0.0, then breaking changes would be major, big non-breaking changes (new features) would minor, and everything else would be patch.
  8. I don't usually need to set a specific version number instead of bumping, but I can imagine that this would be a useful escape hatch.
  9. I haven't needed to programmatically read or update other pyproject.toml fields.

I may be biased as an existing Poetry user, but I think they get the API pretty right for poetry version.

@HenriBlacksmith
Copy link

A few suggestions/additions:

This could give commands like:

  • uv project version bump minor
  • uv project version show or even simply uv project version
  • uv project version show-bump
  • uv project add author (why not?)

The commands are a bit longer though (but those can easily be aliased).

@Gankra
Copy link
Contributor

Gankra commented Mar 20, 2025

We've got a PR up for an interface/implementation we're reasonably happy with: #12349

We might still make uv version sugar for uv metadata version if people really want but for now it's cleanest to not change the semantics of an existing command, and we want this metadata namespace claimed.

@ebits21
Copy link

ebits21 commented Mar 21, 2025

We've got a PR up for an interface/implementation we're reasonably happy with: #12349

We might still make uv version sugar for uv metadata version if people really want but for now it's cleanest to not change the semantics of an existing command, and we want this metadata namespace claimed.

Honest feedback: it’s pretty verbose command wise. I would love the uv version sugar as my 2 cents of feedback.

I personally like just uv bump as well.

Thanks for adding this! Very appreciative.

@zanieb
Copy link
Member

zanieb commented Mar 21, 2025

uv bump doesn't really make sense for the use-case of reading the version.

We're not particularly settled between uv metadata version and uv version though.

@ebits21
Copy link

ebits21 commented Mar 21, 2025

uv bump doesn't really make sense for the use-case of reading the version.

We're not particularly settled between uv metadata version and uv version though.

I get it.

I do think uv self version for uv’s version and uv version —bump is quite elegant.

@daviewales
Copy link

I do think uv self version for uv’s version and uv version —bump is quite elegant.

I feel that uv --version is better than uv self version.

uv version --bump is more explicit than uv version [patch|minor|major|version_string] (like Poetry), but I still think the latter is the most elegant, at the expense of disallowing versions called 'patch', 'minor' or 'major'.

@zanieb
Copy link
Member

zanieb commented Mar 23, 2025

uv --version isn't going anywhere — we just also have a whole uv self interface and that's where I'd expect a long-form command for uv to report its own version to be.

@dusktreader
Copy link

I think that there would be unnecessary confusion by having a subcommand named version and a root-command --version option. You're going to find yourself trying to help people understand the difference between uv version and uv --version constantly.

I think it makes a lot of sense to have a uv metadata version subcommand, but I have to say that typing out metadata every time is going to be irritating. What about shorting metadata to just meta. It still conveys the idea well but is much nicer to type.

I would be very excited about being able to type uv meta version --bump=minor in my projects soon.

@slingshotvfx
Copy link

One more vote for shorter being better. As the uv command I will probably use the most, I'd much rather type uv version minor than uv metadata version --bump minor every time.

uv --version or uv -v/-V or uv self version all seem very intuitive to me and --version/-v/-V in particular align with how poetry, npm, and python all work.

@HenriBlacksmith
Copy link

I think that there would be unnecessary confusion by having a subcommand named version and a root-command --version option. You're going to find yourself trying to help people understand the difference between uv version and uv --version constantly.

I think it makes a lot of sense to have a uv metadata version subcommand, but I have to say that typing out metadata every time is going to be irritating. What about shorting metadata to just meta. It still conveys the idea well but is much nicer to type.

I would be very excited about being able to type uv meta version --bump=minor in my projects soon.

The command syntax is not as important as the feature, setting aliases is quite easy for those who need them.

And for my use-cases, it will be used in CI hence typing the command is not a question.

And the coherence with Cargo is interesting too: https://doc.rust-lang.org/cargo/commands/cargo-metadata.html

Having more automations around that command would be awesome (optional/configurable git tag and commit on bump), having a way to template other files, etc.

@chrisrodrigue
Copy link

chrisrodrigue commented Mar 24, 2025

--version/-V is probably the most universal command line parameter there is (next to --help/-h). uv self version would be a welcome complement to the legacy --version parameter.

In case you’re unfamiliar, or if it’s been a while and you’ve forgotten, run this in your terminal:

python3 -c "import this"

I tend to concur with all of it, especially the last line.

The uv metadata namespace is a step in the right direction, but "metadata" is ambiguous. Which metadata are we talking about, uv metadata or project metadata? If we are targeting a project, uv project version might better reflect the intent.

In the same manner as uv tool, the uv project namespace could be added to collect all the commands that target projects (uv project add, uv project sync, uv project init, etc.), but the top-level commands should still be available since they make the common case fast.

In the case of uv version, I think that it could print the version of the project first, followed by the version of uv, along with some type of hint promoting the namespaced commands uv self version and uv project version.

The Concepts overview page gives a good list of what might be desirable to capture as command namespaces:

  • Projects (i.e. uv project version and uv project sync)
  • Tools (i.e. uv tool add)
  • Python (i.e. uv python list)

@mkk5
Copy link

mkk5 commented Mar 31, 2025

I didn’t have experience with poetry version, so I might be missing something, but what is the advantage of

pyproject.toml file serving as the single source of truth for a project's version

instead of using a git tag as the single version source, which, in my opinion, has certain advantages?

@slhck
Copy link

slhck commented Mar 31, 2025

I'd say: Because projects are not always shared as Git repositories (in particular the actual Python distributions), and not everyone might use Git. The pyproject.toml file should be a single source of truth for the project and its metadata.

@kwaegel
Copy link

kwaegel commented Apr 1, 2025

The current implementation errors the command on all operations if the version field is not defined (which I believe would be the case if dynamic = ["version"]).

If I'm reading the current PR correctly, it looks like it won't be able to read the dynamic version generated by a plugin? That's a bit unfortunate, since I'm not entirely sure how to extract that bit of information without using external tools that could get out of sync with the project file (e.g. uv run dunamai ...).

If the uv metadata version command can't/won't handle dynamically generated version strings, is there a best practice on how to handle that?

@codejunction
Copy link

Just a thought based on https://pypi.org/project/bumpver/

  1. uv project bump --major - for major version udpate. Eg: 1.9.11 -> 2.0.0
  2. uv project bump --minor - for minor version update. Eg: 1.8.11 -> 1.9.0
  3. uv project bump --micro/--patch - for micro or patch update. Eg: 1.9.11 -> 1.9.12

Gankra added a commit that referenced this issue Apr 24, 2025
…edits (#12349)

This is a reimplementation of #7248 with a new CLI interface.

The old `uv version` is now `uv self version` (also it has gained a
`--short` flag for parity).
The new `uv version` is now an interface for getting/setting the project
version.

To give a modicum of support for migration, if `uv version` is run and
we fail to find/read a `pyproject.toml` we will fallback to `uv self
version`. `uv version --project .` prevents this fallback from being
allowed.

The new API of `uv version` is as follows:

* pass nothing to read the project version
* pass a version to set the project version
* `--bump major|minor|patch` to semver-bump the project version
* `--dry-run` to show the result but not apply it
* `--short` to have the final printout contain only the final version
* `--output-format json` to get the final printout as json

```
$ uv version
myfast 0.1.0

$ uv version --bump major --dry-run
myfast 0.1.0 => 1.0.0

$ uv version 1.2.3 --dry-run
myfast 0.1.0 => 1.2.3

$ uv version 1.2.3
myfast 0.1.0 => 1.2.3

$ uv version  --short 
1.2.3

$ uv version  --output-format json 
{
  "package_name": "myfast",
  "version": "1.2.3",
  "commit_info": null
}
```

Fixes #6298
zanieb pushed a commit that referenced this issue Apr 29, 2025
…edits (#12349)

This is a reimplementation of #7248 with a new CLI interface.

The old `uv version` is now `uv self version` (also it has gained a
`--short` flag for parity).
The new `uv version` is now an interface for getting/setting the project
version.

To give a modicum of support for migration, if `uv version` is run and
we fail to find/read a `pyproject.toml` we will fallback to `uv self
version`. `uv version --project .` prevents this fallback from being
allowed.

The new API of `uv version` is as follows:

* pass nothing to read the project version
* pass a version to set the project version
* `--bump major|minor|patch` to semver-bump the project version
* `--dry-run` to show the result but not apply it
* `--short` to have the final printout contain only the final version
* `--output-format json` to get the final printout as json

```
$ uv version
myfast 0.1.0

$ uv version --bump major --dry-run
myfast 0.1.0 => 1.0.0

$ uv version 1.2.3 --dry-run
myfast 0.1.0 => 1.2.3

$ uv version 1.2.3
myfast 0.1.0 => 1.2.3

$ uv version  --short
1.2.3

$ uv version  --output-format json
{
  "package_name": "myfast",
  "version": "1.2.3",
  "commit_info": null
}
```

Fixes #6298
@zanieb zanieb closed this as completed in f401d9b Apr 29, 2025
@Francesco146
Copy link

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

since #12349 got merged, what's the new standard way to handle version bumps in github action?

@Gankra
Copy link
Contributor

Gankra commented Apr 30, 2025

I believe what you posted is, as of 0.7.1, equivalent to uv version $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