Skip to content

fix(ci): the registry cache must not carry the resolved index - #390

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/registry-cache-tracks-the-index
Sep 11, 2026
Merged

fix(ci): the registry cache must not carry the resolved index#390
Sunrisepeak merged 1 commit into
mainfrom
fix/registry-cache-tracks-the-index

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

The bug

actions/cache held all of ~/.mcpp/registry — including data/xim-pkgindex and data/mcpplibs, the resolved indices, the descriptors mcpp actually reads. The key's restore-keys prefix ends at MCPP_VERSION:

restore-keys: |
  mcpp-registry-${{ runner.os }}-${{ matrix.toolchain }}-${{ env.MCPP_VERSION }}-

So a run restored whatever index the previous run left behind, regardless of what had landed upstream in between.

It already cost a day

Two successive fixes to xim:wix (openxlings/xim-pkgindex#808, then #809) were each merged, each re-run here, and each appeared to change nothing. Both were read as "the fix does not work" — and the second was written on that false premise. Neither had ever been loaded.

The tell was in the logs the whole time: 7zip, which #809 declares as a dependency, appeared zero times in a run that was supposedly testing #809. A fix that is not in the log is not being tested.

What eventually refreshed the index was moving MCPP_VERSION for unrelated reasons — a coincidence of cache-key composition, not a mechanism anyone chose. Until then the effective rule was: a change to a xim package cannot be verified from this repo's CI.

Why exclude rather than key on the index revision

Keying would evict everything on every upstream commit. Measured on a developer machine:

size
data/xim-pkgindex + data/mcpplibs ~8 MB
data/xpkgs ~28 GB

Re-fetching 8 MB per job is the cheap half, and it is the half that has to be current. Rebuilding 28 GB because a descriptor changed in another repository is the expensive half, and it does not.

path: |
  ~/.mcpp/registry
  !~/.mcpp/registry/data/xim-pkgindex
  !~/.mcpp/registry/data/mcpplibs

Payloads and toolchains stay cached; the indices stop being.

Note

index-snapshots/<repo>/<sha>/ is deliberately left cached — it is keyed by commit, so it self-invalidates and a stale entry is simply never asked for.

`actions/cache` held all of `~/.mcpp/registry`, and that includes
`data/xim-pkgindex` and `data/mcpplibs` — the RESOLVED indices, the
descriptors mcpp actually reads. The key's `restore-keys` prefix ends at
MCPP_VERSION, so a run restored whatever index the previous run left
behind, regardless of what had landed upstream in between.

THIS ALREADY COST A DAY

Two successive fixes to `xim:wix` (openxlings/xim-pkgindex#808, then #809)
were each merged, each re-run here, and each appeared to change nothing.
Both were read as "the fix does not work" and the second one was written
on that false premise. Neither had ever been loaded.

The tell was in the logs the whole time: `7zip`, which #809 declares as a
dependency, appeared ZERO times in a run that was supposedly testing #809.
A fix that is not in the log is not being tested.

What eventually refreshed the index was moving MCPP_VERSION for unrelated
reasons — a coincidence of cache-key composition, not a mechanism anyone
chose. Until then the rule was, in effect: **a change to a xim package
cannot be verified from this repo's CI.**

EXCLUDE, DO NOT KEY ON IT

Adding the index revision to the key would evict everything on every
upstream commit. Measured on a developer machine: the two index trees are
~8 MB, `data/xpkgs` is ~28 GB. Re-fetching 8 MB per job is the cheap half
and it is the half that has to be current; rebuilding 28 GB because a
descriptor changed in another repository is the expensive half and it does
not.

So the payloads and toolchains stay cached and the indices stop being.
@Sunrisepeak

Copy link
Copy Markdown
Member Author

The one red check is inherited from main, not introduced here.

Image: windows-2022
loader ... FAIL (exit -1073741515, 0.03s)
  vulkan   6s  FAIL

0xC0000135 is STATUS_DLL_NOT_FOUND: the windows-2022 image carries no vulkan-1.dll, and main is pinned there by #385. This PR touches only the cache path: list. #388 moves that pin to windows-2025 and the failure goes with it.

@Sunrisepeak
Sunrisepeak merged commit 409a433 into main Sep 11, 2026
25 of 28 checks passed
@Sunrisepeak
Sunrisepeak deleted the fix/registry-cache-tracks-the-index branch September 11, 2026 11:23
Sunrisepeak added a commit that referenced this pull request Sep 11, 2026
Every reason to distrust the diff used to escalate to the whole workspace.
On a PR that is the wrong trade twice over: it buries the change under ~22
shards of unrelated work, and it puts the PR's own legs behind an hour of
queue, so the thing under review is the last thing to report.

Touching this file was enough to trigger it, which is the case that keeps
biting: a one-line CI edit cannot be reviewed against a fast signal.
Measured three times today -- #390, #391 and #392 each ran a full matrix to
validate a change whose blast radius was one job.

`full` now answers only where "check everything" IS the request: the weekly
cron and a manual `workflow_dispatch`. On a PR or a push, the same reasons
call `widen` instead, which records them, prints them, and writes them to
the run summary so a reviewer sees WITHOUT opening a job that this run
deliberately tested less -- and that the sweep is one manual dispatch away.

Degraded, with their reasons kept:

    .github/workflows/validate.yml, tests/*.sh
    mcpp.toml non-member change
    unclassified path
    push with no predecessor / predecessor not in history

NOT weakened: descriptor and member changes select their members exactly as
before. The only thing that changed is what happens when the diff cannot be
classified.

One consequence handled. `widen` does not exit, so the push-with-no-
predecessor path has to leave a usable range behind. `HEAD` alone would diff
root-to-HEAD, name every file and select every member -- a full run by
another name, which is what this change exists to stop. It leaves the range
EMPTY instead: nothing selected, the reason already said, the summary
carrying it to a human. Rare either way, since merges here are squashes and
`event.before` is present on every normal push.

The weekly Sunday 06:00 sweep is deliberately kept. It is the only thing
that would have caught the windows vulkan regression before a user did --
main's leg was pinned to `windows-2022` in #385 and the vulkan members were
never re-tested there until a full run happened to fire today. Removing the
automatic full run on PRs and keeping the periodic net is the same shape
openxlings/xim-pkgindex#815 just added on the other side.

Verified: the rendered fragment on `pull_request` with a validate.yml edit
plus an unclassified path selects only the member its descriptor change
names, and the same input under `workflow_dispatch` still goes full.

Co-authored-by: sunrisepeak <x.d2learn.org@gmail.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.

1 participant