Skip to main content
Documentation
This material has been adapted from the "Software Engineering" module of the SABS R³ Center for Doctoral Training.

This material has been adapted from the "Software Engineering" module of the SABS R³ Center for Doctoral Training.

Creative Commons License
This course material was developed as part of UNIVERSE-HPC, which was funded through the SPF ExCALIBUR programme under grant number EP/W035731/1

This course material was developed as part of UNIVERSE-HPC, which was funded through the SPF ExCALIBUR programme under grant number EP/W035731/1

Creative Commons License

Documentation

Writing documentation for software is crucial.
  1. Improves Code Understanding: Good documentation gives a clear understanding of the flow, architecture, and functionalities of the software, reducing the time it takes for new team members to understand how things work.
  2. Easier Maintenance: Documentation is essential for maintaining software, particularly if the original engineers are no longer involved in the project. Without documentation, future developers may not understand why certain decisions were made.
  3. Boosts Productivity: Developers spend a significant amount of time understanding existing code. If software is well documented, developers can understand it quicker and spend more time writing new code or improving existing features.
  4. Reduces Dependency: Good documentation reduces the dependency on particular team members who have expert knowledge of the software. It enables any developer to understand and contribute to the software, irrespective of their prior involvement in the project.
  5. Enhances Software Quality: Writing documentation forces developers to think through their design before implementing it, often leading to better design decisions. It can also serve as a form of review to catch potential problems before the software is built.
  6. Facilitates Code Reusability: With adequate documentation, code functions, libraries, and modules can be reused easily in different projects, saving time and effort.
  7. Compliance and Auditing: In some industries, documentation is a legal requirement for audits and regulatory compliance. It helps demonstrate that the software meets certain standards or regulations.
  8. Supports Debugging: When problems arise, good documentation can help developers understand the system better and assist in debugging.
  9. Preserves Information: Documentation helps to preserve the rationale and thought process behind the implementation. This is especially important when key decisions are made about how something was implemented and why.
We will be using Sphinx to generate the documentation, and GitHub Pages to host it.

Sphinx

Sphinx is a powerful and flexible open-source documentation generation tool primarily used for Python, but it can be used for other programming languages as well.
Here are some key features:
  1. Extensible Output Formats: Sphinx can generate several output formats, including HTML, LaTeX (for printable PDF versions), manual pages, plain text, and more.
  2. Cross-referencing Code: Sphinx supports automatic generation of API documentation from Python modules, and allows linking to specific function definitions, classes, methods, and more from other parts of the documentation.
  3. Indexing and Searching: Sphinx provides robust indexing that is crucial for larger projects. It supports glossaries and can generate search pages for HTML output.
  4. Theming Support: Sphinx supports themes for its HTML output, allowing documentation to match the aesthetic and branding of a project or organization.

Where to put it

Generated HTML has to be served from somewhere.
Most scientific Python projects use Read the Docs, which builds your documentation on its own servers whenever you push, hosts it for free, and gives you two things that are genuinely hard to arrange yourself: documentation versioned alongside your releases, so a user on an old version reads the right page, and preview builds on pull requests. It is worth knowing, and you will meet it constantly.
We are going to use GitHub Pages instead, for two reasons.
The first is that the build happens where you can watch it. This course is about seeing your pipeline run, and Read the Docs does the interesting part somewhere else, behind a login on a different site.
The second is that Pages is general and you will find it useful for all sorts of things. It serves static files out of a repository, and it does not care whether those files are API documentation, a coverage report, a project website, a set of benchmark results, a rendered notebook, or even an interactive web app. Once you have built one thing and published it, you will know how to publish anything.

Setting up Sphinx

Make sure the documentation dependencies are installed:
pip install -e ".[dev,docs]"
Create a directory called docs at the top level of your project, and from inside it run:
sphinx-quickstart
Accept the defaults, but give the project a name.
This generates conf.py, index.rst and a couple of build scripts. rst stands for restructured text and is a markup format similar to, but a little more sophisticated than markdown.

Telling Sphinx about your code

Out of the box, Sphinx will happily build a site containing nothing but the page you just made. To get it to read your code, you need two extensions.
In docs/conf.py, find the extensions list and make it:
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon"]
autodoc imports your package and pulls out the docstrings. napoleon teaches it to read the numpydoc style those docstrings are written in; without it, the parameter and return sections render as an unformatted mess.
While you are in conf.py, delete this line:
html_static_path = ['_static']
sphinx-quickstart creates an empty docs/_static directory for custom CSS and images. Git does not track empty directories, so the moment you commit, the directory does not exist for anyone else, and Sphinx warns about it. You have no static assets, so the simplest fix is the one above. Put the line back if you ever add static assets (for instance, a project logo).

Adding an API reference

Create docs/reference.rst:
API reference ============= .. automodule:: ci_course.io :members: .. automodule:: ci_course.stats :members: .. automodule:: ci_course.report :members:
and add reference to the toctree in docs/index.rst.
Build it:
sphinx-build -W -b html docs docs/_build/html
Open docs/_build/html/index.html in a browser and look at the API reference.
The -W turns warnings into errors. Documentation warnings are easy to ignore for months, and they are usually telling you that something is not appearing on the page you think it is.

What is missing?

Compare the API reference against src/ci_course/stats.py. If you skipped the previous section, one function is absent.

Publishing it

Now automate the build and put the result online.
First, turn GitHub Pages on: on your GitHub repository, go to Settings, then Pages, and set the source to GitHub Actions rather than a branch. This is why your repository needed to be public: Pages on a free account requires it.

Deploy the documentation

Write a workflow, pages.yml, that builds the documentation on every push to main and publishes it.
You will need three actions you have not used before: actions/configure-pages, actions/upload-pages-artifact and actions/deploy-pages.
You will also need a permissions block. Deployment needs pages: write to publish, and id-token: write so the runner can prove to GitHub Pages which workflow it is, without you storing a secret anywhere.
Push it, watch it run, and follow the URL in the deploy job summary. Your documentation is online, and it will now stay current without anyone remembering to update it!

This is deployment

You pushed a commit, and a change went live on a website, with no human having to remember to do it.
That is Continuous Deployment.
The alternative is Continuous Delivery: every change that passes is built, tested and made ready to release, and then a person decides whether to release it. The pipeline is identical right up to the last step. The difference is entirely whether somebody has to approve.
For documentation on a small project, deploying automatically is the right call. For something with real users, or where a bad release is expensive to undo, you usually want the approval. Later in the course you will add one.

Next steps

Keep documenting

The API reference is generated, but a reference is not a guide. Someone arriving at your project still needs to know what it is for and how to start.
Add an install and a quickstart page to the toctree, with a worked example of loading the sample data, summarising it and writing a report.
Push, and watch the site update itself.
  1. [optional] read the Sphinx documentation.
  2. [optional] read about publishing with GitHub Pages.