Skip to content

✨ NEW: reference a pre-built HTML report from a mounted bundle (html_extra_path)#6

Merged
ubmarco merged 1 commit into
mainfrom
example-html-report
Jun 14, 2026
Merged

✨ NEW: reference a pre-built HTML report from a mounted bundle (html_extra_path)#6
ubmarco merged 1 commit into
mainfrom
example-html-report

Conversation

@ubmarco

@ubmarco ubmarco commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Demonstrates referencing a pre-built HTML report (e.g. an lcov tree) from a mounted bundle without copying sources, while keeping the rendered site self-contained.

The report is a static artefact, not a mounted source. The host conf.py lists it in Sphinx's html_extra_path, which copies it verbatim into the build output (<site>/coverage/) — so _build/html is self-contained and publishable anywhere — while the report itself is read in place from the Bazel output tree and is never staged into the docs source tree. The api-foo bundle ships a coverage page that links to and <iframe>-embeds it via the bundle-relative URL ../../coverage/index.html.

This is plain Sphinx (html_extra_path), not a new sphinx-mounts feature: mounts handle source trees, html_extra_path handles finished static artefacts, and they compose.

Changes

  • tests/example/coverage_report/ — genrule emitting a small lcov-style HTML report.
  • tests/example/docs/conf.py — conditional html_extra_path (set only when the report exists, so the -nW build degrades gracefully when the artefact is absent, mirroring the example's mount-absence stance).
  • tests/example/bundles/api-foo/BUILD.bazel — a coverage page (link + iframe) wired into the bundle toctree.
  • tests/example/BUILD.bazel, build_docs_sandbox.sh — materialise the report via :all_bundles and stage it for the sandboxed docs_html target.
  • tests/example/README.md — documents the pattern.

Tests

  • tests/test_example.py (bazel e2e): asserts the report is materialised, copied into the site output (self-contained), linked + embedded by the bundle page, and not staged into srcdir.
  • tests/test_mounting.py::test_mounted_bundle_links_html_extra_path_report (fast, non-bazel): the same pattern from scratch.

Docs / changelog

Example + README only — no shipped-library behavior change, so docs/source/ and the changelog are unchanged. Happy to add a changelog note if you'd prefer one.

Code quality

uv run prek run --all-files passes; uv run --group ty ty check clean; non-bazel suite green (107).

ubmarco added a commit that referenced this pull request Jun 14, 2026
## Summary

Adds **path confinement** for mounted bundles: a directive inside a
mounted bundle that references a file **outside the bundle root** now
fails the build by default, keeping bundles self-contained and portable.

Directives resolve file paths relative to the document's own location,
which for a mounted doc is the bundle on disk — so relative references
resolve *inside* the bundle. Two shapes escape: a leading-slash path
(`/foo`, "absolute from the source root" = the host `srcdir`) and a `..`
climb above the bundle root. Either drags an outside file into the host
build (and, for asset directives, copies it into the host's
`_images`/`_downloads` output, risking collisions with host files). The
check is **directive-agnostic** — it inspects `env.dependencies` for
each mounted doc — so it covers `literalinclude`, `include`,
`csv-table`/`raw` (`:file:`), `image`, `figure`, `graphviz`, `uml`,
`mermaid`, and any other directive that records a file dependency.

## Config
New per-mount `path_check` in `ubproject.toml`: `"error"` (default —
fail the build), `"warn"` (log a warning; escalates under `-W`), or
`"off"` (disable for that mount).

**Behavior change:** a bundle that today references a file via a leading
slash or `..` will now fail by default; set `path_check =
"warn"`/`"off"` to opt out.

## Tests
- `tests/test_path_directives.py` (new): happy-path resolution for all
nine file-referencing directives (host-side decoy proves
bundle-relative-not-host resolution; renderer-independent — mermaid
`raw`, plantuml/graphviz asserted via the recorded dependency), the two
leak boundaries, and enforcement (error/warn/off, directive-agnostic,
file-list mode, per-mount).
- `tests/test_config.py`: `path_check` validation + parse round-trip.
- `tests/test_example.py`: the Bazel example's `api-foo` bundle now
exercises all nine directives end-to-end under `-nW`.

## Docs / changelog
- `docs/source/configuration.rst`: new `path_check` option row + a "Path
confinement" section.
- `docs/source/changelog.rst`: Unreleased entry.

## Code quality
`uv run prek run --all-files` passes; `uv run --group ty ty check`
clean; non-bazel suite green (132); Bazel e2e green (with
`dot`/`java`/`plantuml` available).

> Note: overlaps with #6 in `tests/example/` (api-foo `BUILD.bazel`,
`docs/conf.py`, `README.md`, `test_example.py`); whichever merges second
will need a small conflict resolution.
@ubmarco ubmarco force-pushed the example-html-report branch from 134c437 to f0628e6 Compare June 14, 2026 21:01
@ubmarco ubmarco force-pushed the example-html-report branch from f0628e6 to 368051b Compare June 14, 2026 21:03
@ubmarco ubmarco merged commit 1be99f8 into main Jun 14, 2026
11 checks passed
@ubmarco ubmarco deleted the example-html-report branch June 14, 2026 21:06
@ubmarco ubmarco mentioned this pull request Jun 14, 2026
ubmarco added a commit that referenced this pull request Jun 14, 2026
## Release 0.1.1

Version bump `0.1.0 → 0.1.1` plus changelog stamp. No library code
changes — this is release-prep only.

### Changes
- `pyproject.toml` + `src/sphinx_mounts/__init__.py`: version `0.1.0 →
0.1.1`
- `uv.lock`: own-package version synced to `0.1.1`
- `docs/source/changelog.rst`: the accumulated `Unreleased` entries are
stamped as the `0.1.1` release (dated 2026-06-14), matching the `0.1.0`
block's format (label + `:Released:`), with no empty `Unreleased`
section left behind — same convention the `0.1.0` tag used.

### Included in 0.1.1
- **Per-mount `path_check`** option (`"error"` default / `"warn"` /
`"off"`) that confines mounted-bundle directives to the bundle root (#7)
- Regression coverage proving **absolute diagnostic locations** for
mounted docs (#9)
- Regression coverage proving **incremental rebuilds re-read** mounted
docs when their files / include targets change (#10)
- **Sphinx 8 CI coverage** — the matrix now exercises Sphinx 8 on Python
3.12 (full 7/8/9 coverage) (#11)

### Intentionally excluded from the changelog
- **#6 (`html_extra_path` example)** — the commit itself notes this is
stock Sphinx composing with mounts, *not* a sphinx-mounts feature; only
`tests/example/` + `tests/` changed, no `src/`.
- **#8** — CI-only (Bazel doc-build wiring).
- **#4** — docs-site sidebar link (cosmetic).

### Verification
- `uv run prek run` — all hooks pass (the CI `Prek` gate)
- `uvx ruff@0.12.2 format --check` — already formatted (CI's pinned
ruff)
- `sphinx-build -nW --keep-going` — docs build succeeds; changelog
renders

### After merge
Publishing is tag-driven (PyPI Trusted Publishing via `release.yaml`).
To cut the release:

```bash
git tag -a 0.1.1 -m "Release 0.1.1"
git push origin 0.1.1
```

The bare-semver tag (`0.1.1`, no `v`) matches the workflow trigger and
publishes to PyPI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant