Development¶
Building the documentation¶
pip install -r docs/requirements.txt
sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html
-W turns warnings into errors, which is what CI uses, so a broken cross-reference fails the build
rather than shipping a dead link. -d keeps Sphinx’s build cache out of the output directory, which
is published verbatim.
The Python API page needs the compiled camera_interface module to be importable. Without it the
build still succeeds and the page shows a note in place of the reference, so a docs-only change does
not require a full C++ build locally.
How the docs stay current¶
Reference tables that restate something the source already knows are generated at build time and cross-checked against the source, so the build fails when they diverge:
Table |
Source of truth |
|---|---|
Base commands |
The dispatch chain in camerad/camera_server.cpp, with syntax from |
Configuration keys |
Reads through a config object’s |
ATC FITS keywords |
The |
Descriptions are written by hand in docs/data/, keyed by command or key name. Adding a command or
a config key to the source without a description there fails the docs build; so does describing one
that no longer exists.
The generators are Sphinx directives in docs/_ext/camerad_tables.py. Validation runs once at
builder-inited, so a mismatch fails immediately rather than partway through writing pages.
Tip
Commands are taken from the dispatch chain rather than from CAMERAD_SYNTAX, because the two have
diverged: CAMERAD_SYNTAX feeds the help output and still advertises commands the server no
longer implements. The dispatch is what actually answers a client.
Adding a command or key¶
Make the change in the C++ as usual.
Run the docs build. It fails, naming what is now undescribed.
Add the entry to
docs/data/commands.yamlordocs/data/config_keys.yaml.
Nothing has to be added to a page: the tables pick it up.
Documentation layout¶
docs/
conf.py Sphinx configuration
requirements.txt pinned docs toolchain
data/ hand-written descriptions the generators consume
_ext/ generator extensions
<chapter>/ one directory per chapter
Pages are Markdown via MyST. Link to a file in the repository with
{source}`camerad/camera_interface.h` rather than pasting signatures into the prose; the C++
reference here is narrative by design.
Publishing¶
.github/workflows/docs.yml builds on every pull request and every push to main.
A merge to
mainpublishes the site to the root of thegh-pagesbranch.Every build uploads the rendered HTML as a workflow artifact, which is how a pull request build is viewed rendered. Download it from the run’s summary page.
workflow_dispatchonmainalso publishes, so the site can be restored without an empty commit.
Important
The gh-pages branch needs a .nojekyll file at its root. Without it Pages runs the output through
Jekyll, which skips directories beginning with an underscore, and the whole site loads with no CSS
because _static/ returns 404. Recreating gh-pages from scratch means adding it again.
Testing camerad itself¶
make run_unit_tests && ./bin/run_unit_tests
The end-to-end tests run against the emulator in CI, in
.github/workflows/emulator-integration.yml.
Warning
The build workflow compiles the default target, and an instrument only when one is named explicitly.
hispec_tracking_camera is the only instrument any workflow builds, so the other modules can fall
behind changes to the core without CI noticing.
Instrument submodules¶
Instrument modules are pinned submodules. Updating one is a commit to camera-interface that moves
the pin, which .github/workflows/update-submodules.yml automates. Documentation for an instrument
lives here, in this repository, while each instrument repository keeps its own README.