Across the repositories
On this page
Working across the repositories
../README.md is the front page; making a change that crosses
repositories is contributing.md.
What the umbrella is for, what each of its checks catches, and what it leaves to the nine.
What it is for
Each repository proves its own change with its own gate. What none of them
can prove is that a change to a public item still builds what depends on it,
because every dependency between them is a git dependency on main — a
pushed revision, not the working tree beside it. Cargo.toml's [patch]
table redirects every one of those at the sibling checkout on disk, so one
build here compiles the working trees rather than the pushed revisions.
It does not reach everything. The build graph is what gate/ names:
xpui, xpui-chrome, the four board crates, both backends,
xpui-screenshot, xpui-simulator and xpui-gallery. The two firmwares and
xpui-cpp are outside it — nothing depends on them — and the full run does
not close the gap either, because each sibling's own gate resolves its git
dependencies against pushed main. A local, unpushed change to xpui is
never compiled against a firmware or the C++ host in any mode here. Push
xpui first, then run those two repositories' own gates.
The trap in [patch]
Cargo matches a patch to a dependency by URL string. A trailing .git,
http for https, or a different case, and the patch silently does not
apply — the build succeeds against the pushed revision, and the local change
is not tested at all. Cargo.lock is where to check: every xpui* crate
should have no source line.
A sibling that is missing is not silent: a [patch] path that does not
exist is a hard cargo error before any stage runs.
every repository is checked out beside this one is first among the
cross-repository stages so that the three unpatched repositories — the two
firmwares and xpui-cpp — are named too, in one message rather than nine.
The lock file that does not travel
Cargo.lock here is resolved against the patched paths, so it records what
the stack looked like on the machine that last ran the gate rather than what
a fresh clone of the nine would resolve to. Treat it as a local artifact.
every lock file agrees about the shared crates reads this one and every
sibling's, the monorepo's included, so a local lock that drifts fails the
stage like any other: embedded-graphics, embedded-graphics-core,
critical-section and u8g2-fonts cross repository boundaries as types,
and a DrawTarget from one major version of embedded-graphics-core is not
the next one's — the compiler names the same path twice in one error and
blames a trait rather than a version. Only a semver-incompatible pair can do
it; cargo unifies 0.8.1 with 0.8.2.
What is shared, and how
Nothing is published and there is no submodule, so a file that every repository needs is copied, and a copy nobody compares is a fork with a delay on it. Two kinds are compared:
-
Files, byte for byte, each across the repositories that hold it:
LICENSE,clippy.tomlall eleven — the nine, this one, and the monorepo while it exists SECURITY.md,CODE_OF_CONDUCT.md, both.github/ISSUE_TEMPLATE/*.yml,.github/PULL_REQUEST_TEMPLATE.md,.github/dependabot.yml, both.claude/agents/*.mdthe ten ten xtaskmodulesthe nine: reading a markdown fence, a manifest, a path and a comment is the same job everywhere .gitignorenine of the ten; xpui-cpp's is a superset with the PlatformIO lines, and there is no superset modebuild-and-test.shsix xtask/src/cpp.rsthe two that hold C++ xtask/src/cargo.rsin three shapes — xpui-rp2040addshost_triplebecause its cargo config targets the board, andxpui-simulatorandxpui-cppdroptarget_installedbecause neither has a bare-metal lintrust-toolchain.toml'schannellineall eleven, so a warning means the same thing everywhere Each repository's
xtask/src/main.rsis deliberately not compared; it is that repository's own list of checks. The FreeInk SDK revision is compared by a stage of its own. -
Sections, as text: the
## Where it sitsdiagram in every README, apart from thestyleline that bolds the repository you are in, and the[workspace.lints]table in every workspace root — more of those than there are repositories:xpui-rp2040'sdocs-test/andxtask/, andxpui-esp32'sdocs-test/, are workspaces themselves.
A change to any of them is made in all ten in one sitting, or the umbrella fails on the first push; contributing.md says how.
What each check catches
| every repository is checked out beside this one | names every missing one in a single message, before nine other stages fail one at a time with worse ones. A patched sibling that is gone is a hard cargo error; one present but not a git checkout would pass silently |
| every shared file is one file | twenty-five paths in twenty-seven comparisons — the table above, each across the repositories that hold it |
| every shared section is one section | the diagram across the ten READMEs, and the [workspace.lints] table across every workspace root — more than one per repository, because xpui-rp2040's docs-test/ and xtask/, and xpui-esp32's docs-test/, declare a [workspace] of their own |
| both repositories pin the same SDK revision | xpui-backends compiles the shim against the SDK's headers and xpui-cpp links it; a revision written down twice is one that will disagree with itself |
| every organisation URL names a file that is there | each repository's documented paths resolve reads relative links and says so; nothing else reads a github.com/XPUI-Framework/… URL, and this resolves its blob/main and tree/main links against the sibling's pushed origin/main |
| every lock file agrees about the shared crates | the four crates above |
| every repository gates itself | all only: each sibling's ./build-and-test.sh, from its own root |
| every crate, from local paths | cargo build --workspace and cargo test --workspace through the [patch] table, so what is tested is what is on disk |
What cross skips
cross is what CI runs, because each repository's own workflow has already
run its gate, and running all nine again would pay twice for the same checks.
So cross does not run:
- any sibling's gate — its lint for a bare-metal target, its comment checks, its README order, its doctests;
- anything in C++ — the format stage, the compiled
cppfences, the symbol check, the shim, the host and itsctestcases. CI here installs neither clang-format nor the FreeInk SDK, and needs neither; - any firmware image — the
allmode ofxpui-rp2040andxpui-esp32. Nor does the full run:every repository gates itselfinvokes each sibling's script with no argument, which is itscheckmode, and both firmwares put their link stages behindall. No image is linked here in either mode.
A change that touches any of those is proven in its own repository first,
then here. ./build-and-test.sh with no argument runs the nine gates too,
which is the twenty-minute version; iterate on cross.
Edit this page on GitHubIt lives in xpui-dev; a correction goes there.