Scion/harness journey p1#447
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to re-import and update harness configurations and templates from their remote source URLs. It adds a new harness-config update CLI command, a POST /api/v1/harness-configs/{id}/reimport API endpoint, database schema updates to store the source_url, and a "Refresh from Source" button in the frontend UI. The review feedback highlights several safety and robustness improvements, including using cmd.Context() to respect CLI cancellation signals, avoiding the r.ContentLength anti-pattern when parsing HTTP request bodies, and adding nil checks for database and API client responses to prevent potential nil pointer dereferences.
| var req ReimportHarnessConfigRequest | ||
| if r.ContentLength > 0 { | ||
| if err := readJSON(r, &req); err != nil { | ||
| BadRequest(w, "Invalid request body: "+err.Error()) | ||
| return | ||
| } | ||
| } |
There was a problem hiding this comment.
Checking r.ContentLength > 0 to decide whether to parse the request body is an anti-pattern. In HTTP/1.1 with chunked transfer encoding or in HTTP/2, r.ContentLength can be -1 (indicating unknown length), which would cause the request body to be silently ignored. Instead, check if r.Body is not nil and not http.NoBody before decoding.
| var req ReimportHarnessConfigRequest | |
| if r.ContentLength > 0 { | |
| if err := readJSON(r, &req); err != nil { | |
| BadRequest(w, "Invalid request body: "+err.Error()) | |
| return | |
| } | |
| } | |
| var req ReimportHarnessConfigRequest | |
| if r.Body != nil && r.Body != http.NoBody { | |
| if err := readJSON(r, &req); err != nil { | |
| BadRequest(w, "Invalid request body: "+err.Error()) | |
| return | |
| } | |
| } |
| hc, err := s.store.GetHarnessConfig(ctx, id) | ||
| if err != nil { | ||
| writeErrorFromErr(w, err, "") | ||
| return | ||
| } |
There was a problem hiding this comment.
Add a nil check for hc to prevent a potential nil pointer dereference if GetHarnessConfig returns nil, nil.
hc, err := s.store.GetHarnessConfig(ctx, id)
if err != nil {
writeErrorFromErr(w, err, "")
return
}
if hc == nil {
writeError(w, http.StatusNotFound, "not_found", "Harness config not found", nil)
return
}| ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) | ||
| defer cancel() |
There was a problem hiding this comment.
Use cmd.Context() instead of context.Background() to respect cancellation signals (such as Ctrl+C) handled by Cobra.
| ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) | |
| defer cancel() | |
| ctx, cancel := context.WithTimeout(cmd.Context(), 120*time.Second) | |
| defer cancel() |
| if err != nil { | ||
| return fmt.Errorf("failed to search Hub: %w", err) | ||
| } |
There was a problem hiding this comment.
| if err != nil { | ||
| return fmt.Errorf("failed to list harness-configs: %w", err) | ||
| } |
There was a problem hiding this comment.
Add a nil check for resp to prevent a potential nil pointer dereference if the API client returns a nil response without an error.
| if err != nil { | |
| return fmt.Errorf("failed to list harness-configs: %w", err) | |
| } | |
| if err != nil { | |
| return fmt.Errorf("failed to list harness-configs: %w", err) | |
| } | |
| if resp == nil { | |
| return fmt.Errorf("failed to list harness-configs: received empty response") | |
| } |
0414107 to
69f09cd
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to re-import and update harness configurations from their remote source URLs. It adds a new harness-config update CLI command, a backend API endpoint /api/v1/harness-configs/{id}/reimport, and a frontend "Refresh from Source" button. Additionally, the source_url field is integrated into the HarnessConfig and Template database schemas. The review feedback highlights two main improvements in cmd/harness_config_update.go: handling errors when resolving the project directory instead of silently ignoring them, and adding a nil check on the re-import result to prevent a potential nil pointer dereference.
| result, err := hubCtx.Client.HarnessConfigs().Reimport(ctx, match.ID, urlOverride) | ||
| if err != nil { | ||
| return fmt.Errorf("reimport failed: %w", err) | ||
| } |
There was a problem hiding this comment.
The Reimport call can potentially return a nil result even if err is nil. To prevent a potential nil pointer dereference panic when accessing result.Count or result.HarnessConfigs, add a nil check for result.
result, err := hubCtx.Client.HarnessConfigs().Reimport(ctx, match.ID, urlOverride)
if err != nil {
return fmt.Errorf("reimport failed: %w", err)
}
if result == nil {
return fmt.Errorf("reimport failed: received empty response from Hub")
}| var gp string | ||
| if projectPath != "" { | ||
| resolved, err := config.GetResolvedProjectDir(projectPath) | ||
| if err == nil { | ||
| gp = resolved | ||
| } | ||
| } else if projectDir, err := config.GetResolvedProjectDir(""); err == nil { | ||
| gp = projectDir | ||
| } |
There was a problem hiding this comment.
If projectPath is explicitly provided by the user, any error encountered while resolving the project directory should be handled and returned rather than silently ignored. Silently ignoring the error can lead to unexpected behavior or confusing error messages later in the execution.
| var gp string | |
| if projectPath != "" { | |
| resolved, err := config.GetResolvedProjectDir(projectPath) | |
| if err == nil { | |
| gp = resolved | |
| } | |
| } else if projectDir, err := config.GetResolvedProjectDir(""); err == nil { | |
| gp = projectDir | |
| } | |
| var gp string | |
| if projectPath != "" { | |
| resolved, err := config.GetResolvedProjectDir(projectPath) | |
| if err != nil { | |
| return fmt.Errorf("failed to resolve project directory %q: %w", projectPath, err) | |
| } | |
| gp = resolved | |
| } else if projectDir, err := config.GetResolvedProjectDir(""); err == nil { | |
| gp = projectDir | |
| } |
91c9d15 to
73daa89
Compare
Add optional source_url field to track the import origin URL for harness-configs and templates, enabling reimport/update flows.
… pipeline Add SourceURL field to store.HarnessConfig, store.Template, ResourceRecord, and the ent adapter CRUD operations. Update Bootstrap() to accept sourceURL parameter and persist it on create/update. Thread sourceURL from resourceDir through the import worker loop.
- POST /api/v1/harness-configs/{id}/reimport endpoint that re-imports
from stored source_url or an override URL
- CLI: scion harness-config update <name> [--url] [--all]
- Hub client: Reimport() method on HarnessConfigService
- Show command now displays source URL when present
- Display source URL as clickable link in metadata row
- Show Refresh from Source button when sourceUrl is present
- Button calls POST /api/v1/harness-configs/{id}/reimport
- Reload config details after successful reimport
The mock was missing the new Reimport method added to the HarnessConfigService interface, causing CI lint failures.
Remove WithDropColumn and WithDropIndex from Ent auto-migration. These flags cause SQLite to silently drop data during table recreation when schema changes occur between versions, which was the root cause of URL-imported harness configs disappearing after server restarts.
The importFromRemote signature gained a nameFilter []string parameter upstream. Pass nil for the reimport endpoint since it reimports all resources from the source URL.
Without a no_auth section, selecting "no authentication" for the antigravity harness causes the container to start with the full agy-wrapper.sh command (dbus + gnome-keyring + AGY) instead of dropping to a shell. This fails because AGY has no credentials. Add no_auth behavior matching claude/gemini/codex/opencode harnesses.
C-1: Add user-scope authorization check in reimport handler. Without this, any authenticated user could reimport another user's harness config. Also add default-deny for unknown scopes. M-1: Properly handle malformed JSON in reimport request body instead of silently discarding parse errors. H-1/H-2: Gate human-readable printf calls behind !isJSONOutput() in the CLI update command so --format json produces clean structured output.
- Use r.Body != nil && r.Body != http.NoBody instead of r.ContentLength for chunked/HTTP2 compatibility in reimport handler - Add nil check for harness config after GetHarnessConfig lookup - Use cmd.Context() instead of context.Background() in update command - Add nil checks for resp after Hub List calls in both update functions
- Add nil check for result after Reimport() call to prevent panic on (nil, nil) return - Return error when user-provided projectPath fails to resolve instead of silently ignoring it
73daa89 to
4fc7f1b
Compare
Fixes #<issue_number_goes_here>