ci: activate dependency-aware package builds and tests - #2467
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
edfbf97 to
66445a4
Compare
a06ad8b to
adf15bd
Compare
adf15bd to
ba702ca
Compare
ba702ca to
85f173e
Compare
85f173e to
9cf09a9
Compare
|
mdboom
left a comment
There was a problem hiding this comment.
Sorry this review will be long, and will negate some of the earlier decisions in the stack. I should have evaluated the whole stack at once to see where this is going.
I think this is fundamentally a maintenance nightmare and way more verbose than it needs to be. Rather than passing 9 new parameters between jobs, there should be a single, structured JSON object that is passed around. I am thinking something like (using YAML because it's easier to type, but it would be JSON).
modules:
test_helpers:
needs_build: false
needs_test: false
pathfinder:
needs_build: false
needs_test: false
build_depends: []
test_depends: ["test_helpers"]
bindings:
needs_build: false
needs_test: false
build_depends: ["pathfinder"]
test_depends: ["test_helpers"]
core:
needs_build: false
needs_test: false
build_depends: ["bindings"]
test_depends: ["test_helpers"]
baseline_run_id: 123456789
baseline_sha: c0ffee
This makes verbose things that are sensitive to modules coming and going like:
${{ needs.detect-changes.outputs.build_pathfinder == 'true' ||
needs.detect-changes.outputs.build_bindings == 'true' ||
needs.detect-changes.outputs.build_core == 'true' ||
needs.detect-changes.outputs.build_python == 'true' }}
into:
Object.values(data.modules).some(m => m.needs_test)
Rather than this:
test_bindings: >-
${{ steps.baseline.outputs.available != 'true' ||
steps.filter.outputs.changes == '' ||
steps.filter.outputs.force_all == 'true' ||
steps.filter.outputs.all_tests == 'true' ||
steps.filter.outputs.pathfinder_source == 'true' ||
steps.filter.outputs.bindings_source == 'true' ||
steps.filter.outputs.bindings_tests == 'true' ||
steps.filter.outputs.test_helpers == 'true' }}
You can do:
(name, modules, seen = new Set()) => {
if (seen.has(name)) return false;
seen.add(name);
const m = modules[name];
return m.needs_test || (m.depends || []).some(dep => moduleNeedsTest(dep, modules, seen));
};
rather than hardcoding the dependencies into a bunch of large boolean expressions.
We can pre-compute values for downstream consumers so this kind of logic is only written in one place.
data["needs_build"] = Object.values(data.modules).some(m => m.needs_build)
# or Python
data["needs_build"] = any(mod["needs_build"] for mod in data["modules"])
This object would get passed between jobs as "workplan" (or some better name).
Given my other comment that dorny/paths-filter seems like the wrong tool for the job, I would propose:
A standalone Python script that does the analysis of changes and builds this workplan object, including as many pre-computed dependendent information as we can to make downstream consumers of this information concise and prevent long complicated expressions being repeated everywhere.
This script has the side benefit of forming the basis of a future local helper to test only what is needed (which all of this GHA work doesn't move us toward).
(I confirmed that outputs can have a size maximum of 1MB which should be more than enough for this.)
|
|
||
| has_match() { | ||
| grep -qE "$1" <<< "$changed" && echo true || echo false | ||
| - name: Classify changed paths |
There was a problem hiding this comment.
The hardcoded path lists here is going to be a maintenance nightmare.
Each subsection follows a pretty similar pattern, though. If there were a better way of specifying things to reduce duplication, I think that would be fine. (For example, if we could globally exclude all AGENTS.md).
As it stands, if this is the best we can do with dorny/paths-filter, I think we should reach for a different tool or write our own in Python. Upside of that, too, is we could build a "test everything we need to" local script on top of it, whereas this is stuck in the GHA silo.
There was a problem hiding this comment.
Originally my agent had implemented a Python script to encapsulate the logic of what paths / files impact which builds / tests and I found that script even more difficult to understand and maintain than maintaining a list of paths like this that an agent could easily update (and we should include in the AGENTS.md in hindsight). Let me see what I can do to simplify things here, because I agree this is going to be an ongoing annoyance.
For what it's worth, I think this overall work is going to be a stopgap as opposed to the end solution, where moving to something like moon (https://moonrepo.dev/moon) or bazel is probably a better longer term solution that makes things more "target" oriented as opposed to path / file oriented.
| # cuda_python/README.md is a symlink to this packaging input. | ||
| - 'README.md' |
There was a problem hiding this comment.
Not sure I understand the comment.
There was a problem hiding this comment.
cuda_python/README.md symlinks the root README.md and it gets included in the Python package that we produce, so changes to the top level README need to trigger a rebuild of the metapackage.
Important
Stack completion: PR 4 of 4. #2464, #2465, and #2466 have merged. This is the final PR in the stack.
Merge order: #2464 (merged) -> #2465 (merged) -> #2466 (merged) -> #2467 (this PR). The branch lives in the
kkraus14fork and targets upstreammain.What
dorny/paths-filterv4.0.3, pinned to its full commit SHA.mainCI run for the PR's exact merge-base commit and reuse its complete wheel set.**/pixi.tomland**/pixi.lock.Expected package behavior
cuda_coresource change: build/test cuda-core and retest the downstream cuda-python metapackage; skip cuda-bindings and cuda-pathfinder builds/tests.cuda_bindingssource change: build/test cuda-bindings, cuda-core, and cuda-python; skip cuda-pathfinder.cuda_pathfindersource change: build/test the full downstream closure.The cuda-python wheel is reused for a core-only change rather than rebuilt because development cuda-python wheels exactly pin cuda-bindings; rebuilding it would force an otherwise unnecessary bindings rebuild.
Validation
mainafter ci: add selective wheel test plumbing #2466 merged; the net diff is only.github/workflows/ci.yml.git diff --no-renames, preserving deletion and cross-package rename handling.Implements the remaining dependency-aware build/test selection requested in #299.