Skip to content

Configure the sublibrary QA lanes for monorepo docs and facade reexports - #4018

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-sublibrary-qa-config
Jul 26, 2026
Merged

ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-sublibrary-qa-config

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

This PR should be ignored until reviewed by @ChrisRackauckas.

The failure

Every lib/* QA lane is red — ~45 sublibrary-ci / lib/… [QA] jobs. This is
easy to miss because the sublibrary matrix is path-filtered: a PR that does not
touch lib/ spawns zero sublibrary QA jobs, so its Sublibrary CI goes green
vacuously. #4014 touched lib/OrdinaryDiffEqCore/Project.toml, which triggered
the full matrix and surfaced it.

To be clear about causation: this pre-dates #4014. I checked out
eb3888cf7 (before that merge) and ran the Feagin QA lane directly:

$ ODEDIFFEQ_TEST_GROUP=QA julia +1.12 --project=lib/OrdinaryDiffEqFeagin -e 'using Pkg; Pkg.test()'
public API is rendered in docs: Test Failed
No unapproved public reexports: Test Failed
ERROR: LoadError: Some tests did not pass: 19 passed, 2 failed, 0 errored, 0 broken.

Why

SciMLTesting 2.x defaults api_docs and check_reexports to true. Both
assumptions are wrong for solver sublibraries:

1. Rendered docs. run_api_docs resolves docs_src to <pkgroot>/docs/src,
which no sublibrary has — lib/OrdinaryDiffEqFeagin/ contains only
src/ test/ Project.toml README.md LICENSE.md. A missing directory yields an
empty rendered set, so every public name is reported unrendered:

┌ Info: run_api_docs: public API names not rendered in a @docs block
│   pkg = OrdinaryDiffEqFeagin
│   docs_src = ".../lib/OrdinaryDiffEqFeagin/docs/src"
│   unrendered = 182-element Vector{Symbol}

These packages are documented in the umbrella manual, where the root QA lane
already checks rendering.

2. Facade reexports. The solver packages @reexport using SciMLBase (or
StochasticDiffEqCore / DiffEqBase) by design — several qa.jl files already
say so in a comment. With no reexports_allow, that deliberate surface is
reported wholesale (185 names for Feagin).

The fix

Per package, mirroring what #3988 did for the umbrella:

api_docs_kwargs = (; rendered = false),
reexports_allow = union(public_api_names(SciMLBase), (:SciMLBase,)),

Neither check is switched off:

  • the docstring half of the api-docs check stays on, so a public name with
    no docstring is still caught;
  • reexports from any package other than the deliberately-reexported one are
    still reported.

Mapping is mechanical, from each package's own @reexport using:
SciMLBase (30), StochasticDiffEqCore (9), DiffEqBase (2), no reexport (7 —
rendered = false only). The module name is already in scope via the package's
own reexport, so no test-environment or Project.toml changes are needed.
GlobalDiffEq and ImplicitDiscreteSolve already point docs_src at the monorepo
manual; their api-docs configuration is left alone.

Verification

Ran ODEDIFFEQ_TEST_GROUP=QA on Julia 1.12 (the version the QA lanes use),
covering every shape in the change:

Package Group Result
OrdinaryDiffEqFeagin SciMLBase tests passed
OrdinaryDiffEqExplicitRK SciMLBase, pre-existing api_docs_kwargs merged into tests passed
OrdinaryDiffEqDifferentiation no reexport tests passed
GlobalDiffEq DiffEqBase, bespoke docs_src preserved tests passed
ImplicitDiscreteSolve SciMLBase, bespoke docs_src preserved tests passed

What this does not fix

Some sublibraries stay red on a separate, pre-existing seam unrelated to
these two checks. In each case the two checks this PR targets do now pass:

  • OrdinaryDiffEqTsit5 — Public API documentation 1 pass, No unapproved public reexports 1 pass; still errors on ExplicitImports
    (all_qualified_accesses_are_public).
  • StochasticDiffEqMilstein — reexports check passes; Public API documentation still errors inside the docstring half with
    Constant binding was imported from multiple modules (a Julia 1.12
    binding_module interaction, not the rendered check).
  • OrdinaryDiffEqCore — rendered check passes; still has a stale explicit
    import (_unwrap_val) and a non-public qualified access.
  • StochasticDiffEqCore — still reports 22 reexported names (SDEIntegrator,
    SDEOptions, issplit, …). These are DiffEqBase-owned names the sublibrary
    exports even though DiffEqBase never declared them public. That is a real
    API-hygiene finding, so I deliberately did not allowlist it away — it
    wants either public declarations in lib/DiffEqBase or removal from the
    sublibrary export lists, as its own change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TPHRh64BLfoXSzQ3AxKNwC

SciMLTesting 2.x defaults `api_docs` and `check_reexports` to `true`. Both
assumptions are wrong for the `lib/*` solver packages, so every sublibrary QA
lane fails on two checks that cannot pass as configured:

* **rendered docs** — `run_api_docs` resolves `docs_src` to
  `<pkgroot>/docs/src`, which no sublibrary has. A missing directory yields an
  empty rendered set, so *every* public name reads as unrendered (182 names for
  OrdinaryDiffEqFeagin). These packages are documented in the umbrella
  OrdinaryDiffEq manual, where the root QA lane already checks rendering.

* **facade reexports** — the solver packages `@reexport using SciMLBase`
  (or StochasticDiffEqCore / DiffEqBase) by design; several qa.jl files already
  say so in comments. Without a `reexports_allow`, that deliberate surface is
  reported wholesale (185 names for Feagin).

Set `api_docs_kwargs = (; rendered = false)` and
`reexports_allow = union(public_api_names(M), (:M,))` for the module each
package reexports, mirroring what SciML#3988 did for the umbrella. The docstring
half of the api-docs check stays on, and reexports from any *other* package are
still reported, so neither check is disabled outright. `M` is in scope already
via the package's own reexport, so no test-environment changes are needed.

GlobalDiffEq and ImplicitDiscreteSolve already point `docs_src` at the monorepo
manual; their api-docs configuration is left as is.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review July 26, 2026 08:33
@ChrisRackauckas
ChrisRackauckas merged commit bf3d7a6 into SciML:master Jul 26, 2026
313 of 353 checks passed
ChrisRackauckas added a commit that referenced this pull request Jul 27, 2026
…es (#4029)

#4018 fixed the two systemic QA checks but left 27 sublibrary lanes red. The
largest remaining group is ExplicitImports flagging names that the Developer
Extension API page already declares out of scope:

    Cache types and low-level nonlinear solve helper functions are not public API.

Most of it is one omission: OrdinaryDiffEqCore's precompile workload grew
`lorenz_pref`/`lorenz_pref_params`, but the ignore lists that already carry
`lorenz`/`lorenz_oop`/`lorenz_p`/`lorenz_p_params` were never extended. The rest
are Base internals with no public equivalent (`structdiff`, `broadcastable`) and
imports kept in a namespace for dependent sublibraries, whose cross-package use
ExplicitImports cannot see (`_unwrap_val`, `MatrixOperator`, `_reshape`).

Extends the existing per-package ignore lists rather than disabling any check,
matching the pattern already in these files.

Verified with `ODEDIFFEQ_TEST_GROUP=QA` on Julia 1.12, the version the QA lanes
use. Every ExplicitImports error across the 27 is gone, and 9 lanes go fully
green: BDF, FIRK, LowStorageRK, RKN, SSPRK, Tsit5, Verner,
StochasticDiffEqImplicit, StochasticDiffEqLeaping.

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
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.

2 participants