Automatically update project version info in sphinx documentation

From time to time I need to get project version information and use it somewhere - in project documentation, in About box or include it in website footer.

I use git for my projects, and find it very convenient to let git to provide version info instead of hardcoding it into the source code. There are several possible ways to ask git for version information, including keyword expansion - and some of them are described in this stackoverflow post. For me, git describe works best, since it doesn’t modify sources on checkout (comparing to keyword expansion) and provides version information in format that could be used in other git commands such as git diff.

git describe

git describe returns information about state of working tree or any particular commit. There are several command line switches to consider, but in most cases git describe --tags --always will work just fine for everyone. The command finds the most recent tag that is reachable from a commit, and if the commit itself is pointed at by the tag, shows the tag. Otherwise, it suffixes the tag name with the number of additional commits and the abbreviated object name of the commit.

% git describe --tags --always
v0.1.3-16-ge1b5922

Performance

Keep in mind that running git every time you need version information may not be the best idea. When source code changes are rare and performance is important (e.g. production website) it is wise to get information only once, then store it for later use. In other cases, when changes are often and performance is not critical, it may be ok to query git every time.

Example

Sphinx is a tool that makes it easy to create intelligent and beautiful documentation, and it is often used in Python world. Project version information is stored in Sphinx configuration file and is embedded auto-generated project documentation. Since Sphinx itself is written in Python, getting version info is simple. First, add the following lines to your docs/conf.py:

from subprocess import Popen, PIPE

def get_version():
"""
Returns project version as string from 'git describe' command.
"""
pipe = Popen('git describe --tags --always', stdout=PIPE, shell=True)
version = pipe.stdout.read()

if version:
    return version
else:
    return 'X.Y'

Then, replace hardcoded version and release values:

# The version info for the project you're documenting, acts as replacement for
# version and release, also used in various other places throughout the
# built documents.

# The short X.Y version.
version = get_version().lstrip('v').rstrip()
# The full version, including alpha/beta/rc tags.
release = version

Now Sphinx will call git describe --tags --always every time when documentation is generated and include your project vetsion information it in docs.

comments powered by Disqus