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
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ body:
- sphinx-mounts
- sphinx-codelinks
- sphinx-test-reports
- ub-test-reports
- ub-project
- the repository (workflows, CI, release, docker, tooling)
validations:
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ body:
- sphinx-mounts
- sphinx-codelinks
- sphinx-test-reports
- ub-test-reports
- ub-project
- the repository (workflows, CI, release, docker, tooling)
validations:
Expand Down
8 changes: 6 additions & 2 deletions .github/issue-labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
# patterns case-insensitive, like the workflow's `contains()` gate, so the two agree.
'pkg: sphinx-needs':
- '/### Package[^#]*\bsphinx-needs\b/i'
# No two of `sphinx-needs`, `sphinx-mounts`, `sphinx-codelinks`, `sphinx-test-reports` and
# `ub-project` contains another as a \b-delimited word, so no two patterns can match one choice. Every
# No two of `sphinx-needs`, `sphinx-mounts`, `sphinx-codelinks`, `sphinx-test-reports`,
# `ub-test-reports` and `ub-project` contains another as a \b-delimited word, so no two patterns
# can match one choice (`ub-test-reports` is not a word inside `sphinx-test-reports`: the
# `-` before `test` is a boundary, but the pattern needs `ub-` there). Every
# pattern has to be present before its option is offered by a form, though: the workflow
# runs with `sync-labels: 1`, so a pattern that is missing when its option is picked means
# the label is synced away rather than merely not added
Expand All @@ -18,6 +20,8 @@
- '/### Package[^#]*\bsphinx-codelinks\b/i'
'pkg: sphinx-test-reports':
- '/### Package[^#]*\bsphinx-test-reports\b/i'
'pkg: ub-test-reports':
- '/### Package[^#]*\bub-test-reports\b/i'
'pkg: ub-project':
- '/### Package[^#]*\bub-project\b/i'
'pkg: workspace':
Expand Down
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
'pkg: sphinx-needs-testkit':
- changed-files:
- any-glob-to-any-file: 'packages/sphinx-needs-testkit/**'
'pkg: ub-test-reports':
- changed-files:
- any-glob-to-any-file: 'packages/ub-test-reports/**'
'pkg: ub-project':
- changed-files:
- any-glob-to-any-file: 'packages/ub-project/**'
Expand Down
184 changes: 141 additions & 43 deletions .github/workflows/ci.yaml

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ name: Release
# `<dist>-v<version>`, where <dist> is a directory name under `packages/`.
#
# The filename is load-bearing and must not change: every publishable member's PyPI project
# (sphinx-needs, sphinx-mounts, sphinx-codelinks, sphinx-test-reports, ub-project) names
# `release.yaml` in its trusted-publisher entry.
# (sphinx-needs, sphinx-mounts, sphinx-codelinks, sphinx-test-reports, ub-project,
# ub-test-reports) names `release.yaml` in its trusted-publisher entry -- ub-test-reports' is
# created, as a pending publisher, before its first tag.
#
# The leading `*` in the tag filter is deliberately loose -- GitHub's tag filters are globs,
# not regexes, and cannot express "one of these four names" -- and the `plan` job is what
# not regexes, and cannot express "one of these names" -- and the `plan` job is what
# refuses everything else. That order matters: GitHub *creates* an environment that a
# workflow names and that does not exist, with no protection rules at all, so
# `environment: pypi-${{ needs.plan.outputs.dist }}` is a fence only for the names that
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/test-extensions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ jobs:
flags: reports
files: ./reports.xml
fail_ci_if_error: true
- name: "ub-test-reports: pytest"
# sphinx-test-reports' Sphinx-free core: the converter, the pytest plugin, the parsers
# and the `[test_reports]` model. Here for every cell's platform and interpreter --
# Windows above all, where the converter's path handling and the plugin's source
# locations are the platform-sensitive part -- and for coverage under a flag of its
# own; `toolchain-free` in ci.yaml stays the run that proves it imports no Sphinx.
# Same `if:` as the steps above
if: ${{ !cancelled() && steps.prepare.outcome == 'success' }}
run: uv run --no-sync pytest -v packages/ub-test-reports/tests --cov=ub_test_reports --cov-report=xml:ub-test-reports.xml --cov-report=term-missing
- name: "ub-test-reports: upload to Codecov"
if: inputs.upload-coverage && github.event.pull_request.head.repo.full_name == github.repository && github.repository == 'useblocks/sphinx-needs' && github.actor != 'dependabot[bot]'
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
name: ub-test-reports-pytests
flags: ub-test-reports
files: ./ub-test-reports.xml
fail_ci_if_error: true
- name: "ub-project: pytest"
# The shared `ubproject.toml` reader, which every extension above is to depend on.
# Its suite takes under a second and needs nothing this cell does not already have;
Expand Down
30 changes: 17 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ the shim.
| its documentation | `packages/sphinx-needs/docs/` (changelog: `docs/changelog.rst`) |
| sphinx-mounts' behaviour, tests, documentation | `packages/sphinx-mounts/{src/sphinx_mounts,tests,docs}/` — start at [`packages/sphinx-mounts/AGENTS.md`](packages/sphinx-mounts/AGENTS.md) |
| sphinx-codelinks' behaviour, tests, documentation | `packages/sphinx-codelinks/{src/sphinx_codelinks,tests,docs}/` — start at [`packages/sphinx-codelinks/AGENTS.md`](packages/sphinx-codelinks/AGENTS.md) |
| sphinx-test-reports' behaviour, tests, documentation | `packages/sphinx-test-reports/{src/sphinx_test_reports,tests,docs}/` — start at [`packages/sphinx-test-reports/AGENTS.md`](packages/sphinx-test-reports/AGENTS.md) |
| sphinx-test-reports' behaviour (the Sphinx extension), tests, documentation | `packages/sphinx-test-reports/{src/sphinx_test_reports,tests,docs}/` — start at [`packages/sphinx-test-reports/AGENTS.md`](packages/sphinx-test-reports/AGENTS.md); its `docs/` are ub-test-reports' too |
| ub-test-reports' behaviour (the converter, the pytest plugin, the parsers, the `[test_reports]` model — no Sphinx), tests | `packages/ub-test-reports/{src/ub_test_reports,tests}/` — start at [`packages/ub-test-reports/AGENTS.md`](packages/ub-test-reports/AGENTS.md) |
| how every tool reads `ubproject.toml` — finding, anchoring, `[variants]`, the variant-data merge | `packages/ub-project/{src/ub_project,tests,design}/` — start at [`packages/ub-project/AGENTS.md`](packages/ub-project/AGENTS.md) |
| the fixtures, helpers and renderer resolution three suites share | `packages/sphinx-needs-testkit/` — a member this repository never publishes, installed through the root's `test` group and loaded by each suite's `tests/conftest.py` as a pytest plugin |
| the three conformance corpora | `packages/sphinx-needs/tests/conformance/` (needflow) and `packages/sphinx-mounts/tests/fixtures/variant_condition_conformance.toml` (variant conditions), whose repository of record is ubCode, and `packages/ub-project/tests/fixtures/ubproject_reading_conformance.toml` (reading `ubproject.toml`), whose record is THIS repository and which ubCode is to vendor — all shared byte-for-byte; do not reformat any of them (`.gitattributes` plus the yamlfmt and taplo excludes protect them) |
Expand All @@ -37,7 +38,7 @@ the shim.
| the PlantUML renderer | `vendor/plantuml/` — `pin.toml` (version + sha256, the one place either is written), the committed `plantuml-<version>.jar` it names, and a `README.md`. `uv run poe verify-plantuml` fences the two against each other |
| CI | `.github/workflows/`, and `.github/scripts/` for the three checks that must run *inside* a CI environment |
| the docker image | `docker/` — a repository-level deliverable, like the workflows |
| Read the Docs | sphinx-needs: `.readthedocs.yml`, and it stays at the root under that exact name — the configuration path applies to every version, so moving it makes older tags unbuildable. sphinx-mounts: `packages/sphinx-mounts/.readthedocs.yaml`, sphinx-codelinks: `packages/sphinx-codelinks/.readthedocs.yaml`, and sphinx-test-reports: `packages/sphinx-test-reports/.readthedocs.yaml`, each of which its own RTD project points at; every path inside those is relative to the REPOSITORY root, not to the file |
| Read the Docs | sphinx-needs: `.readthedocs.yml`, and it stays at the root under that exact name — the configuration path applies to every version, so moving it makes older tags unbuildable. sphinx-mounts: `packages/sphinx-mounts/.readthedocs.yaml`, sphinx-codelinks: `packages/sphinx-codelinks/.readthedocs.yaml`, and sphinx-test-reports: `packages/sphinx-test-reports/.readthedocs.yaml`, each of which its own RTD project points at; every path inside those is relative to the REPOSITORY root, not to the file. ub-test-reports has no RTD project: it is documented on sphinx-test-reports' site, whose yaml installs it from the checkout first. ub-project has no docs site |

**`tools/` is the workspace's tooling — a virtual member, never released, whose manifest
declares the tooling's dependencies; `.github/scripts/` keeps only the checks that must
Expand Down Expand Up @@ -75,17 +76,18 @@ rejects on upload, for the by-hand path.
nothing**: standard library only, no Sphinx, fenced by its own `tests/test_imports.py` and
by CI's `toolchain-free` job, which runs its suite where Sphinx is not installed. Its
contract is its conformance corpus (ubCode is to vendor it) plus `design/reading-contract.md`;
it decides no policy — discovery, warnings and `-D` stay with each consumer. No member
depends on it yet: every `--no-sources` gate resolves a consumer from the index, so the
consumers arrive one pull request each after its first release, and from then on each
release of it re-floors all of them.
it decides no policy — discovery, warnings and `-D` stay with each consumer. sphinx-needs,
sphinx-mounts, sphinx-codelinks and ub-test-reports depend on it, so each release of it
re-floors all of them (`propagate_floors.py`).

**Naming: `sphinx-*` is a Sphinx extension; `ub-*` is a useblocks package that is not one**
— a tool (such as the future `ub-test-reports`) or a library (such as `ub-project`, import
`ub_project`). The name does not say which of the two a `ub-*` package is; its README and
— a tool (such as `ub-test-reports`, import `ub_test_reports`) or a library (such as
`ub-project`, import `ub_project`). The name does not say which of the two a `ub-*` package is; its README and
classifiers do. A `ub-*` library says in its README's first line that it is a library for
the sphinx-needs family which the extensions pull in, and carries no `Framework :: Sphinx`
classifier. Its poe tasks keep the whole name (`test-ub-project`): only `sphinx-` is dropped.
classifier; a `ub-*` tool says it is a tool for the family, and carries none either. Their
poe tasks keep the whole name (`test-ub-project`, `test-ub-test-reports`): only `sphinx-` is
dropped.

## Commands

Expand All @@ -96,6 +98,7 @@ uv run poe test-needs -k <expr> # trailing words are appended to the task'
uv run poe test-mounts # the sphinx-mounts suite (bazel tests deselected)
uv run poe test-codelinks # the sphinx-codelinks suite (adds the libclang group)
uv run poe test-reports # the sphinx-test-reports suite
uv run poe test-ub-test-reports # the ub-test-reports suite (no Sphinx needed)
uv run poe lint # every prek hook over the whole tree
uv run poe typecheck # ty over both packages, against the oldest supported sphinx
uv run poe typecheck-js-needs # tsc over the vendored needstable.js (needs node)
Expand All @@ -110,6 +113,7 @@ uv run poe check-workspace # the manifests agree with each other (Lin
uv run poe release-plan # what is pending, in what order (advice; exits 0)
uv run poe bump <dist> --bump minor # stamp a release: version, literals, floors, lock, changelog
uv run poe import-check-needs # import the wheel against PyPI-resolved dependencies
uv run poe import-check-ub-test-reports # the same for ub-test-reports (with its pytest extra)
uv run poe import-check-codelinks # the same for sphinx-codelinks (with its libclang extra)
uv run --frozen --no-sync pytest tools/tests -q # the tooling's own tests
UV_PYTHON=3.12 uv run --no-sync poe test-needs-sphinx8 # one CI matrix cell
Expand Down Expand Up @@ -169,7 +173,7 @@ and the testkit all are. The sdist is ≈7.4 MB rather than 28.

**sphinx-test-reports is the two cases at once**: its SUITE needs neither renderer (no test
document carries a rendering directive, and the dead 8.6 MB jar its tests used to carry left
with the import), while `docs-reports` DOES render — 13 `needflow` directives — so it needs
with the import; ub-test-reports' suite needs none either), while `docs-reports` DOES render — 13 `needflow` directives — so it needs
`java` and `dot`, and its `.readthedocs.yaml` keeps `apt_packages` where both SIBLING
extensions' have none. (sphinx-needs' own docs render too, and more: 48 needflow
directives.)
Expand Down Expand Up @@ -251,12 +255,12 @@ the rootdir, so the tasks carry `--ignore=performance` instead of naming `tests`
the task's own command would be *added* to yours rather than replaced by it.)

**A bare `pytest` at the root collects sphinx-needs' suite and the tooling's — not
sphinx-mounts', sphinx-codelinks', sphinx-test-reports' or ub-project's.** Their `tests` directories are deliberately
sphinx-mounts', sphinx-codelinks', sphinx-test-reports', ub-test-reports' or ub-project's.** Their `tests` directories are deliberately
absent from `testpaths`: every package ships a `tests/__init__.py`, so under
`--import-mode=importlib` every `conftest.py` resolves to the module name `tests.conftest`
and a rootdir-invoked pytest refuses the second outright — listing one there collects
*nothing*, rather than more. Run those suites through `poe test-mounts`,
`poe test-codelinks`, `poe test-reports` and `poe test-ub-project` (which cd into the package), the way CI does
`poe test-codelinks`, `poe test-reports`, `poe test-ub-test-reports` and `poe test-ub-project` (which cd into the package), the way CI does
with an explicit path.
The Lint job's "Check a bare root pytest still collects" step is what keeps the list
honest.
Expand Down Expand Up @@ -457,7 +461,7 @@ removed* (`error-on-warning` makes an unused suppression an error), never by loo

Every issue and pull request carries one or more `pkg:` labels naming what it concerns:
`pkg: <package>` (today `pkg: sphinx-needs`, `pkg: sphinx-mounts`,
`pkg: sphinx-codelinks`, `pkg: sphinx-test-reports`, `pkg: sphinx-needs-testkit` and `pkg: ub-project`) or `pkg: workspace` for the repository
`pkg: sphinx-codelinks`, `pkg: sphinx-test-reports`, `pkg: sphinx-needs-testkit`, `pkg: ub-test-reports` and `pkg: ub-project`) or `pkg: workspace` for the repository
itself — workflows, CI, release, docker, tooling, the workspace root. Pull requests get
theirs automatically from the paths they touch (`.github/labeler.yml`); the issue forms
set it from their "Package" dropdown (`.github/issue-labeler.yml`). **An issue created
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ definitions and the CI workflows.
| [`packages/sphinx-needs`](packages/sphinx-needs) | [`sphinx-needs`](https://pypi.org/project/sphinx-needs/) | the Sphinx extension for managing requirements and specifications — [documentation](https://sphinx-needs.readthedocs.io), [README](packages/sphinx-needs/README.rst) |
| [`packages/sphinx-mounts`](packages/sphinx-mounts) | [`sphinx-mounts`](https://pypi.org/project/sphinx-mounts/) | the Sphinx extension that mounts external source trees into a build without copying or symlinking — [documentation](https://sphinx-mounts.useblocks.com), [README](packages/sphinx-mounts/README.md) |
| [`packages/sphinx-codelinks`](packages/sphinx-codelinks) | [`sphinx-codelinks`](https://pypi.org/project/sphinx-codelinks/) | fast source-code traceability for sphinx-needs — it scans source files for comment markers, turns them into needs, and links documentation to exact source lines — [documentation](https://codelinks.useblocks.com), [README](packages/sphinx-codelinks/README.md) |
| [`packages/sphinx-test-reports`](packages/sphinx-test-reports) | [`sphinx-test-reports`](https://pypi.org/project/sphinx-test-reports/) | test results as needs: JUnit/ctest/googletest XML and tox-envreport JSON become needs in a build, and a `test-reports` command turns the same reports into a `needs.json` without running Sphinx — [documentation](https://sphinx-test-reports.readthedocs.io), [README](packages/sphinx-test-reports/README.rst) |
| [`packages/sphinx-test-reports`](packages/sphinx-test-reports) | [`sphinx-test-reports`](https://pypi.org/project/sphinx-test-reports/) | test results as needs: the Sphinx extension in which JUnit/ctest/googletest XML and tox-envreport JSON become needs in a build — [documentation](https://sphinx-test-reports.readthedocs.io), [README](packages/sphinx-test-reports/README.rst) |
| [`packages/ub-test-reports`](packages/ub-test-reports) | `ub-test-reports` (not yet on PyPI) | the Sphinx-free half of test reports, which sphinx-test-reports depends on: the `test-reports` command that turns reports into a `needs.json` without running Sphinx, the pytest plugin, the parsers — documented on sphinx-test-reports' site, [README](packages/ub-test-reports/README.rst) |
| [`packages/ub-project`](packages/ub-project) | [`ub-project`](https://pypi.org/project/ub-project/) | the shared reader for `ubproject.toml` and its variant data, which the other packages depend on — no documentation site, [README](packages/ub-project/README.rst) |

## Why one repository, and why still several packages

Expand Down
15 changes: 11 additions & 4 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# One repository, three packages, three coverage uploads -- so three flags with targets of
# their own. Without them all three would land on the `default` status and a young
# package's coverage would be averaged into a mature one's 80%, moving a gate nobody
# decided to move.
# One repository, one coverage upload per package -- so one flag each, with a target of its
# own. Without them every upload would land on the `default` status and a young package's
# coverage would be averaged into a mature one's 80%, moving a gate nobody decided to move.
coverage:
status:
project:
Expand Down Expand Up @@ -32,6 +31,14 @@ coverage:
flags: [reports]
target: auto
threshold: 0.5%
# ub-test-reports, sphinx-test-reports' Sphinx-free core, uploaded by the same cell with
# `flags: ub-test-reports`. `target: auto` because its statements MOVED out of
# `reports` when the core was split off -- that flag's number moves with them, and
# neither number says anything about a change in coverage on that pull request
ub-test-reports:
flags: [ub-test-reports]
target: auto
threshold: 0.5%
patch:
default:
target: 67%
Expand Down
Loading
Loading