[draft] DO NOT MERGE: rayapp test prototype#372
Conversation
Add a pre-flight check to verify anyscale is installed before running commands, returning a clear error if not. Include comprehensive tests using mock scripts to test success, failure, and not-installed scenarios. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Summary of ChangesHello @elliot-barn, 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 integrates the Anyscale CLI into the 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
|
Signed-off-by: elliot-barn <elliot.barnwell@anyscale.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a wrapper for the anyscale CLI, including a pre-flight check for its installation and comprehensive tests. The implementation is solid, but I have a few suggestions to improve code quality and robustness. My review includes recommendations for better error handling in anyscale_cli.go, improved path construction and test logic in anyscale_cli_test.go, and fixing missing newlines at the end of files.
Additionally, there are two important points that are outside the changed lines but are highly relevant:
- The application will panic if run without any command-line arguments. You should add a check for
len(args)inrayapp/main.gobefore accessingargs[0]. - The new
anyscale-clicommand is missing from the usage message printed by thehelpcommand. Please update it to reflect the new functionality.
rayapp/anyscale_cli.go
Outdated
|
|
||
| err := cmd.Run() | ||
| if err != nil { | ||
| return "", fmt.Errorf("anyscale error: %v\nstderr: %s", err, stderr.String()) |
There was a problem hiding this comment.
The error formatting could be improved for better diagnostics and to follow modern Go practices. Using %w to wrap the error allows for inspection of the error chain with errors.Is or errors.As. Also, including a newline \n in the error message can make logs harder to parse. It's generally better to have single-line error messages.
| return "", fmt.Errorf("anyscale error: %v\nstderr: %s", err, stderr.String()) | |
| return "", fmt.Errorf("anyscale error: %w, stderr: %s", err, stderr.String()) |
rayapp/anyscale_cli.go
Outdated
| } | ||
|
|
||
| return stdout.String(), nil | ||
| } No newline at end of file |
| tmp := t.TempDir() | ||
|
|
||
| if script != "" { | ||
| mockScript := tmp + "/anyscale" |
There was a problem hiding this comment.
For constructing file paths, it's better to use filepath.Join instead of manual string concatenation with /. This makes the code more portable and works correctly on different operating systems, like Windows. You'll need to add import "path/filepath" to the file.
| mockScript := tmp + "/anyscale" | |
| mockScript := filepath.Join(tmp, "anyscale") |
| if errors.Is(tt.wantErr, errAnyscaleNotInstalled) { | ||
| if !errors.Is(err, errAnyscaleNotInstalled) { | ||
| t.Errorf("expected errAnyscaleNotInstalled, got: %v", err) | ||
| } | ||
| } else if !strings.Contains(err.Error(), tt.wantErr.Error()) { | ||
| t.Errorf("error %q should contain %q", err.Error(), tt.wantErr.Error()) | ||
| } |
There was a problem hiding this comment.
The error checking logic is a bit complex and can be simplified for better readability and maintainability. Specifically, errors.Is(tt.wantErr, errAnyscaleNotInstalled) is an unconventional way to check if tt.wantErr is of a certain type. A direct comparison tt.wantErr == errAnyscaleNotInstalled is more idiomatic here.
| if errors.Is(tt.wantErr, errAnyscaleNotInstalled) { | |
| if !errors.Is(err, errAnyscaleNotInstalled) { | |
| t.Errorf("expected errAnyscaleNotInstalled, got: %v", err) | |
| } | |
| } else if !strings.Contains(err.Error(), tt.wantErr.Error()) { | |
| t.Errorf("error %q should contain %q", err.Error(), tt.wantErr.Error()) | |
| } | |
| if tt.wantErr == errAnyscaleNotInstalled { | |
| if !errors.Is(err, errAnyscaleNotInstalled) { | |
| t.Errorf("expected errAnyscaleNotInstalled, got: %v", err) | |
| } | |
| } else if !strings.Contains(err.Error(), tt.wantErr.Error()) { | |
| t.Errorf("error %q should contain %q", err.Error(), tt.wantErr.Error()) | |
| } |
| t.Error("should return true when in PATH") | ||
| } | ||
| }) | ||
| } |
|
Does this need reviewing? 👁️ 👁️ |
Signed-off-by: elliot-barn <elliot.barnwell@anyscale.com>
Signed-off-by: elliot-barn <elliot.barnwell@anyscale.com>
|
I've addressed the code review findings: Fixed Issues:
Verification:
|
rayapp/test.go
Outdated
| for !strings.Contains(state, StateRunning.String()) { | ||
| state, err = anyscaleCLI.getWorkspaceStatus(wtc.workspaceName) | ||
| if err != nil { | ||
| return fmt.Errorf("get workspace status failed: %w, retrying...", err) |
There was a problem hiding this comment.
Details
If copyTemplateToWorkspace or runCmdInWorkspace fail, the function returns immediately without calling terminateWorkspace. This leaves the workspace running, consuming resources and potentially costing money.
Impact: Failed tests will leave orphaned workspaces that must be manually cleaned up.
Suggested fix: Use defer for cleanup:
// After successful workspace creation
defer func() {
if err := anyscaleCLI.terminateWorkspace(wtc.workspaceName); err != nil {
fmt.Printf("warning: failed to terminate workspace: %v\n", err)
}
}()Was this helpful? React with 👍 / 👎
Signed-off-by: elliot-barn <elliot.barnwell@anyscale.com>
Signed-off-by: elliot-barn <elliot.barnwell@anyscale.com>
|
I've addressed the critical bugs found in the code review: Fixed:
Verification:
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
no sir this is for prototyping. Will clean it up and then break it down into smaller PRs |
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add waitForWorkspaceState function to AnyscaleCLI for waiting on workspace state - Replace manual polling loop with waitForWorkspaceState call - Fix bug: use wtc.workspaceName instead of tr.workspaceName in terminate call Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove commented code and cleanup script - Execute rayapp with arguments instead of copying to root directory Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Parse the AWS config path from template.ComputeConfig["AWS"] and convert it to a named compute config (e.g., "configs/basic-single-node/aws.yaml" becomes "basic-single-node-aws"). This config name is then passed to the --compute-config flag when creating workspaces via the Anyscale CLI. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CreateComputeConfig now checks if a config already exists using GetComputeConfig before attempting to create it. Also adds ListComputeConfigs method and creates compute config in test runner before workspace creation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of pushing the template directory directly, now zip it first and push the zip file. This adds zipDirectory utility function and pushFileToWorkspace CLI method. Template directory paths are now resolved relative to the build file. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create a temp directory with prefix 'template_zip', zip the template into it, push the directory to the workspace, then clean up the temp directory on completion. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CreateComputeConfig now detects old-style compute configs (with head_node_type and worker_node_types keys) and automatically converts them to the new format (head_node and auto_select_worker_config) before creating the config. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review 👍 Approved with suggestions 10 resolved / 13 findingsPrototype PR with 3 pre-existing issues still present: double close of zip.Writer, workspace leaked on test failure, and help text documenting non-existent flags. Author acknowledges this is for prototyping and will be cleaned up.
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Adding anyscale CLI wrapper and test workflow to test templates in anyscale
Add a pre-flight check to verify anyscale is installed before running commands, returning a clear error if not. Include comprehensive tests using mock scripts to test success, failure, and not-installed scenarios.