feat(wanda): Add dependency resolution for wanda specs#347
feat(wanda): Add dependency resolution for wanda specs#347andrew-anyscale merged 1 commit intomainfrom
Conversation
|
Summary of ChangesHello @andrew-anyscale, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a core dependency resolution mechanism for Wanda specifications. The primary goal is to enable a more intuitive, Bazel-like user experience where Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces dependency resolution for wanda specs, a significant feature that adds core dependency graph functionality. The implementation includes a dependency graph with topological sorting (Kahn's algorithm), cycle detection, and support for transitive dependencies. The changes are well-structured and accompanied by a comprehensive set of tests. My review focuses on improving robustness by handling a potential error, increasing performance in the topological sort algorithm, and enhancing maintainability in the spec variable expansion logic.
6f660b1 to
c9aea31
Compare
wanda/testdata/dep-middle.wanda.yaml
Outdated
| deps: [dep-base.wanda.yaml] | ||
| froms: ["@dep-base"] |
There was a problem hiding this comment.
this is double-declaring the dependency, both in froms and in deps. can we have a design (yet backwards-compatible), that can just reference another image based on the name?
think about bazel, when referencing another rule as deps, it does not need to specify which file to find it.
kind of out of scope, but we might also think about the possibility to:
- declare multiple images in one wanda definition file
- inline dockerfile contents, or inversely, inline wanda rules definition in the dockerfile.
wanda/spec.go
Outdated
| result.Dockerfile = expandVar(s.Dockerfile, lookup) | ||
| result.BuildArgs = stringsExpanVar(s.BuildArgs, lookup) | ||
| result.BuildHintArgs = stringsExpanVar(s.BuildHintArgs, lookup) | ||
| result.DisableCaching = s.DisableCaching |
There was a problem hiding this comment.
hmm... was this missed before? is this a bug?
and stringsExpanVar probably should be stringsExpandVar
could you put these two small fixes in another PR?
and maybe add a unit test that can cover the bug..
c9aea31 to
c1346cb
Compare
988af31 to
388c9c1
Compare
388c9c1 to
b822440
Compare
|
|
||
| // checkUnexpandedVars checks if a spec has any unexpanded environment variables | ||
| // and returns a helpful error message if so. | ||
| func checkUnexpandedVars(spec *Spec, specPath string) error { |
There was a problem hiding this comment.
I cleaned up quite a bit of this logic in the subsequent PR #368. With that PR we have defined params, making it easier to declare what should be possible in froms and name
| } | ||
|
|
||
| // findUnexpandedVars finds $VAR patterns in a string that were not expanded. | ||
| func findUnexpandedVars(s string) []string { |
There was a problem hiding this comment.
4c062ac to
d437c29
Compare
|
Apologies for the bloodbath of updates here 😭 Ran into some issues of namespace conflict for Ray names in |
aslonnie
left a comment
There was a problem hiding this comment.
could you update the PR's description / title? this PR seems to be just a rename now.
aslonnie
left a comment
There was a problem hiding this comment.
oh, sorry, there are two large / hidden files.
wanda/deps.go
Outdated
| }() | ||
|
|
||
| // 3) Walk directory (single goroutine) and feed candidate files | ||
| walkErr := filepath.WalkDir(searchRoot, func(path string, d fs.DirEntry, err error) error { |
There was a problem hiding this comment.
instead of scanning all dirs, we should have have a config input and scan just given directories (and their sub dirs). for ray repo, this is:
docker/
ci/docker/
.buildkite/release-automation/
There was a problem hiding this comment.
Going with a project-level file .wandaspecs
wanda/deps.go
Outdated
| // Skip common non-source directories | ||
| if name == ".git" || name == "node_modules" || name == "vendor" { |
There was a problem hiding this comment.
a lot of the scanning time is likely spent on scanning bazel generated files. :)
|
maybe split the renaming as a leading PR, and the toposort algorithm things into another? |
d437c29 to
835bb4c
Compare
9bd8415 to
2f65672
Compare
7bd90b7 to
8193927
Compare
Add buildDepGraph() to parse wanda specs and resolve dependencies by scanning the repo for *.wanda.yaml files. The dependency graph is built in deterministic topological ordering. Key features: - Automatic discovery by scanning repo from git root - Parallel spec parsing for performance - Cycle detection with helpful error messages - Variable expansion with unexpanded var detection Topic: wanda-deps Relative: wanda-refactor-hello Signed-off-by: andrew <andrew@anyscale.com>
8193927 to
eb8860b
Compare
wanda/wanda/main.go
Outdated
| readOnly := flag.Bool("read_only", false, "read-only cache repository") | ||
| epoch := flag.String("epoch", "", "epoch for the image tag") | ||
| rebuild := flag.Bool("rebuild", false, "always rebuild the image") | ||
| wandaSpecsFile := flag.String("wanda_specs_file", ".wandaspecs", "file listing spec directories (relative to repo root)") |
There was a problem hiding this comment.
nit: could you keep the line limit to 80 char?
also, wanda does not have a "repo" concept. the root is workDir.
for this particular file, maybe:
- use a regular file path, rather than a custom relative. otherwise, bash shell completion feels weird.
- leave the default value to "", and in description says that if this flag's value is empty, we look for
.wandaspecsunderwork_dir.
There was a problem hiding this comment.
Thinking for the future of using wanda locally, the one complication with workDir is that it means you'd need to always run all wanda commands from the project root. E.g.
# works
wanda ci/docker/base.build.wanda.yaml
cd ci/docker
# does not work
wanda base.build.wanda.yamlNot for the scope of this PR, but it would be interesting to think on whether we'd want to enable this type of UX at some point
wanda/deps_test.go
Outdated
| // a | ||
| // │ | ||
| // ▼ | ||
| // b | ||
| // │ | ||
| // ▼ | ||
| // c |
There was a problem hiding this comment.
wow! lol..
can this be just a -> b -> c?
I guess this is claude code showing off its ascii art skills..
eb8860b to
7f955fd
Compare
Code Review 👍 Approved with suggestions 5 resolved / 7 findingsWell-structured dependency resolution implementation with comprehensive test coverage. Two previous minor findings remain unresolved but are reasonable design tradeoffs. Suggestions 💡 2 suggestionsBug: discoverSpecs silently skips parse errors in the indexWhen While this behavior makes sense for tolerance during discovery (not all if err != nil {
log.Printf("debug: skipping %s: %v", path, err)
outCh <- discovered{skipped: true}
continue
}At minimum, document this intentional behavior in the function comment. Edge Case: findUnexpandedVars doesn't handle ${VAR} brace syntaxThe Consider adding support for brace syntax: if s[i] == '$' && i+1 < len(s) {
if s[i+1] == '{' {
// Handle ${VAR} syntax
j := i + 2
for j < len(s) && s[j] != '}' { j++ }
if j < len(s) {
vars = append(vars, s[i:j+1])
}
i = j
continue
}
// ... existing $VAR handling
}Impact: Specs using Resolved ✅ 5 resolvedEdge Case: localDeps doesn't strip image tags from dependency names
Edge Case: findRepoRoot may fail with .git file (worktrees/submodules)
Code Quality: validateDeps() function is defined but never called
Edge Case: findRepoRoot may loop indefinitely on empty path edge case
Bug: Race condition: walkErr accessed before WalkDir completes
What Works WellClean implementation of topological sorting with cycle detection. Good separation of concerns between discovery, loading, and sorting phases. Comprehensive test suite covering linear chains, diamond dependencies, cycles, and transitive discovery scenarios. OptionsAuto-apply is off Gitar will not commit updates to this branch. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | This comment will update automatically (Docs) |
Add buildDepGraph() to parse wanda specs and resolve dependencies by scanning the repo's
spec_dirsfor *.wanda.yaml files. The dependency graph is built in deterministic topological ordering.Key features:
.wandaspecsat git rootDesign Decisions
Name collisions: Error on collision during index building. If two specs expand to the same name, this indicates a real problem that should be fixed. The error message will list both file paths.
Non-git repos: Use the spec file's directory as the search root. This is a safe default that still enables discovery for local testing without requiring a git repository.
Topic: wanda-deps