Switch to better version management with Python
Description of feature
Adopt some sort of tool to directly grab the version string from the git tag, instead of hard-coding it manually in the code. I think we've all made mistakes in versioning and the __version__ is not guaranteed to be 100% correct.
Note that this applies to all MDOLab-related packages so perhaps this is a worthy topic at the maintenance meeting? CC @eirikurj. I'd be happy to help prototype/implement.
Potential solution
Candidates include
- setuptools_scm which I have successfully used in the past
- versioneer which has more stars but has not had a release in ~2 years.
- bump-my-version (previously bump2version) can be applied manually or part of a build process
I recall us discussing this in the past and I am all for it. There are some other tools also available with a more manual approach, like bump-my-version (previously bump2version). Added this to the candidate list above.
IMO using these tools seems like a lot of work just to avoid updating a single number in a repo. To me, the versioning mistakes we make most often is that we bump the version in the code and then never make the corresponding tag/release or that we make a new release without having updated the version in the code. We could probably come up with a github action to automatically spot when the version number has changed and then make a release. This would fix both issues.
My proposed workflow for setuptools_scm is fairly simple:
- User merges in a PR but does not alter the version string at all
- User makes a release, this tags the latest commit on the default branch
That's it. The version string is generated from the tag when we build the package (for PyPI this is done in GHA, for local install this happens when you run pip install .). The only downside is that, the string is no longer hard-coded in the package, which means that in an editable install, querying <package>.__version__ is not guaranteed to return the correct version but rather the last version that was installed (even if you ran in editable mode). But if you are running in editable install then the version string is semi-useless anyhow. Setting up this system should require pretty minimal changes to the code/infrastructure (maybe 10-20 lines IIRC).
My main concern with relying on the number in the repo is that, not only do we forget to make the release sometime, but also we may merge a PR that bumps the version but then intentionally wait for another PR before actually releasing the package. This dissociation between the tag (the actual source of truth) and the version string cannot be solved unless we do one of two things
- Treat the tag as the truth -- this is my preferred option and is what is proposed here.
- Treat the version string as the source of truth and set up GHA to make releases based on this. IMO this is very error-prone and requires more effort/maintenance.
Yeah perhaps I was a little strong in my opinion there. I was just a little concerned that these systems all seem to rely on pyproject.toml files and I wasn't sure that will interact with our setup.py based projects, and that it may vary from package to package. Regardless, of the 3 you have above, setuptools_scm seems like the best option.