Repository navigation
ci(workflows): build Talos only when its sources changed - #4021
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review. 📝 WalkthroughWalkthroughThe workflow now classifies Talos-related changes from rename-blind paths. Same-repository Talos builds run only when required, fork builds remain unconditional, and finalization selects the correct bootbox overlay reference. ChangesTalos build gating
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant PlanJob
participant TalosJob
participant FinalizeJob
participant Overlay
PlanJob->>TalosJob: provide talos build requirement
TalosJob->>FinalizeJob: report success or skipped status
FinalizeJob->>Overlay: provide package exclusions
TalosJob->>Overlay: preserve generated bootbox on success
Overlay->>FinalizeJob: select generated or base bootbox reference
Suggested reviewers: Merge Risk: ⚪ Minimal · up to The workflow gates unaffected same-repository Talos builds while preserving fork behavior and the correct bootbox reference. No merge-blocking correctness or availability risk is currently evidenced. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 4 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
c68f37c to
708b465
Compare
Aleksei Sviridkin (lexfrei)
left a comment
There was a problem hiding this comment.
NOT LGTM. The gate leans on a property of the plan job that the plan job does not promise and no test pins, and the branch sits on a base commit its base branch no longer contains.
Business context: skip the Talos build on same-repo PRs that did not touch its sources, since nothing on that path consumes either half of its output, and keep it unconditional for forks because the fork publish job needs at least one OCI archive.
Blockers
- The trailing space in
contains(needs.plan.outputs.touched, 'packages/core/talos ')is load-bearing and pinned by nothing.
The plan job builds that value at .github/workflows/pull-requests.yaml:190 with sed ... | sort -u | tr '\n' ' ', so today every element carries a trailing space, the last one included, and the match works wherever packages/core/talos sorts. That space is a side effect of tr, not a contract. The producer's own comment on line 189 describes the value as "Whitespace-separated, no trailing slash", and the only consumer that existed before this change, hack/overlay-main-images.sh:50, takes it as "whitespace-separated package dirs" and word-splits, which cannot tell a trailing space from its absence. Switching that pipeline to paste -sd' ', or appending a sed 's/ *$//' tidy-up, keeps both of those contracts and quietly changes this gate: contains stops matching whenever packages/core/talos sorts last, and the build is skipped on precisely the PRs the gate exists to catch.
hack/build-talos-gating_test.bats pins the consumer side only. Its own comment states the producer's behaviour ("The touched list is space-joined by the plan job, so the trailing space is what keeps this from matching a future packages/core/talos-something") without checking it, so the coupling is asserted in a place that cannot fail. The failure is silent in the direction that costs: no build, nothing red, and a broken packages/core/talos reaches main and first shows up on the release path, where nightly.yaml:286 and e2e-tag.yaml:181 still run make prepare-env. A case in the same file that runs the plan pipeline over a fixture and asserts the last element keeps its space would close it, or the producer can emit the delimiter deliberately instead of inheriting it.
- The branch is built on
c68f37c70, whichfeat/e2e-container-lane-v2no longer contains after being force-pushed to708b4652e.
mergeable is CONFLICTING against its own base, and the API reports 71 changed files and +3989/-4276 for what is a two-file change. Both numbers are artifacts of the stale base: measured over c68f37c70..0ac677bd6 the contribution is 2 files, +81/-1. Rebase onto 708b4652e before this can be read or merged as a stacked change.
Non-blocking
The comment's opening line, "Runs when this PR could have changed what it builds", is wider than the condition below it. packages/core/talos/Makefile:6 includes hack/common-envs.mk, which supplies REGISTRY, IMAGE_TAG and the image-tags/cache-args helpers the recipe calls, and the job hands hack/buildkitd.toml to buildx. An edit to either changes what the build produces or how it runs, and neither puts packages/core/talos into touched, so the build is skipped. The practical cost is small because nothing on this path consumes the output, but the sentence is permanent and checkable, so it is worth narrowing to what the gate actually keys on.
One coordination point for the rebase. This branch carries 24 references to the full-e2e label in pull-requests.yaml, and they are not all prose: line 51 compares github.event.label.name != 'full-e2e' inside the concurrency key. If the in-flight rename of that label lands first, whoever merges second reinstates a name that no longer exists, and a string comparison against a label does not fail a test when the label stops existing. Worth settling the merge order rather than finding out afterwards.
708b465 to
00c6eb1
Compare
Classify the rename-blind changed-path list against direct Talos sources and shared build inputs. This lets same-repository pull requests skip the heavy build while removals, renames, and build configuration changes still select it. Fork builds remain unconditional. Preserve the matchbox digest produced by a successful Talos build when finalize overlays base-branch image references. When the job is skipped, bootbox continues to receive the current base reference. Assisted-By: LLM Signed-off-by: Myasnikov Daniil <[email protected]>
0ac677b to
975ea6a
Compare
Aleksei Sviridkin (lexfrei)
left a comment
There was a problem hiding this comment.
LGTM. Both blockers from my last pass are closed, and the paths the gate keys on match what the build actually reads.
The trailing-space coupling is gone because the gate no longer reads touched at all. plan hands hack/build-talos-needed.sh the rename-blind /tmp/changed_norenames.txt, the script matches whole lines, and hack/build-talos-gating_test.bats goes red if build-talos's if ever mentions needs.plan.outputs.touched again. Base is main now and the PR is mergeable, so the stale-base blocker went with it. hack/common-envs.mk and hack/buildkitd.toml, the two shared inputs I raised as non-blocking last time, are both in the pattern.
I enumerated the inputs from the recipe instead of from the pattern, and they line up. make -C packages/core/talos image reads images/talos/profiles/{installer,kernel,initramfs}.yaml and takes TALOS_VERSION out of installer.yaml. Matchbox builds from images/matchbox/Dockerfile with the repo root as context, and that Dockerfile copies only _out/assets/* plus packages/core/talos/images/matchbox/{groups,profiles}. Registry and tag macros come from hack/common-envs.mk, the buildx config from hack/buildkitd.toml, the job env from pull-requests.yaml. I found no input outside the five entries.
Nothing on this path reads either output, so the skip is safe downstream. hack/e2e-compose.yaml:28 boots ghcr.io/siderolabs/talos:v1.13.5 by digest rather than the built image, and no chart in the tree references ${REGISTRY}/talos. The only cross-job handoff is pr-patch-fragment-talos; with it absent, finalize's apply loop skips the unmatched glob and the overlay hands bootbox the base-branch matchbox ref. No stale artifact gets substituted anywhere, because there is no consumer.
The overlay half fixes a real bug rather than only accommodating the skip. Before this, a successful Talos build stamped packages/extra/bootbox/images/matchbox.tag and the overlay then put the base-branch ref back over it, since bootbox was in neither BUILD_MATRIX nor TOUCHED. Adding it to BUILT_JSON on success keeps the fresh digest. Skipping the whole package costs nothing here: bootbox's values.yaml carries no image reference, so images/matchbox.tag is the only file covered.
I ran the bats file and mutated three things to check the tests can actually fail: dropped hack/common-envs.mk from the pattern, removed skipped from finalize's Talos condition, and made the overlay treat bootbox as rebuilt regardless of TALOS_RESULT. Each one turned a different test red.
What I could not observe from this PR's own runs. It never exercises its own skip path, because it edits .github/workflows/pull-requests.yaml, which the classifier counts as a Talos input, so Build Talos ran and succeeded on run 34506559966. Any PR touching the workflow behaves the same, so the first run with talos == 'false' lands after merge. Job-result propagation is CI-only too: the test pins the text of finalize's condition, not what GitHub does when a needed job skips. The red E2E on this head is chainsaw/redis-2-backup-roundtrip and nothing else, which is #4218; it cannot be this change, since Talos built on that run and e2e got the same artifacts it would have without the gate.
Non-blocking
The description's reason for keeping forks unconditional does not hold. It says e2e-fork.yaml's archive check works "only because this job always ran", but finalize uploads pr-oci-installer for every fork PR (pull-requests.yaml:736-742) and finalize runs on every non-docs PR, so the -ge 1 check at e2e-fork.yaml:480 is satisfied without Talos. The comment you added to the job says exactly that and contradicts the description. Keeping forks unconditional is still the right call as a scope boundary. It is the stated reason that is wrong, and the description is what a reader reaches for first.
Also stale: the description opens with "Stacked on #4020, not independently mergeable". #4020 merged on 7 September, base is main, and GitHub reports the PR mergeable.
hack/build-talos-needed.sh is not among the paths it matches, so a PR editing only the classifier skips the build it governs. It cannot ship a wrong image, since the classifier is not a build input, but a change to the gate gets no run under the gate. .dockerignore is in the pattern and no such file exists in the tree, which is harmless and will do the right thing if one is added.
Stacked on #4020, not independently mergeable.
Nothing on the same-repo PR path consumes either half of what
build-talosproduces.image-talospushes${REGISTRY}/talos:pr-N-sha, which no chart in the tree references and which is not even version-tagged here (PUBLISH_VERSIONEDandPUBLISH_FLOATINGare both 0).image-matchboxstampspackages/extra/bootbox/images/matchbox.tag, and that one line is the whole content ofpr-patch-fragment-talos- checked against the artifact from a real run - but bootbox is opt-in and the E2E platform Package does not enable it, so no run pulls the image. Unstamped tag leaves installer artifact pointing at released matchbox, which is a valid ref nothing on this path resolves.So the job ran a privileged siderolabs imager build on every PR for two artifacts with no reader. Now it runs when the PR touched
packages/core/talos, andfinalizeaccepts a skipped result as well as a successful one. Without that second half skipping it would block finalize, and therefore e2e, on nearly every PR.Forks keep the unconditional build, and the reason is not about talos.
e2e-fork.yamlpublish job requires at least one OCI archive to exist, an invariant that holds today only because this job always ran, so a fork PR touching nothing underpackages/would arrive with an empty export and fail a legitimate run. Teaching that guard whatplanexpected to build is work in the fork allowlist path and belongs in its own change.Saving is about 1.5-2 min of critical path. Main point is removing a privileged image build that nobody reads from every pull request.
Summary by CodeRabbit
CI Improvements
Documentation
Tests