Developing OnePower#

If you’re interested in developing OnePower – welcome! You should first read the guide to contributing. This page is about more technical details of how OnePower is developed, and its philosophy.

Branching and Releasing#

The aim is to make OnePowers’s releases as useful, comprehendible, and automatic as possible. This section lays out explicitly how this works (mostly for the benefit of the admin(s)).

Versioning#

The first thing to mention is that we will try to use strict semantic versioning. Thus the versions are MAJOR.MINOR.PATCH, with MAJOR including API-breaking changes, MINOR including new features, and PATCH fixing bugs or documentation etc. If you depend on onepower, you can set your dependency as onepower >= X.Y < X+1 and not worry that we’ll break your code with an update.

To mechanically handle versioning within the package, we use two methods that we make to work together automatically. The “true” version of the package is set with setuptools-scm. This stores the version in the git tag. There are many benefits to this – one is that the version is unique for every single change in the code, with commits on top of a release changing the version. This means that versions accessed via onepower.__version__ are unique and track the exact code in the package (useful for reproducing results). To get the current version from command line, simply do python setup.py --version in the top-level directory.

Branching#

For branching, the plan is to use a very similar model to git-flow. That is, we will have a dev branch which acts as the current truth against which to develop, and main essentially as a deployment branch. I.e., the dev branch is where all features are merged (and some non-urgent bugfixes). main is always production-ready, and corresponds to a particular version on PyPI. Features should be branched from dev, and merged back to dev. Hotfixes can be branched directly from main, and merged back there directly, as well as back into dev. Breaking changes must only be merged to dev when it has been decided that the next version will be a major version. We do not do any long-term support of releases (so can’t make hotfixes to v2.x when the latest version is 2.(x+1), or make a new minor version in 2.x when the latest version is 3.x). We have set the default branch to dev so that by default, branches are merged there. This is deemed best for other developers (not maintainers/admins) to get involved, so the default thing is usually right.

Note

Why not a more simple workflow like Github flow? The simple answer is it just doesn’t really make sense for a library with semantic versioning. You get into trouble straight away if you want to merge a feature but don’t want to update the version number yet (you want to merge multiple features into a nice release). In practice, this happens quite a lot.

Note

OK then, why not just use main to accrue features and fixes until such time we’re ready to release? The problem here is that if you’ve merged a few features into main, but then realize a patch fix is required, there’s no easy way to release that patch without releasing all the merged features, thus updating the minor version of the code (which may not be desirable). You could then just keep all features in their own branches until you’re ready to release, but this is super annoying, and doesn’t give you the chance to see how they interact.