Automatic Github Pages generation from Sphinx documentation
Sphinx is a very common documentation tool which gobbles up ReStructuredText and other free-form markup formats and outputs great HTML, PDF and other formats. It is meant for reference manuals and API documentation due to its good integration with source code (especially Python). The libuv book is written using Sphinx so that it looks so good with minimum effort.
Sphinx uses make
to generate the HTML, which is great. The only problem is that deploying this to Github Pages requires multiple commands to switch branches to gh-pages
, pull in the source text, then cleanup the working copy and switch back to master
. This is boring after about one time, so I automated it, and I think other projects can benefit from it as well. Once you follow the instructions, running:
make gh-pages
will take the latest commit, switch to the gh-pages
branch, generate HTML, push it to Github, then clean everything up and switch back to master
.
NOTE: You need to commit or revert any working copy modifications before running this.
One-time commands
These steps only need to be run the first time when you want to generate Github Pages. First setup the branch to have no parents. Let me stress again the importance of making sure all changes are committed! Otherwise they’ll be lost.
$ cd repo
$ git checkout --orphan gh-pages
$ git rm -rf .
$ echo "First commit" > index.html
$ git add .
$ git commit -m "Just to create the branch."
$ git push origin gh-pages
Now the gh-pages branch is setup. We can start generating the actual pages instead of the current index.html
.
Set the source files
Edit the Sphinx Makefile
. Add a variable GH_PAGES_SOURCES
. This should be a list of the files/directories that contain the documentation sources. This will usually be only source
which contains the Sphinx reST docs, but if you are embedding external code or images, those directories have to be listed as well. In addition the Makefile
has to be in the list. For the libuv book it is:
GH_PAGES_SOURCES = source code libuv Makefile
Add the target
Create a target gh-pages
with the following commands (remember to use TABs in Makefiles):
gh-pages:
git checkout gh-pages
rm -rf build _sources _static
git checkout master $(GH_PAGES_SOURCES)
git reset HEAD
make html
mv -fv build/html/* ./
rm -rf $(GH_PAGES_SOURCES) build
git add -A
git ci -m "Generated gh-pages for `git log master -1 --pretty=short --abbrev-commit`" && git push origin gh-pages ; git checkout master
Here is how it goes. The checkout simply switches branches. Then we remove all the old data to prevent any rebuilding artifacts. Since the gh-pages
branch won’t have any of your original data, but only the HTML output, we need to pull the sources from the master
branch. Then we generate the HTML. We move these from the build
folder to the top level. Then we remove all the sources and the now empty build
folder. We stage all the changes. Finally the last line generates a commit message for the gh-pages
changes which is the first line of the latest commit on master
and pushes to Github. The reason the git checkout master
command is on the same line and semi-colon separated; if the push were to fail for some reason (network error, DAG inconsistency), I want to be returned to master in my working copy. If you don’t want this to happen, feel free to move it to a new line on its own.
Done!
You can now get back to your main task - writing great documentation. Whenever you have an urge to show it to the world, simply run make gh-pages
and your latest documentation is served fresh!