Skip to content

fix: resolve the openkal index and runtime revisions once per run - #804

Open
ZheFeng7110 wants to merge 1 commit into
mcpp-community:mainfrom
ZheFeng7110:fix/ci-openkal-pinned-revisions
Open

ZheFeng7110 wants to merge 1 commit into
mcpp-community:mainfrom
ZheFeng7110:fix/ci-openkal-pinned-revisions

Conversation

@ZheFeng7110

Copy link
Copy Markdown
Member

Summary

openkal-cross.yml has four build jobs that each cloned main of
mcpp-community/mcpp-index and of mcpplibs/openkal-llvm-runtime of their own
accord, and three run jobs that then assert all four hosts built the same
sources. Four clones of a moving branch are not four copies of one revision.

That is what failed in run 38399400601
(PR #803, 2026-10-13): all three run jobs reported

::error::index sources differ

The run started at 12:43 UTC and its build jobs at 12:52:08, 12:53:44,
12:58:20 and 13:01:33 UTC, and they do not clone at the same point in their own
step sequence (the macOS leg builds its own mcpp first), while
mcpp-index@main took four commits inside that window — 21b9a77a 12:56:12,
d3a328c8 13:04:42, cfb808bc 13:10:06, 0340de61 13:17:58. Two clones
straddling one push is all it takes, and the reading arrives 40 minutes later
in a job that built nothing. Nothing about the change under test was involved,
and a rerun only re-rolls the dice.

The fix

  • A new revisions job runs first and resolves mcpp-index@main and
    openkal-llvm-runtime@$OPENKAL_BRANCH to one commit each.
  • The four build jobs materialise those commits instead of cloning a branch.
    The run jobs keep their cross-host comparison: it is now what proves a host
    used the pin rather than re-resolving for itself.
  • OPENKAL_BRANCH keeps its meaning — an override still verifies exactly what
    it named, resolved once instead of once per runner.

git_clone_retry.sh grows the two primitives that needs, under the retry the
helper already exists for (a resolver blip is not a red build):

  • --rev <ref> <url> — print the commit a ref names, without downloading the
    tree (ls-remote; both repositories are ~17 MB).
  • --commit <sha> <url> <dir> — materialise exactly that commit
    (init + fetch --depth 1 origin <sha>, since --branch takes a branch or
    a tag and a commit is neither).

Pinning a SHA into the workflow was the alternative and it is the wrong one:
it is the pin-nobody-is-reminded-to-move that the file's own OPENKAL_BRANCH
comment is annotated with.

Verification

  • git_clone_retry.sh: 16 cases against throwaway local repositories —
    --rev for a branch name, a full ref and HEAD; a ref that does not exist
    (exit 1, no retry); an unreachable URL (retries, then gives up); --commit
    for an older commit (detached, no stray branch ref), the tip, a 0…0 SHA and
    a non-SHA; a non-empty destination (self-heals); the plain-clone path and its
    partial-clone removal. All pass; bash -n clean.
  • Against GitHub itself: --rev main on mcpp-index resolved to
    0340de61ffc83f0eeeae459e74a4156b11935897, and --commit materialised
    exactly that commit (813 files, detached HEAD) — the fetch-by-SHA the pin
    depends on works on the host the jobs run against.
  • The revisions step's shell was executed with a stub helper: it emits
    index=/runtime= to $GITHUB_OUTPUT, calls the helper with the two refs,
    and fails with ::error::not a commit on a non-commit.
  • tests/e2e/232_workflow_syntax.sh passes (24 workflows load);
    .github/tools/check_workflow_assertions.py reports 0 problems;
    tools/lint-ci-assertions.sh reports the same two pre-existing warnings as
    before this change; git diff --check clean.

.github/** classifies as code=true, so this PR's own CI runs the full
matrix — including the four-host openkal build and the three run jobs the
pin is for.

Test plan

  • Documentation-only: not applicable, no documentation changed
  • mcpp test (unit/integration): not applicable, no C++ changed
  • The openkal jobs in this PR's CI are the E2E coverage of the change

The four build jobs of openkal-cross.yml each cloned `main` of the index and
of the runtime of their own accord, at four different moments on four runners
that become available at four different times, and the run jobs then asserted
that all four had built the same sources. On 2026-10-13 that assertion failed
for a reason the change under test had nothing to do with: run 38399400601
started at 12:43 UTC, its build jobs at 12:52:08 through 13:01:33, and
mcpp-index@main took four commits inside that window (21b9a77a 12:56:12,
d3a328c8 13:04:42, cfb808bc 13:10:06, 0340de61 13:17:58), so the four clones
straddled pushes and the run jobs reported `index sources differ`.

Resolve both refs once, in a new `revisions` job, and have every host
materialise the commit it names. OPENKAL_BRANCH keeps its meaning: an
override still verifies exactly what it named, now as one commit rather than
as whatever the branch had become when each runner woke up. The run jobs keep
their cross-host comparison; it is what proves a host used the pin rather
than re-resolving for itself.

git_clone_retry.sh grows the two primitives that needs: `--rev <ref> <url>`,
which prints the commit a ref names without downloading the tree, and
`--commit <sha> <url> <dir>`, which materialises exactly that commit, both
under the retry the helper already exists for. Writing a SHA into the
workflow instead would be the pin-that-keeps-a-check-green-by-keeping-it-
out-of-date that the file itself warns about.
@ZheFeng7110
ZheFeng7110 force-pushed the fix/ci-openkal-pinned-revisions branch from aff91b0 to 608d307 Compare October 13, 2026 13:40
@ZheFeng7110

Copy link
Copy Markdown
Member Author

CI analysis: the two red checks are flaky, and neither one is this diff

Run 38406939721 (this PR's head 608d3072) ended 60/62 green. Both failures are pre-existing flakes outside the two files this PR touches, and the openkal jobs the change exists for are all green — the four build jobs, the three run jobs and the new revisions job.

1. windows / bare Windows: no Visual Studio (windows x64), 17s — the mask's rename was refused

masking C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC
  rename failed: Access to the path '...\18\Enterprise\VC' is denied.
FAIL: VC tools still present after masking:
  C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Tools\MSVC
##[error]Process completed with exit code 1.

The step relies on "the Visual Studio root is held open on the runner and renaming it is denied, while VC one level down renames fine" (ci-windows.yml). That premise is host state, not image state — the same script on the same image:

time (UTC) runner image renaming ...\18\Enterprise\VC
09:57 windows-2025-vs2026, commit 20260925.250 ok
13:59 (this run) same denied
14:32 same ok

ci-windows.yml is not in this diff, and the same step on the same image passed 33 minutes later (run 38411372563). The mask's own postcondition is deliberate — an incomplete mask must not read as a green "bare Windows" row — so a transient denial becomes a red check.

2. macos-e2e / e2e suite 2/2 (xcode-27) — 845 kills mcpp before the phase its assertion names

E2E Summary: 144 passed, 1 failed, 170 skipped, Failed: 845_play_game_restores_the_terminal.sh, from the script's own play.py:71:

AssertionError: G1: no status row carries the score
assert re.search(r"Building .* · snake \d+", plain), ...

The captured g3.log stops in the Programs phase:

Running ⠀⠐⠒⠂… 0/1 · 0:01 · build.mcpp app compiling 0:01 · snake 0
build.mcpp app               ran 1.24s
Running ⠀⠀⠒⠒… 1/1 · 0:01 · snake 0

play.py sends the arrows and the Ctrl-C at a fixed t0 + 1.5s, while the build reaches Phase::Building only after the Programs phase (build.mcpp compile + run, plus toolchain resolution), which took ~1.24s here. The rows do carry the score in the Programs frames; phase_status() prints Running for Phase::Programs and Building only for Phase::Building (src/build/progress.cppm:1074), so the only missing token is the phase word. A 1.5s deadline against ~1.24s of work is decided by host jitter:

  • the macos-15 twin of this job passed in this same run;
  • on main (38378041638) the macos-15 twin failed with the identical assertion while xcode-27 passed;
  • 2 of the last 11 ci runs failed e2e suite 2/2, the two hosts alternating.

Next

Both are fixed in a follow-up PR: e2e 845 waits for the frame its assertion names instead of for a wall-clock delay, and the Visual Studio mask — currently three copies of the same block, in ci-windows.yml, ci-fresh-install.yml and measure-windows-tool-crt.yml — gains retries with a one-level-deeper fallback, with the postcondition kept.

@ZheFeng7110

Copy link
Copy Markdown
Member Author

Both are fixed in #806: e2e 845 now waits for the status row its assertion names instead of for a wall-clock delay, and the Visual Studio mask (three copies, now one action) retries a refused rename and falls back to masking VC\Tools, postcondition kept.

This branch has not been deployed

No deployments
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