SCVersioning 2.2.1¶
A Sphinx extension that lets you build Sphinx docs for all versions of your project without needing special hosting services.
A Few Examples | |
alabaster |
sphinx_rtd_theme |
classic |
nature |
Project Links¶
- Documentation: https://robpol86.github.io/sphinxcontrib-versioning
- Source code: https://github.com/Robpol86/sphinxcontrib-versioning
- PyPI homepage: https://pypi.python.org/pypi/sphinxcontrib-versioning
Installation¶
Getting started is pretty simple. The first step is to install the library.
Pip Install¶
The easiest way to get SCVersioning is to use pip. Simply run this command.
pip install sphinxcontrib-versioning
Latest from GitHub¶
You can also elect to install the latest bleeding-edge version by using pip to install directly from the GitHub repository.
pip install git+https://github.com/Robpol86/sphinxcontrib-versioning.git
Clone and Install¶
Lastly you can also just clone the repo and install from it. Usually you only need to do this if you plan on contributing to the project.
git clone git@github.com:Robpol86/sphinxcontrib-versioning.git
cd sphinxcontrib-versioning
python setup.py install
Tutorial¶
This guide will go over the basics of the project.
Make sure that you’ve already installed it.
Building Docs Locally¶
Before we begin make sure you have some Sphinx docs already in your project. If not read First Steps with Sphinx first. If you just want something quick and dirty you can do the following:
git checkout -b feature_branch master # Create new branch from master.
mkdir docs # All documentation will go here (optional, can be anywhere).
echo "master_doc = 'index'" > docs/conf.py # Create Sphinx config file.
echo -e "Test\n====\n\nSample Documentation" > docs/index.rst # Create one doc.
git add docs
git commit
git push origin feature_branch # Required.
Note
It is required to push doc files to origin. SCVersioning only works with remote branches/tags and ignores any local changes (committed, staged, unstaged, etc). If you don’t push to origin SCVersioning won’t see them. This eliminates race conditions when multiple CI jobs are building docs at the same time.
Build All Versions¶
Now that you’ve got docs pushed to origin and they build fine with sphinx-build
let’s try building them with
SCVersioning:
sphinx-versioning build -r feature_branch docs docs/_build/html
open docs/_build/html/index.html
More information about all of the options can be found at Settings or by running with --help
but just for
convenience:
-r feature_branch
tells the program to build our newly created/pushed branch at the root of the “html” directory. We do this assuming there are no docs in master yet. Otherwise you can omit this argument.docs/_build/html
is the destination directory that holds generated HTML files.- The final
docs
argument is the directory where we put our RST files in, relative to the git root (e.g. if you clone your repo to another directory, that would be the git root directory). You can add more relative paths if you’ve moved the location of your RST files between different branches/tags.
The command should have worked and your docs should be available in docs/_build/html/index.html with a “Versions” section in the sidebar.
If all you want SCVersioning to do is build docs for you for all versions and let you handle pushing them to a web host
and hosting them yourself then you are done here. Otherwise if you want to use the push
feature then keep reading.
Pushing to Remote Branch¶
SCVersioning supports pushing generated HTML files of your documentation to a remote branch, handling retries in case of race conditions where other parallel jobs try to build docs and push them to the same branch.
Building on the previous section above let’s go ahead and push those docs to a branch called gh-pages
. The branch
must already exist before trying to use the push feature, branches won’t be automatically created. So let’s do that:
git checkout --orphan gh-pages # Create the required branch with no history.
git reset .gitignore # Optionally keep your .gitignore.
git rm -rf . # Delete staged files left over from your previous branch.
echo "My project's documentation." > README.rst # Nice to have in all branches.
git add README.rst .gitignore
git commit # Initial commit.
git push origin gh-pages
Since this branch will just host HTML pages you can create an orphaned branch with no history instead of cluttering it up with the history of your code changes.
Push All Versions¶
Now that you have the destination branch in origin go ahead and run SCVersioning:
sphinx-versioning push -r feature_branch docs gh-pages .
Again you can find more information about all of the options at Settings or by running with --help
but just
for convenience:
gh-pages
is obviously the branch that will hold generated HTML docs..
is the path relative to the git root directory in thegh-pages
branch where HTML files will be placed. If that branch will host other files like code coverage and you want users to navigate to http://domain.local/documentation/index.html instead of “/index.html” then replace “.” with “documentation”.- The final
docs
argument is the directory where we put our RST files in just like the build command in the section above.
Note
By default SCVersioning does not delete any files in the destination directory/branch. It only adds new
ones or changes existing ones. This may lead to orphaned files in the branch if you delete branches/tags from the
repository (their HTML files will be left behind in gh-pages and still accessible to your users). To enable the
delete feature use one or more --grm-exclude <path>
options. More info in --grm-exclude
or --help
.
Banner Message¶
Banner messages can be displayed at the top of every document informing users that they are currently viewing either old
or the development version of the project’s documentation, with the exception of the --banner-main-ref
. This
feature is inspired by banner on the Jinja2 documentation.
The banner feature is disabled by default. It can be enabled with the --show-banner
setting.

The message displayed when users are viewing docs from a branch and the --banner-main-ref
is a tag. The
entire banner is a link that sends users to the latest version of the current page if it exists there.

The message displayed when users are viewing docs from a tag and the --banner-main-ref
is a tag. Like the
message above this one links users to the latest version of the current page.

An example of a banner message from a page that does not exist in the --banner-main-ref
version. Since
there is no page to link to this is just text informing the user that they’re viewing the development version of the
docs.
Settings¶
sphinx-versioning [GLOBAL_OPTIONS] build [OPTIONS] REL_SOURCE... DESTINATION
sphinx-versioning [GLOBAL_OPTIONS] push [OPTIONS] REL_SOURCE... DEST_BRANCH REL_DEST
SCVersioning reads settings from two sources:
- Your Sphinx conf.py file.
- Command line arguments.
Command line arguments always override anything set in conf.py. You can specify the path to conf.py with the
--local-conf
argument or SCVersioning will look at the first conf.py it finds in your REL_SOURCE
directories. To completely disable using a conf.py file specify the --no-local-conf
command line argument.
Below are both the command line arguments available as well as the conf.py variable names SCVersioning looks for. All
conf.py variable names are prefixed with scv_
. An example:
# conf.py
author = 'Your Name'
project = 'My Project'
scv_greatest_tag = True
Global Options¶
These options apply to to both build and push sub commands. They must be specified before the build/push command or else you’ll get an error.
-
-c
<directory>
,
--chdir
<directory>
¶ Change the current working directory of the program to this path.
-
-g
<directory>
,
--git-root
<directory>
¶ Path to directory in the local repo. Default is the current working directory.
-
-l
<file>
,
--local-conf
<file>
¶ Path to conf.py for SCVersioning to read its config from. Does not affect conf.py loaded by sphinx-build.
If not specified the default behavior is to have SCVersioning look for a conf.py file in any
REL_SOURCE
directory within the current working directory. Stops at the first conf.py found if any.
-
-L
,
--no-local-conf
¶
Disables searching for or loading a local conf.py for SCVersioning settings. Does not affect conf.py loaded by sphinx-build.
-
-N
,
--no-colors
¶
By default INFO, WARNING, and ERROR log/print statements use console colors. Use this argument to disable colors and log/print plain text.
-
-v
,
--verbose
¶
Enable verbose/debug logging with timestamps and git command outputs. Implies
--no-colors
. If specified more than once excess options (number used - 1) will be passed to sphinx-build.
Common Positional Arguments¶
Both the build and push sub commands use these arguments.
-
REL_SOURCE
¶
The path to the docs directory relative to the git root. If the source directory has moved around between git tags you can specify additional directories.
This cannot be an absolute path, it must be relative to the root of your git repository. Sometimes projects move files around so documentation might not always have been in one place. To mitigate this you can specify additional relative paths and the first one that has a conf.py will be selected for each branch/tag. Any branch/tag that doesn’t have a conf.py file in one of these REL_SOURCEs will be ignored.
-
--
,
scv_overflow
¶
It is possible to give the underlying
sphinx-build
program command line options. SCVersioning passes everything after--
to it. For example if you changed the theme for your docs between versions and want docs for all versions to have the same theme, you can run:sphinx-versioning build docs docs/_build/html -- -A html_theme=sphinx_rtd_theme
This setting may also be specified in your conf.py file. It must be a tuple of strings:
scv_overflow = ("-A", "html_theme=sphinx_rtd_theme")
Build Arguments¶
The build
sub command builds all versions locally. It always gets the latest branches and tags from origin and
builds those doc files.
Positional Arguments¶
In addition to the common arguments:
-
DESTINATION
¶
The path to the directory that will hold all generated docs for all versions.
This is the local path on the file sytem that will hold HTML files. It can be relative to the current working directory or an absolute directory path.
Options¶
These options are available for the build sub command:
-
-a
,
--banner-greatest-tag
,
scv_banner_greatest_tag
¶
Override banner-main-ref to be the tag with the highest version number. If no tags have docs then this option is ignored and
--banner-main-ref
is used.This setting may also be specified in your conf.py file. It must be a boolean:
scv_banner_greatest_tag = True
Override banner-main-ref to be the most recent committed tag. If no tags have docs then this option is ignored and
--banner-main-ref
is used.This setting may also be specified in your conf.py file. It must be a boolean:
scv_banner_recent_tag = True
-
-b
,
--show-banner
,
scv_show_banner
¶
Show a warning banner. Enables the Banner Message feature.
This setting may also be specified in your conf.py file. It must be a boolean:
scv_show_banner = True
The branch/tag considered to be the latest/current version. The banner will not be displayed in this ref, only in all others. Default is master.
If the banner-main-ref does not exist or does not have docs the banner will be disabled completely in all versions. Docs will continue to be built.
This setting may also be specified in your conf.py file. It must be a string:
scv_banner_main_ref = 'feature_branch'
-
-i
,
--invert
,
scv_invert
¶
Invert the order of branches/tags displayed in the sidebars in generated HTML documents. The default order is whatever git prints when running “git ls-remote –heads –tags”.
This setting may also be specified in your conf.py file. It must be a boolean:
scv_invert = True
-
-p
<kind>
,
--priority
<kind>
,
scv_priority
¶
kind
may be either branches or tags. This argument is for themes that don’t split up branches and tags in the generated HTML (e.g. sphinx_rtd_theme). This argument groups branches and tags together and whichever is selected forkind
will be displayed first.This setting may also be specified in your conf.py file. It must be a string:
scv_priority = 'branches'
-
-r
<ref>
,
--root-ref
<ref>
,
scv_root_ref
¶
The branch/tag at the root of
DESTINATION
. Will also be in subdirectories like the others. Default is master.If the root-ref does not exist or does not have docs,
sphinx-versioning
will fail and exit. The root-ref must have docs.This setting may also be specified in your conf.py file. It must be a string:
scv_root_ref = 'feature_branch'
-
-s
<value>
,
--sort
<value>
,
scv_sort
¶
Sort versions by one or more certain kinds of values. Valid values are
semver
,alpha
, andtime
.You can specify just one (e.g. “semver”), or more. The “semver” value sorts versions by Semantic Versioning, with the highest version being first (e.g. 3.0.0, 2.10.0, 1.0.0). Non-semver branches/tags will be sorted after all valid semver formats. This is where the multiple sort values come in. You can specify “alpha” to sort the remainder alphabetically or “time” to sort chronologically (most recent commit first).
This setting may also be specified in your conf.py file. It must be a tuple of strings:
scv_sort = ('semver',)
-
-t
,
--greatest-tag
,
scv_greatest_tag
¶
Override root-ref to be the tag with the highest version number. If no tags have docs then this option is ignored and
--root-ref
is used.This setting may also be specified in your conf.py file. It must be a boolean:
scv_greatest_tag = True
-
-T
,
--recent-tag
,
scv_recent_tag
¶
Override root-ref to be the most recent committed tag. If no tags have docs then this option is ignored and
--root-ref
is used.This setting may also be specified in your conf.py file. It must be a boolean:
scv_recent_tag = True
-
-w
<pattern>
,
--whitelist-branches
<pattern>
,
scv_whitelist_branches
¶
Filter out branches not matching the pattern. Can be a simple string or a regex pattern. Specify multiple times to include more patterns in the whitelist.
This setting may also be specified in your conf.py file. It must be a tuple of either strings or
re.compile()
objects:scv_whitelist_branches = ('master', 'latest')
Same as
--whitelist-branches
but for git tags instead.This setting may also be specified in your conf.py file. It must be a tuple of either strings or
re.compile()
objects:scv_whitelist_tags = (re.compile(r'^v\d+\.\d+\.\d+$'),)
Push Arguments¶
push
does the same as build and also attempts to push generated HTML files to a remote branch. It will retry up to
three times in case of race conditions with other processes also trying to push files to the same branch (e.g. multiple
Jenkins/Travis jobs).
HTML files are committed to DEST_BRANCH
and pushed to --push-remote
.
Positional Arguments¶
In addition to the common arguments:
-
DEST_BRANCH
¶
The branch name where generated docs will be committed to. The branch will then be pushed to the remote specified in
--push-remote
. If there is a race condition with another job pushing to the remote the docs will be re-generated and pushed again.This must be a branch and not a tag. This also must already exist in the remote.
-
REL_DEST
¶
The path to the directory that will hold all generated docs for all versions relative to the git roof of DEST_BRANCH.
If you want your generated index.html to be at the root of
DEST_BRANCH
you can just specify a period (e.g..
) for REL_DEST. If you want HTML files to be placed in say… “<git root>/html/docs”, then you specify “html/docs”.
Options¶
All build options are valid for the push sub command. Additionally these options are available only for the push sub command:
-
-e
<file>
,
--grm-exclude
<file>
,
scv_grm_exclude
¶
Causes “git rm -rf $REL_DEST” to run after checking out
DEST_BRANCH
and then runs “git reset <file>” to preserve it. All other files in the branch inREL_DEST
will be deleted in the commit. You can specify multiple files or directories to be excluded by adding more--grm-exclude
arguments.If this argument is not specified then nothing will be deleted from the branch. This may cause stale/orphaned HTML files in the branch if a branch is deleted from the repo after SCVersioning already created HTML files for it.
This setting may also be specified in your conf.py file. It must be a tuple of strings:
scv_grm_exclude = ('README.md', '.gitignore')
-
-P
<remote>
,
--push-remote
<remote>
,
scv_push_remote
¶
Push built docs to this remote. Default is origin.
This setting may also be specified in your conf.py file. It must be a string:
scv_push_remote = 'origin2'
HTML Context API¶
The following Jinja2 context variables are exposed in the Sphinx HTML builder context in all versions.
Versions Iterable¶
versions
is the main variable of interest. It yields names of other (and the current) versions and relative URLs to
them. You can iterate on it to get all branches and tags, or use special properties attached to it to yield just
branches or just tags.
-
versions
¶ An iterable that yields 2-item tuples of strings. The first item is the version (branch/tag) name while the second item is the relative path to the documentation for that version. The path is URL safe and takes into account HTML pages in sub directories.
{%- for name, url in versions %} <li><a href="{{ url }}">{{ name }}</a></li> {%- endfor %}
-
versions.
branches
¶ The
versions
iterable has a branches property that itself yields versions in branches (filtering out git tags). The order is the same and it yields the same tuples.<dl> <dt>Branches</dt> {%- for name, url in versions.branches %} <dd><a href="{{ url }}">{{ name }}</a></dd> {%- endfor %} </dl>
The
versions
iterable also has a tags property that itself yields versions in tags (filtering out git branches). Just as the branches property the order is maintained and the yielded tuples are the same.<dl> <dt>Tags</dt> {%- for name, url in versions.tags %} <dd><a href="{{ url }}">{{ name }}</a></dd> {%- endfor %} </dl>
Functions¶
-
vhasdoc
(other_version)¶ Similar to Sphinx’s hasdoc() function. Returns True if the current document exists in another version.
{% if vhasdoc('master') %} This doc is available in <a href="../master/index.html">master</a>. {% endif %}
-
vpathto
(other_version)¶ Similar to Sphinx’s pathto() function. Has two behaviors:
- If the current document exists in the specified other version pathto() returns the relative URL to that document.
- If the current document does not exist in the other version the relative URL to that version’s master_doc is returned instead.
{% if vhasdoc('master') %} This doc is available in <a href="{{ vpathto('master') }}">master</a>. {% else %} Go to <a href="{{ vpathto('master') }}">master</a> for the latest docs. {% endif %}
Banner Variables¶
These variables are exposed in the Jinja2 context to facilitate displaying the banner message and deciding which message to display.
A boolean set to True if
--banner-greatest-tag
is used.
A boolean set to True if the banner main ref is a branch.
A boolean set to True if the banner main ref is a tag.
A string, the value of
--banner-main-ref
.
A boolean set to True if
--banner-recent-tag
is used.
A boolean set to True if
--show-banner
is used.
Other Variables¶
-
current_version
¶ A string of the current version being built. This will be the git ref name (e.g. a branch name or tag name).
<h3>Current Version: {{ current_version }}</h3>
-
scv_is_branch
¶ A boolean set to True if the current version being built is from a git branch.
-
scv_is_greatest_tag
¶ A boolean set to True if the current version being built is:
- From a git tag.
- A valid semver-formatted name (e.g. v1.2.3).
- The highest version number.
-
scv_is_recent_branch
¶ A boolean set to True if the current version being built is a git branch and is the most recent commit out of just git branches.
-
scv_is_recent_ref
¶ A boolean set to True if the current version being built is the most recent git commit (branch or tag).
-
scv_is_recent_tag
¶ A boolean set to True if the current version being built is a git tag and is the most recent commit out of just git tags.
-
scv_is_root
¶ A boolean set to True if the current version being built is in the web root (defined by
--root-ref
).
-
scv_is_tag
¶ A boolean set to True if the current version being built is from a git tag.
Supported Themes¶
Below are screen shots of the supported built-in Sphinx themes. You can the “Versions” section in each screen shot on sidebars.
If your theme isn’t here you can either create a pull request or add support for SCVersioning using HTML Context API.
GitHub Pages¶
It’s pretty easy to use GitHub Pages to host all of your versioned documentation. Before starting be sure to go through the Tutorial first to make sure you can build your docs locally. You’ll also want to do the Push All Versions section.
Tip
You may want to enable GitHub’s protected branches feature for the gh-pages branch to prevent you or anyone from accidentally deleting the branch from remote.
This guide assumes:
- You already have documentation in your master branch and SCVersioning builds it locally. If not you’ll need to use
the
--root-ref
argument. - You already have your CI configured and running on your repo (this guide uses Travis CI but it should work on any other).
Turn Off Jekyll¶
Building on the steps in the Tutorial document you’ll want to disable Jekyll because it doesn’t copy over files and directories that start with underscores, which Sphinx uses.
git checkout gh-pages
git pull origin gh-pages
touch .nojekyll
git add .nojekyll
git commit
git push origin gh-pages
git checkout master # Or whatever branch you were in.
Then navigate to https://username.github.io/repo_name/ and if you used .
for your REL_DEST
you should see
your HTML docs there. Otherwise if you used something like html/docs
you’ll need to navigate to
https://username.github.io/repo_name/html/docs/.
Tip
Old repositories may not have Enforce HTTPS enabled for their GitHub Pages. It’s a good idea to enable this feature. More info: https://help.github.com/articles/securing-your-github-pages-site-with-https/
Running in CI¶
The goal of using GitHub Pages is to have docs automatically update on every new/changed branch/tag. In this example we’ll be using Travis CI but any CI should work.
Travis won’t be able to push any changes to the gh-pages branch without SSH keys. This section will worry about just getting Travis to run SCVersioning. It should only fail when trying to push to origin.
CI Config File¶
Edit your CI configuration file (e.g. .travis.yml) with:
install:
- pip install sphinxcontrib-versioning
after_success:
- git config --global user.email "builds@travis-ci.com"
- git config --global user.name "Travis CI"
- sphinx-versioning push docs gh-pages .
The two git config lines are needed to make commits locally to the gh-pages branch (cloned to a temporary directory by SCVersioning). If you want SCVersioning to delete unrelated files from the gh-pages branch (e.g. deleted branches’ HTML documentation, deleted tags, etc) change the sphinx-versioning command to:
sphinx-versioning -e .gitignore -e .nojekyll -e README.rst push docs gh-pages .
This tells SCVersioning to delete all files in gh-pages except those three. More information in --grm-exclude
.
Commit¶
Commit your changes to the CI config file and push. You should see documentation building successfully, but it should fail when it tries to push since we haven’t given your CI any permission to make changes to the git repository.
SSH Key¶
Now that we know SCVersioning works fine locally and remotely it’s time to unleash it. We’ll be using Deploy Keys to grant Travis write access to your repository. At the time of this writing this is the most narrow-scoped authorization method for docs deployment.
To avoid leaking the SSH private key (thereby granting write access to the repo) we’ll be using Travis CI’s Encrypting Files feature. You’ll need to install the Travis CI ruby client for this section.
ssh-keygen¶
First we’ll create the SSH key pair.
ssh-keygen -t rsa -b 4096 -C "Travis CI Deploy Key" -N "" -f docs/key
cat docs/key.pub # We'll be adding this to GitHub's repo settings page.
travis encrypt-file docs/key docs/key.enc --add after_success # Updates .travis.yml
rm docs/key docs/key.pub # Don't need these anymore.
We need to give GitHub your SSH public key (the one we ran with cat
). Go to
https://github.com/username/repo_name/settings/keys and click “Add deploy key”. The title could be anything (e.g.
“Travis CI Deploy Key”). The key you’re pasting will be one long line and will look something like “ssh-rsa AAAAB3N…==
Travis CI Deploy Key”
Be sure to check Allow write access.
travis.yml¶
The travis encrypt-file
command should have updated your .travis.yml
with the openssl command for you. However
we still need to make one more change to the file before committing it. Update .travis.yml to make the after_success
section look like the following. Remember to replace $encrypted_x_key and $encrypted_x_iv with what you
currently have.
after_success:
- eval "$(ssh-agent -s)"; touch docs/key; chmod 0600 docs/key
- openssl aes-256-cbc -d -K $encrypted_x_key -iv $encrypted_x_iv < docs/key.enc > docs/key
&& ssh-add docs/key # Use && to prevent ssh-add from prompting during pull requests.
- git config --global user.email "builds@travis-ci.com"
- git config --global user.name "Travis CI"
- git remote set-url --push origin "git@github.com:$TRAVIS_REPO_SLUG"
- export ${!TRAVIS*} # Optional, for commit messages.
- sphinx-versioning push docs gh-pages .
Warning
Always conditionally run ssh-add only if openssl succeeds like in the example above. Encrypted environment variables are not set on Travis CI and probably other CIs during pull requests for security reasons. If you always run ssh-add (which appears to be what everyone does) all of your pull requests will have failing tests because:
- Travis CI runs all commands in after_success even if one fails.
- openssl appears to copy “key.enc” to “key” when it fails to decrypt.
- ssh-add will prompt for a passphrase because it thinks the file is encrypted with an SSH passphrase.
- The Travis job will hang, timeout, and fail even if tests pass.
Finally commit both .travis.yml and the encrypted docs/key.enc file. Push and watch Travis update your docs automatically for you.
NearlyFreeSpeech.NET¶
This guide will go over how to host your built documentation on NearlyFreeSpeech. We’ll be using GitHub and Travis CI to actually build the docs and push them to NFSN but any other providers can be substituted.
We’ll be covering two methods of having NFSN host your documentation: using rsync
to transfer HTML files to NFSN and
using a remote git repository hosted on NFSN using git init --bare
and having a git hook export HTML files to the
“/home/pubic” directory. Since NFSN’s pricing structure is usage based the latter method technically costs more since
the entire git history of the HTML files’ git branch will be stored on NFSN, whereas in the rsync method only the HTML
files are stored on NFSN. The cost difference is probably minimal but it’s something to keep in mind.
Before starting be sure to go through the Tutorial first to make sure you can build your docs locally. If you’re
going with the rsync
route you can stop after the Build All Versions section. Otherwise you should go through
the Push All Versions section as well.
This guide assumes:
- You already have documentation in your master branch and SCVersioning builds it locally. If not you’ll need to use
the
--root-ref
argument. - You already have Travis CI configured and running on your repo.
- You already have an account on NFSN.
Running in CI¶
Before touching NFSN let’s setup Travis CI to run SCVersioning. Edit your .travis.yml file with:
addons:
ssh_known_hosts: ssh.phx.nearlyfreespeech.net
install:
- pip install sphinxcontrib-versioning
after_success:
- sphinx-versioning build docs docs/_build/html
Commit your changes and push. You should see documentation building successfully.
SSH Key¶
Now we need to create an SSH key pair and upload the private key to Travis CI. The public key will be given to NFSN in the next section.
To avoid leaking the SSH private key (thereby granting write access to the repo) we’ll be using Travis CI’s Encrypting Files feature. You’ll need to install the Travis CI ruby client for this section.
Create the SSH key pair.
ssh-keygen -t rsa -b 4096 -C "Travis CI Deploy Key" -N "" -f docs/key
cat docs/key.pub # We'll be adding this to NFSN's Add SSH Key page.
travis encrypt-file docs/key docs/key.enc --add after_success # Updates .travis.yml
rm docs/key docs/key.pub # Don't need these anymore.
The travis encrypt-file
command should have updated your .travis.yml
with the openssl command for you. However
we still need to make one more change to the file before committing it. Update .travis.yml to make the after_success
section look like the following. Remember to replace $encrypted_x_key and $encrypted_x_iv with what you
currently have.
after_success:
- eval "$(ssh-agent -s)"; touch docs/key; chmod 0600 docs/key
- openssl aes-256-cbc -d -K $encrypted_x_key -iv $encrypted_x_iv < docs/key.enc > docs/key
&& ssh-add docs/key # Use && to prevent ssh-add from prompting during pull requests.
- sphinx-versioning build docs docs/_build/html
Warning
Always conditionally run ssh-add only if openssl succeeds like in the example above. Encrypted environment variables are not set on Travis CI and probably other CIs during pull requests for security reasons. If you always run ssh-add (which appears to be what everyone does) all of your pull requests will have failing tests because:
- Travis CI runs all commands in after_success even if one fails.
- openssl appears to copy “key.enc” to “key” when it fails to decrypt.
- ssh-add will prompt for a passphrase because it thinks the file is encrypted with an SSH passphrase.
- The Travis job will hang, timeout, and fail even if tests pass.
Finally commit both .travis.yml and the encrypted docs/key.enc file.
Create an NFSN Site¶
First we’ll create a static site on NFSN. Even if you’ve been using NFSN it’s a good idea to try this out in a dedicated and disposable site to avoid breaking anything important.
- Go to the sites tab in the member portal and click “Create a New Site”. This guide will use scversioning as the new site’s short name.
- Since this is all just static HTML files you won’t need PHP/MySQL/etc. Select the “Static Content” server type.
- You should be able to visit http://scversioning.nfshost.com/ and get an HTTP 403 error.
- Go to the profile tab and click “Add SSH Key”. The key you’re pasting will be one long line and will look something like “ssh-rsa AAAAB3N…== Travis CI Deploy Key”
Pushing From CI to NFSN¶
This is the moment of truth. You need to decide if you want to just rsync HTML files from Travis CI to NFSN or add NFSN as a git remote, have SCVersioning push to NFSN, and let a git hook on NFSN move HTML files to the web root.
Using Rsync¶
This is simpler and costs less (though probably not by much since NFSN is pretty cheap). All you need to do is add these
lines to your .travis.yml file’s after_success
section. Be sure to replace username_scversioning with your
actual username and remove the previous sphinx-versioning line.
- export destination=username_scversioning@ssh.phx.nearlyfreespeech.net:/home/public
- sphinx-versioning build docs docs/_build/html && rsync -icrz --delete docs/_build/html/ $destination
We’re adding rsync to the same line as sphinx-versioning because Travis CI runs all commands in after_success even if one of them fails. No point in rsyncing if sphinx-versioning fails.
After committing you should see Travis CI rsync HTML files to NFSN and your site should be up and running with your documentation.
Using Git Bare Repo¶
You can take advantage of SCVersioning’s git push retry logic if you go this route. Here we’ll be pushing build docs to
the nfsn-pages
branch on the remote repo located in your NFSN’s private home directory.
First create the remote repo on NFSN. SSH into your new site and run these commands:
mkdir /home/private/repo
cd /home/private/repo
git init --bare
touch hooks/post-receive
chmod +x hooks/post-receive
Next setup the post-receive git hook. Write the following to /home/private/repo/hooks/post-receive on NFSN:
# !/bin/bash
export GIT_WORK_TREE="/home/public"
while read sha1old sha1new refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
[ "$branch" != "nfsn-pages" ] && continue
lockf -k -t5 /home/tmp/nfsn_pages.lock git checkout -f $branch
done
Now before we move on to the final step you’ll need to create the initial commit to the nfsn-pages branch on the NFSN
remote. SCVersioning does not create new branches, they must previously exist on the remote. Here we’ll be renaming the
gh-pages
branch you created in Pushing to Remote Branch to nfsn-pages
and pushing it to our new NFSN
remote repo. Run these commands on your local machine (replace username_scversioning with your actual username):
git push origin --delete gh-pages # No longer need this in origin.
git checkout gh-pages
git branch -m nfsn-pages
git remote add nfsn "username_scversioning@ssh.phx.nearlyfreespeech.net:/home/private/repo"
git push nfsn nfsn-pages
At this point you should see .gitignore and README.rst in your /home/public directory on NFSN. Finally add these lines
to your .travis.yml file’s after_success
section. Be sure to replace username_scversioning with your actual username
and remove the previous sphinx-versioning line.
- git config --global user.email "builds@travis-ci.com"
- git config --global user.name "Travis CI"
- git remote add nfsn "username_scversioning@ssh.phx.nearlyfreespeech.net:/home/private/repo"
- export ${!TRAVIS*} # Optional, for commit messages.
- sphinx-versioning push -P nfsn docs nfsn-pages .
After committing you should see Travis CI push HTML files to NFSN and your site should be up and running with your documentation.
Robots and 404 Pages¶
Since you’re using NFSN to host your docs you’ll probably want to setup a 404 page as well as a robots.txt
. A
robots.txt is pretty easy: just place it in your docs directory (next to conf.py) and add
html_extra_path = ['robots.txt']
to your conf.py.
A 404 page is slightly more involved. First add a 404.rst in your docs directory. Then create a docs/_templates/layout.html file and add this to it:
{% if pagename == '404' and scv_is_root %}
{% set metatags = '<base href="/">\n ' + metatags %}
{% endif %}
Note
The base href thing fixes the relative URLs problem on 404 errors in subdirectories. If users go to
http://scversioning.nfshost.com/unknown/index.html Apache will serve the /404.html file contents without having
browsers change the current directory path. This causes browsers to resolve relative URLs (and CSS files) in
404.html to for example http://scversioning.nfshost.com/unknown/_static/css/theme.css which itself is a 404.
<base href="/">
fixes this so browsers resolve all relative URLs/links/etc to
http://scversioning.nfshost.com/_static/css/theme.css.
Next you need to tell NFSN to give browsers 404.html on an HTTP 404 error. Add an .htaccess
file in your docs
directory and put ErrorDocument 404 /404.html
in it.
Finally to tie it all together add this to your conf.py:
templates_path = ['_templates']
html_extra_path = ['.htaccess', 'robots.txt']
Changelog¶
This project adheres to Semantic Versioning.
2.2.1 - 2016-12-10¶
- Added
- Time value of
html_last_updated_fmt
will be the last git commit (authored) date.
- Time value of
- Fixed
- Unhandled KeyError exception when banner main ref fails pre-build.
- https://github.com/sphinx-contrib/sphinxcontrib-versioning/issues/26
- https://github.com/sphinx-contrib/sphinxcontrib-versioning/issues/27
2.2.0 - 2016-09-15¶
2.1.4 - 2016-09-03¶
- Fixed
- banner.css being overridden by conf.py: https://github.com/sphinx-contrib/sphinxcontrib-versioning/issues/23
2.1.3 - 2016-08-24¶
- Fixed
- Stopped blocking users from overriding their layout.html. Using another approach to inserting the banner.
2.1.2 - 2016-08-24¶
- Fixed
- Cloning from push remote instead of origin. If HTML files are pushed to another repo other than origin it doesn’t make sense to clone from origin (previous files won’t be available).
2.1.1 - 2016-08-23¶
- Added
- Command line option:
--push-remote
- Command line option:
- Fixed
- Copy all remotes from the original repo to the temporarily cloned repo when pushing built docs to a remote. Carries over all remote URLs in case user defines a different URL for push vs fetch.
2.1.0 - 2016-08-22¶
- Added
- Option to enable warning banner in old/development versions. Similar to Jinja2’s documentation.
- Command line options:
--banner-greatest-tag
--banner-recent-tag
--show-banner
--banner-main-ref
- Jinja2 context functions:
vhasdoc()
vpathto()
- Jinja2 context variables:
scv_show_banner
scv_banner_greatest_tag
scv_banner_main_ref_is_branch
scv_banner_main_ref_is_tag
scv_banner_main_version
scv_banner_recent_tag
- Changed
- Root ref will also be built in its own directory like other versions. All URLs to root ref will point to the one in that directory instead of the root. More info: https://github.com/sphinx-contrib/sphinxcontrib-versioning/issues/15
- Renamed Jinja2 context variable
scv_is_root_ref
toscv_is_root
.
- Fixed
- Removed
- Jinja2 context variables:
scv_root_ref_is_branch
scv_root_ref_is_tag
- Jinja2 context variables:
2.0.0 - 2016-08-15¶
- Added
--git-root
command line option.--whitelist-branches
and--whitelist-tags
command line options.--local-conf
and--no-local-conf
command line options.- Load settings from conf.py file and command line arguments instead of just the latter.
- Changed
- Renamed command line option
--prioritize
to--priority
. - Renamed command line option
-S
to-s
. --chdir
,--no-colors
, and--verbose
must be specified before build/push and the other after.--sort
no longer takes a comma separated string. Now specify multiple times (like--grm-exclude
).- Renamed
--sort
value “chrono” to “time”. - Reordered positional command line arguments. Moved
REL_SOURCE
before the destination arguments. - Renamed command line option
-C
to-N
for consistency with sphinx-build.
- Renamed command line option
- Fixed
- Exposing sphinx-build verbosity to SCVersioning. Specify one
-v
to make SCVersioning verbose and two or more to make sphinx-build verbose. - Using
--no-colors
also turns off colors from sphinx-build. - https://github.com/sphinx-contrib/sphinxcontrib-versioning/issues/16
- Exposing sphinx-build verbosity to SCVersioning. Specify one
1.1.0 - 2016-08-07¶
- Added
- Exposing Jinja2 context variables:
scv_is_branch
scv_is_root_ref
scv_is_tag
scv_root_ref_is_branch
scv_root_ref_is_tag
scv_is_greatest_tag
scv_is_recent_branch
scv_is_recent_ref
scv_is_recent_tag
- Exposing Jinja2 context variables:
- Changed
- Version links point to that version of the current page if it exists there.
- Fixed
1.0.1 - 2016-08-02¶
- Fixed
1.0.0 - 2016-07-23¶
- Initial release.