feat: add session-config repo support (spec.configRepo)#606
feat: add session-config repo support (spec.configRepo)#606jeremyeder wants to merge 2 commits intoambient-code:mainfrom
Conversation
Sessions can now reference a Git repository containing Claude Code configuration (CLAUDE.md, .claude/ rules/skills/agents, .mcp.json) that is overlaid into the workspace at pod init time. The config repo is cloned once by hydrate.sh with retry logic and error reporting via /workspace/.config-repo-error. Workspace repo files take precedence over config repo files (cp -rn overlay). Template: https://github.com/ambient-code/session-config-reference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Store a workspace-level default session-config repo in ProjectSettings CRD so users don't have to paste a config repo URL every time they create a session. - Replace orphaned spec.repositories with spec.defaultConfigRepo in CRD - Add GET/PUT /api/projects/:project/project-settings backend endpoints - Remove dead code: EnrichProjectSettingsWithProviders and its tests - Add config repo fields to Create Workspace, Settings, and Create Session dialogs (pre-fills from workspace defaults, overridable) - Add React Query hooks and API client for project settings - Add 10 unit tests (Ginkgo) and 4 e2e tests (Cypress) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Code ReviewSummaryThis PR adds support for session-level configuration repositories ( Overall Assessment: High-quality implementation with strong adherence to project standards. Clean code removal, comprehensive test coverage, and proper security patterns throughout. Issues by Severity🚫 Blocker IssuesNone - No blocking issues found. 🔴 Critical Issues1. Missing User Token Client Validation in Backend Handler Location: The handlers use user-scoped clients correctly ( _, reqDyn := GetK8sClientsForRequest(c)
if reqDyn == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or missing token"})
c.Abort()
return
}Problem: Per CLAUDE.md line 530-535 and reqK8s, reqDyn := GetK8sClientsForRequest(c)
if reqK8s == nil { // Check reqK8s, not reqDyn
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or missing token"})
c.Abort()
return
}Why this matters: If Fix: Change to check 2. Type Assertion Without Safety Check Location: spec, _, _ := unstructured.NestedMap(obj.Object, "spec")
if spec == nil {
spec = map[string]interface{}{}
}Problem: Per CLAUDE.md line 452-456 and // ❌ FORBIDDEN: Direct type assertions without checking
obj.Object["spec"].(map[string]interface{})
// ✅ REQUIRED: Use unstructured.Nested* helpers
spec, found, err := unstructured.NestedMap(obj.Object, "spec")
if \!found || err \!= nil {
return fmt.Errorf("spec not found")
}Current code: You're ignoring the Fix: spec, found, err := unstructured.NestedMap(obj.Object, "spec")
if err \!= nil {
log.Printf("Failed to get spec: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read spec"})
return
}
if \!found {
spec = map[string]interface{}{}
}🟡 Major Issues3. Direct Type Assertion in Sessions Handler Location: spec := session["spec"].(map[string]interface{})Problem: This violates the type-safety rule (CLAUDE.md line 452-456). While this is existing code in the Create flow where Recommendation: spec, ok := session["spec"].(map[string]interface{})
if \!ok {
log.Printf("Invalid spec type in session")
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to set config repo"})
return
}4. Frontend: Missing Type Definition for Config Repo Location: The type definition is missing from the PR changes. The file was added but not shown in the diff. Verify: Ensure this file exists and has proper types: export type ProjectSettingsCR = {
defaultConfigRepo?: {
gitUrl: string;
branch?: string;
};
};
export type UpdateProjectSettingsRequest = {
defaultConfigRepo?: {
gitUrl: string;
branch?: string;
};
};🔵 Minor Issues5. Inconsistent Error Messages Location: c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read project settings"})vs line 78: c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read project settings"})Observation: The messages are identical for GET and UPDATE failures. Consider making them more specific:
6. Frontend: Potential Race Condition in useEffect Location: useEffect(() => {
if (projectSettings?.defaultConfigRepo?.gitUrl) {
const current = form.getValues();The code is cut off at line 100, but if this is setting form values in useEffect without proper dependencies, it could cause render loops. Recommendation: Ensure the dependency array includes useEffect(() => {
if (projectSettings?.defaultConfigRepo?.gitUrl) {
form.setValue('configRepoUrl', projectSettings.defaultConfigRepo.gitUrl);
if (projectSettings.defaultConfigRepo.branch) {
form.setValue('configRepoBranch', projectSettings.defaultConfigRepo.branch);
}
}
}, [projectSettings, form]); // Ensure proper dependencies7. Missing Context in Operator Log Messages Location: base = append(base, corev1.EnvVar{Name: "CONFIG_REPO_GIT_URL", Value: gitURL})Observation: No log message when config repo env vars are injected. For debugging, consider adding: if gitURL, ok := configRepo["gitUrl"].(string); ok && strings.TrimSpace(gitURL) \!= "" {
log.Printf("Injecting config repo for session %s/%s: %s", namespace, sessionName, gitURL)
base = append(base, corev1.EnvVar{Name: "CONFIG_REPO_GIT_URL", Value: gitURL})
}8. Dead Code Removal Not Reflected in Routes Location: Check You removed
Action: Confirm with: cd components/backend && grep -r "EnrichProjectSettingsWithProviders" .
grep -r "repository" routes.goPositive Highlights✅ Excellent Test Coverage: 10 unit tests (Ginkgo) + 4 e2e tests (Cypress) covering happy path, edge cases, and error conditions. ✅ Proper Security Patterns: User token authentication enforced, RBAC checks, proper auth tests with ✅ Clean Code Removal: Removed 196 lines of dead code ( ✅ Consistent Naming: ✅ React Query Best Practices: Proper query hooks with invalidation, cache management, and mutation patterns per ✅ Shadcn UI Compliance: All UI components use Shadcn ( ✅ Type Safety (Frontend): Zero ✅ CRD Updates: Proper OpenAPI schema in ✅ Error Handling: Non-fatal handling in ✅ Idempotent Operations: Retry logic in RecommendationsPrioritized Action ItemsBefore Merge:
Post-Merge (Nice-to-Have):
Architecture & DesignDesign Pattern: The separation of concerns is excellent:
Hydration Strategy: The API Design: RESTful endpoints ( Testing AssessmentUnit Tests (
E2E Tests (
Coverage: Excellent. All major flows covered. Security Review✅ Authentication: User token required for all operations Performance Considerations
Mitigation: Already implemented - non-fatal error handling, depth=1 clone, single-branch fetch. Future Optimization: Consider caching config repos at the cluster level (shared PVC), but out of scope for this PR. Final VerdictApprove with Minor Fixes ⭐⭐⭐⭐☆ This is a well-architected feature with strong adherence to project standards. The two critical issues are straightforward to fix and don't affect functionality - they're about consistency and defensive programming. Estimated Fix Time: 5 minutes Strengths: Clean code removal, comprehensive tests, proper React Query patterns, security-conscious, excellent UX (pre-fill from workspace defaults). Weaknesses: Minor type-safety oversights in error handling paths (easily fixed). 🔍 View AI decision process (logs available for 90 days) 📋 View memory system files loaded (click to expand)What Amber Loaded for Code ReviewAmber automatically loaded these repository standards from the memory system:
Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines. |
No description provided.