Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 30 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
<!--
SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0
-->
<!-- SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0 -->

# LibreSign documentation

Source for the [LibreSign public documentation](https://docs.libresign.coop/),
built with Sphinx. The site provides separate manuals for stable LibreSign
majors (`/13/`, `/14/`, `/15/`) and development (`/main/`).

- **Edit content:** use RST in `developer_manual/`, `user_manual/` or
`admin_manual/`. The `versioned/base/` directory holds stable foundations;
`versioned/<major>/` holds overrides. Shared development-to-stable sections
are listed in `versioned/shared.json`. Adding a page never requires editing
Python build or screenshot scripts.
- **Contribute:** open a PR. CI checks Sphinx, links, OpenAPI provenance and
version isolation. Review the navigable preview, including any unpublished
release pages under `/_review/`; screenshots are not required.
- **Maintain releases:** see the
[maintainer guide](docs/maintainers/versioning.md) for local builds,
deployment, previews, backports and lifecycle metadata.

Canonical release history and API sources remain in
[LibreSign/libresign](https://github.com/LibreSign/libresign).
Public manuals: **https://docs.libresign.coop**.

The documentation follows Nextcloud's **one branch per version** pattern:

| Branch | LibreSign documentation |
| --- | --- |
| `main` | Next release, in development |
| `stable15` | LibreSign 15 |
| `stable14` | LibreSign 14 |
| `stable13` | LibreSign 13 |

For a new release, use `stableNN`, where NN is the **LibreSign major** (not the
Nextcloud server major). Each branch contains complete `user_manual/`,
`admin_manual/` and `developer_manual/` sources. There are no `versioned/`
source overlays and no per-page Python tests to update.

**To edit a page:** choose the LibreSign version on the website, select
**Edit on GitHub**, update the RST file and open a PR to the **same branch**.
For a new page, add it to the section's `index.rst` (`.. toctree::`).
For changes applying to multiple versions, backport explicitly.

See [CONTRIBUTING.md](CONTRIBUTING.md) for everyday editing and
[docs/maintainers/versioning.md](docs/maintainers/versioning.md) for the
publication process, API contracts and new releases.

The build dynamically discovers released LibreSign majors and pins their
OpenAPI contracts to their exact application commits. Releases are never
inferred from a documentation branch alone.
217 changes: 94 additions & 123 deletions docs/maintainers/versioning.md
Original file line number Diff line number Diff line change
@@ -1,133 +1,104 @@
<!--
SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0
-->

# Versioning, previews and publication

This guide is intended for contributors and release maintainers, not as
public API documentation. The root [README](../../README.md) is deliberately
short. Product release histories remain canonical in
[LibreSign/libresign](https://github.com/LibreSign/libresign/releases).

## Source of truth and release boundaries

Each build resolves the application branches to **immutable commit SHAs** and
fetches `appinfo/info.xml` and `openapi.json` from each resolved SHA.
Stable lines are discovered from the manifest, and incompatible Nextcloud
dependencies cause the build to fail. A stable line must never load an API
contract from `main`. Every generated API reference has accompanying
`openapi.json` and `openapi.provenance.json` files.

Maintain `main/` as top-level navigation and `developer_manual/` as
development documentation. Use `versioned/base/` for the release-safe
foundation and `versioned/<major>/` for release overrides. Directories
verified as shared across development and stable lines are declared in
`versioned/shared.json`; the build copies their RST automatically, without
a per-page script change. Do not expose unreviewed development-only flows in
stable manuals. The Sphinx theme and configuration are shared.

The documentation homepage (the root URL) lists versions from latest stable
to oldest stable and development `main` last. Within the Sphinx manuals,
the version chooser is collapsed in the bottom-left corner, following the
Nextcloud Server documentation pattern. It preserves the current page when
that page exists in the target version, otherwise opening the target
manual index. The selector marks `main` as development, the latest supported
stable line as current, and earlier stable lines as previous. The homepage uses
`assets/home-theme.js` with the same `localStorage.theme` preference as
`sphinx_rtd_dark_mode` on internal pages. Theme changes must persist when
navigating between these pages. EOL status and dates are explicit entries in
`versioning/lifecycle.json`. Never infer an EOL commitment or commercial
support guarantee from branch existence.

## Local build and checks

Use Python 3.13 (as in CI) and install `requirements.txt` plus
`openapi-spec-validator==0.7.2`. Run:
<!-- SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
SPDX-License-Identifier: CC-BY-3.0 -->

# Versioning and publication of LibreSign documentation

The public source is deliberately simple: **one complete documentation branch
per LibreSign major**, following the Nextcloud documentation convention.

## Where to edit

| Target | Git branch | Source path |
| --- | --- | --- |
| Next LibreSign version | `main` | `user_manual/`, `admin_manual/`, `developer_manual/` |
| LibreSign 15 | `stable15` | Same paths |
| LibreSign 14 | `stable14` | Same paths |
| LibreSign 13 | `stable13` | Same paths |

For a future stable release `NN`, create `stableNN`. The documentation branch
name is the **LibreSign major**, not the Nextcloud major; the application
repository uses a different naming convention (`stable35` for LibreSign 15).
Each source branch contains its complete manual, without shared-directory
inheritance or `versioned/base` overlays. **Edit on GitHub** links to the
matching branch and file, not to a generated or inherited source.

Ordinary RST contributions do not require Python changes. Add a page to the
section's `index.rst` toctree, build with Sphinx and open a PR against the
right branch. Backport changes explicitly when they apply to older releases.

## What the central build does

`main` contains the publishing tool and site-wide assets. It:

1. Discovers released application branches and the development branch from
`LibreSign/libresign`, verifying `appinfo/info.xml` compatibility.
2. Pins the application commit and OpenAPI SHA for **each** released version.
3. Fetches the matching documentation `stableNN` branch and pins its Git SHA.
Missing branches cause an error; the build never substitutes development
documentation for a stable release.
4. Builds each branch's manuals using the current common Sphinx theme and
navigation. The published URLs remain `/13/`, `/14/`, `/15/`, `/main/` etc.
5. Validates links, API provenance, signing examples, redirects and the output
of all other versions before deploying atomically to Pages.

Stable application releases are discovered dynamically, not maintained in a
fixed list. EOL dates and policy remain in `versioning/lifecycle.json`.
The API version is always taken from the application manifest, not from the
Nextcloud release number or a guessed API URL.

## Validate a change locally

On the branch containing the publishing tool (`main`):

```sh
python -m pip install -r requirements.txt openapi-spec-validator==0.7.2
python -m unittest discover -s tests -v
node --test tests/js/*.test.mjs
python -m versioning.build --output _build
python -m versioning.verify --output _build
python -m versioning.publish --built _build --destination _publish
python -m versioning.verify --output _publish
python -m http.server 8765 --directory _publish
```

The build needs read-only network access to application Git refs and files.
It fails rather than substituting an outdated or development-branch contract.
Sphinx is compiled with warnings as errors, OpenAPI provenance and links are
checked, and the PR preview is tested at the public preview origin. Screenshots
are not generated or required. Version numbers and documentation pages are
not maintained in capture scripts.

## Pull request previews

The `Documentation PR Preview` workflow builds the full multiversion
candidate without changing production Pages. The URL pattern is:

```text
https://libresign.github.io/site-preview/docs-preview/pr-<number>/
```

The preview lives on the **isolated preview origin**, in the
`LibreSign/site-preview` repository, under its own `docs-preview/`
namespace. The production domain `docs.libresign.coop` is never used for
unreviewed HTML. A preview banner identifies the PR, and all version
selection, redirects and links stay within the preview prefix.

The workflow authenticates to the preview repository through the existing
organization GitHub App `librecode-workflow-automation`. It requires
`vars.LIBRECODE_WORKFLOW_APP_ID` and
`secrets.LIBRECODE_WORKFLOW_APP_PRIVATE_KEY` (the organization already
distributes these to its repositories). The app token is short-lived and
restricted to `LibreSign/site-preview`; no personal PAT needs copying.

For PRs originating in this repository, the workflow publishes the full
navigable preview, verifies the publicly hosted routes, and posts a sticky
comment containing direct links. When the development major has unreleased
release-specific overlays (for example, an event reference before a stable
branch exists), they are built under `/_review/<major>/` with the
development application's contract. A dedicated `/_review/` landing page
links to every rendered overlay page. None of those pages is inserted into
`versions.json`, the version selector or production Pages.

For forks, the unprivileged workflow only uploads an HTML artifact; the
trusted `workflow_run` consumer checks its static files, publishes it and
verifies its public URLs without executing fork code while possessing the
deployment token. The existing preview action posts the PR link; the preview
homepage also links to `/_review/`, so no second comment script is needed.
Upon closing the PR, the trusted cleanup workflow removes the preview.

The preview action and organization App do not publish stable documentation.
Successful preview CI is **not authorization to merge**.

## Releases and backports

1. Confirm the application release/backport and its manifest and OpenAPI.
2. Review changes to `versioned/<major>/`; keep the stable content bounded
by the branch's actual capabilities.
3. Open a documentation PR, inspect the navigable preview (including
`/_review/` when relevant), and wait for CI checks.
4. After approval and merge, the `Deploy Sphinx Docs` workflow deploys
the complete site. For a targeted update, dispatch with
`version: <major>` or `version: main`. The application release
tooling may send `repository_dispatch` events named
`libresign-documentation-release` or
`libresign-documentation-backport` with
`client_payload.version`.
5. The daily scheduled workflow also discovers new stable application
branches and captures subsequent backports. Each line is built from a
pinned commit of its application branch.
6. Partial releases first check out the existing `gh-pages` site and
**replace only the selected version**; they fail if the old catalog
or another previously published version is missing. Full releases must
build every version before deployment.
7. Test each published major/manual URL and its corresponding
`openapi.provenance.json`. The root URL lists every available version
(latest stable first); legacy, unversioned manual URLs redirect to the
current stable line.

Pages deployments are serialized by workflow concurrency. Their output must
never erase sibling stable versions.
The build requires read-only Git access to the LibreSign application and
this documentation repository. All released application versions must have
an existing documentation source branch before CI can publish them.

When editing a `stableNN` documentation branch, the CI builds its local
manuals with Sphinx warnings treated as errors. It does **not** regenerate
all public releases; the publication workflow on `main` does that.

## PR previews

The main-branch PR workflow builds a complete isolated candidate on
`https://libresign.github.io/site-preview/docs-preview/pr-<number>/`.
Development documentation already exists at `/main/`; it is not duplicated
in a fake stable version under `/_review/NN/`. The `/_review/` index links to
the actual development manual and its preview. The separate preview origin is
never the production domain. PRs from forks are deployed only by the
privileged workflow after static-artifact inspection.

The sticky preview comment includes stable and development entry links.
A successful preview does not authorize a merge.

## Release procedure

1. Review and approve the application release manifest and its OpenAPI.
2. Freeze approved documentation for the release in `main`.
3. Create a DCO-signed documentation branch `stableNN` from that snapshot,
**before** publishing the application's newly released major in the site.
4. Update the `main` documentation for the next development cycle as needed.
5. Run the central build and verify its HTML pages, exact API provenance,
correct GitHub edit links, and version selector.
6. Deploy via `Deploy Sphinx Docs` after review.

To fix an older release, backport the documentation change to its `stableNN`
branch. The central scheduled workflow sees both application and documentation
updates; for faster updates, run `workflow_dispatch` with `version: NN`.
Partial publication replaces only the selected release and preserves all
others. Full publication validates every version before deployment. Existing
unversioned URLs remain pinned through `versioning/legacy-routes.json`;
they must not be redirected silently to a newer API or a different release.

GitHub Pages deployments are serialized. Publishing unreleased material to
`docs.libresign.coop` requires an explicitly authorized release process.
Loading