Release process


Update build dependencies:

$ pip install -U setuptools wheel twine

Create release branch from main:

$ git checkout -b release

Cleanup (remove all untracked files and directories):

$ git clean -f -d -x

Update help() output:

$ python

Set release version (remove .dev0 from $MAJOR.$MINOR[.$BUGFIX] version):

  • docs/

  • graphviz/


Document release:

  • remove (in development) from CHANGES.rst header

Run the tests, lint the code, and build the documentation:

$ python -m tox -r -- -W error  # --recreate, raise error on warning
$ python --disable-noqa
$ python -b doctest
$ python
$ git clean -f -d -x

Commit to release branch and push to origin:

$ git add *
$ git commit -m "release $MAJOR.$MINOR[.$BUGFIX]"
$ git push --set-upstream origin release

Build and check the release files:

$ python sdist bdist_wheel
$ python -m twine check --strict dist/*
  • dist/graphviz-$MAJOR.$MINOR[.$BUGFIX].zip

  • dist/graphviz-$MAJOR.$MINOR[.$BUGFIX]-py3-none-any.whl

If changes are needed (and go back to: Cleanup step):

$ git commit --amend --date=now

Tag with annotated release version tag:

$ git tag -a -m "$MAJOR.$MINOR[.$BUGFIX] release"

Bump post-release version to $MAJOR.$MINOR.[.$BUGFIX].dev0:

  • docs/

  • graphviz/


Document post-release:

  • add new Version $MAJOR.$MINOR[.$BUGFIX] (in development) heading to CHANGES.rst

Commit version bump to relase branch:

$ git commit -m "bump version for development"

Switch to main branch and merge release:

$ git switch master
$ git merge --ff-only release


Publish the release with twine:

$ python -m twine upload dist/*

Push main branch and push all new tags:

$ git push --tags

Update stable branch to the latest release:

$ git switch stable
$ git merge --ff-only $MAJOR.$MINOR[.$BUGFIX]
$ git push


Verify publication:

Install in default environment:

$ pip install -U graphviz
$ python -c "import graphviz; print((graphviz.__version__, graphviz.version()))"