fix: unify CLI image discovery and standardize Go tooling#738
fix: unify CLI image discovery and standardize Go tooling#738
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
🧰 Additional context used📓 Path-based instructions (4)**/*.{py,ts,tsx,js,vue,go}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
cli/**/*.go📄 CodeRabbit inference engine (CLAUDE.md)
Files:
.pre-commit-config.yaml📄 CodeRabbit inference engine (CLAUDE.md)
Files:
cli/**/*_test.go📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (30)📓 Common learnings📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-19T11:19:40.044ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-15T18:17:43.675ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-16T19:52:03.656ZApplied to files:
📚 Learning: 2026-03-19T11:30:29.217ZApplied to files:
📚 Learning: 2026-03-15T18:17:43.675ZApplied to files:
📚 Learning: 2026-03-15T18:17:43.675ZApplied to files:
📚 Learning: 2026-03-19T11:19:40.044ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-19T11:19:40.044ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-19T11:30:29.217ZApplied to files:
📚 Learning: 2026-03-19T11:19:40.044ZApplied to files:
📚 Learning: 2026-03-15T20:45:14.430ZApplied to files:
📚 Learning: 2026-03-19T07:12:14.508ZApplied to files:
📚 Learning: 2026-03-15T12:00:18.113ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-22T15:39:41.418ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
📚 Learning: 2026-03-15T18:17:43.675ZApplied to files:
📚 Learning: 2026-03-15T12:00:18.113ZApplied to files:
📚 Learning: 2026-03-15T21:32:02.880ZApplied to files:
🧬 Code graph analysis (7)cli/cmd/update.go (1)
cli/internal/diagnostics/collect_test.go (1)
cli/cmd/update_health_test.go (1)
cli/cmd/update_health.go (1)
cli/internal/diagnostics/collect.go (1)
cli/cmd/update_cleanup.go (1)
cli/internal/images/images_test.go (1)
🔇 Additional comments (33)
WalkthroughThis pull request centralizes SynthOrg container image discovery and reference construction into a new Suggested labels
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Dependency ReviewThe following issues were found:
|
Summary of ChangesHello, 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 significantly improves the CLI's robustness and maintainability by centralizing Docker image management and standardizing Go tooling practices. The changes ensure that all SynthOrg images, including those pulled by digest, are correctly identified and managed, preventing silent failures in cleanup operations. Furthermore, the adoption of Highlights
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. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request is a significant and beneficial refactoring. It correctly fixes a bug in Docker image discovery for digest-only images by implementing a more robust listing method. It also greatly improves code maintainability by centralizing duplicated image-related logic into a new internal/images package. The standardization of Go tooling to use go -C cli is a good consistency improvement. The new images package is well-tested, including fuzz tests. I have one suggestion to make the image list parsing slightly more efficient and idiomatic.
| func parseImageList(raw string) []LocalImage { | ||
| var images []LocalImage | ||
| for line := range strings.SplitSeq(strings.TrimSpace(strings.ReplaceAll(raw, "\r\n", "\n")), "\n") { | ||
| if line == "" { | ||
| continue | ||
| } | ||
| parts := strings.SplitN(line, "\t", 5) | ||
| if len(parts) < 5 { | ||
| continue | ||
| } | ||
| repo := parts[0] | ||
| if !strings.HasPrefix(repo, RepoPrefix) { | ||
| continue | ||
| } | ||
| images = append(images, LocalImage{ | ||
| Repository: repo, | ||
| Tag: parts[1], | ||
| Size: parts[2], | ||
| ID: parts[3], | ||
| Digest: parts[4], | ||
| }) | ||
| } | ||
| return images | ||
| } |
There was a problem hiding this comment.
For better performance and more idiomatic Go, consider using a bufio.Scanner to process the raw string line by line. This avoids creating intermediate strings with strings.ReplaceAll and strings.TrimSpace on the entire input, making it more memory-efficient, especially if the docker images output is large. bufio.Scanner also handles both \n and \r\n line endings automatically.
You'll need to add import "bufio" to your imports.
func parseImageList(raw string) []LocalImage {
var images []LocalImage
scanner := bufio.NewScanner(strings.NewReader(raw))
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
parts := strings.SplitN(line, "\t", 5)
if len(parts) < 5 {
continue
}
repo := parts[0]
if !strings.HasPrefix(repo, RepoPrefix) {
continue
}
images = append(images, LocalImage{
Repository: repo,
Tag: parts[1],
Size: parts[2],
ID: parts[3],
Digest: parts[4],
})
}
return images
}There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
cli/cmd/update.go (1)
615-617: 🧹 Nitpick | 🔵 TrivialConsider deriving regex pattern from
images.RepoPrefixfor consistency.The
imageLinePatternregex hardcodesghcr.io/aureliolo/synthorg-while line 641 usesimages.RepoPrefix. While functionally correct (the regex matches existing compose content), deriving the pattern from the constant would ensure consistency if the prefix ever changes.However, since regex patterns require escaping and the prefix is unlikely to change, this is a minor observation rather than a required change.
Also applies to: 641-641
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cli/cmd/update.go` around lines 615 - 617, The regex variable imageLinePattern currently hardcodes the repo prefix; change its initialization to build the pattern from images.RepoPrefix so the code stays consistent if the prefix changes: compose the pattern string using regexp.QuoteMeta(images.RepoPrefix) (to escape special chars) and fmt.Sprintf to insert the quoted prefix into the existing pattern that still matches (e.g. `(\s+image:\s+)<quotedPrefix>(backend|web|sandbox)[\S]*`), then call regexp.MustCompile on that string to set imageLinePattern.cli/cmd/update_health_test.go (1)
9-117: 🧹 Nitpick | 🔵 TrivialConsider consolidating with
images_test.goto reduce duplication.This test file now tests
images.RefForServicefrom thecmdpackage, whilecli/internal/images/images_test.gohas comprehensive tests for the same function. The test cases largely overlap (digest-pinned, tag-based, nil/empty digests, service not in map, etc.).Options:
- Keep both if the intent is to test from the caller's perspective (integration-style).
- Remove this file and rely on
images_test.gofor unit coverage.- Reduce this file to a few smoke tests and let
images_test.gohandle edge cases.Given the PR description mentions "Existing tests updated to call shared functions," keeping caller-side tests may be intentional for regression detection.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cli/cmd/update_health_test.go` around lines 9 - 117, The TestRefForService file duplicates coverage already exercised by cli/internal/images/images_test.go for images.RefForService; either delete this test file (cli/cmd/update_health_test.go) and rely on images_test.go for unit coverage, or reduce it to 2–3 caller-level smoke tests that only assert a couple of representative behaviors (e.g., digest-pinned and tag-based) and remove overlapping table-driven cases; update or remove references to TestRefForService and ensure remaining tests call images.RefForService to preserve any intended integration/caller-level checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@cli/cmd/update_health_test.go`:
- Around line 9-117: The TestRefForService file duplicates coverage already
exercised by cli/internal/images/images_test.go for images.RefForService; either
delete this test file (cli/cmd/update_health_test.go) and rely on images_test.go
for unit coverage, or reduce it to 2–3 caller-level smoke tests that only assert
a couple of representative behaviors (e.g., digest-pinned and tag-based) and
remove overlapping table-driven cases; update or remove references to
TestRefForService and ensure remaining tests call images.RefForService to
preserve any intended integration/caller-level checks.
In `@cli/cmd/update.go`:
- Around line 615-617: The regex variable imageLinePattern currently hardcodes
the repo prefix; change its initialization to build the pattern from
images.RepoPrefix so the code stays consistent if the prefix changes: compose
the pattern string using regexp.QuoteMeta(images.RepoPrefix) (to escape special
chars) and fmt.Sprintf to insert the quoted prefix into the existing pattern
that still matches (e.g.
`(\s+image:\s+)<quotedPrefix>(backend|web|sandbox)[\S]*`), then call
regexp.MustCompile on that string to set imageLinePattern.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 271f5783-59eb-4823-83e1-953455974205
⛔ Files ignored due to path filters (1)
cli/go.sumis excluded by!**/*.sum
📒 Files selected for processing (11)
.pre-commit-config.yamlCLAUDE.mdcli/cmd/update.gocli/cmd/update_cleanup.gocli/cmd/update_health.gocli/cmd/update_health_test.gocli/go.modcli/internal/diagnostics/collect.gocli/internal/diagnostics/collect_test.gocli/internal/images/images.gocli/internal/images/images_test.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: CLI Test (windows-latest)
- GitHub Check: CLI Test (macos-latest)
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (1)
cli/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
cli/**/*.go: Go CLI must use Cobra for command structure, charmbracelet libraries for terminal UI, sigstore-go for signature verification, go-containerregistry for Docker image handling, go-tuf for TUF verification
Go CLI binaries must verify cosign signatures and SLSA provenance at pull time; provide--skip-verifybypass option
Files:
cli/cmd/update.gocli/cmd/update_health_test.gocli/internal/diagnostics/collect_test.gocli/cmd/update_health.gocli/cmd/update_cleanup.gocli/internal/diagnostics/collect.gocli/internal/images/images_test.gocli/internal/images/images.go
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow: Go lint (golangci-lint + go vet) + test (-race -coverprofile) + build (cross-compile: linux/darwin/windows × amd64/arm64) + govulncheck + fuzz testing (main-only, 30s/target, continue-on-error, matrix over 4 packages). cli-pass gate includes fuzz as informational. GoReleaser release on v* tags. Cosign keyless signing of checksums.txt. SLSA L3 provenance attestations. Sigstore bundle (.sigstore.json) attached. Post-release appends checksums/verification/provenance to draft release notes.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/docker.yml : Docker workflow: builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via actions/attest-build-provenance. Scans: Trivy (CRITICAL = hard fail, HIGH = warn) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via .github/.trivyignore.yaml and .github/.grype.yaml. Images only pushed after scans pass. Triggers on push to main and version tags (v*).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T12:00:18.113Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`) -- fast gate before push, skipped in pre-commit.ci
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Applies to cli/**/*.go : Go CLI must use Cobra for command structure, charmbracelet libraries for terminal UI, sigstore-go for signature verification, go-containerregistry for Docker image handling, go-tuf for TUF verification
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:52:03.656Z
Learning: Applies to cli/**/*.go : Lint CLI Go code with golangci-lint and go vet; test with go test -race; check vulnerabilities with govulncheck
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on cli/**/*.go) (fast gate before push, skipped in pre-commit.ci — dedicated CI jobs already run these).
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).
Applied to files:
cli/cmd/update.goCLAUDE.md.pre-commit-config.yamlcli/go.modcli/cmd/update_health.gocli/cmd/update_cleanup.go
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Applies to cli/**/*.go : Go CLI must use Cobra for command structure, charmbracelet libraries for terminal UI, sigstore-go for signature verification, go-containerregistry for Docker image handling, go-tuf for TUF verification
Applied to files:
cli/cmd/update.goCLAUDE.mdcli/go.modcli/cmd/update_health.gocli/cmd/update_cleanup.gocli/internal/diagnostics/collect.gocli/internal/images/images.go
📚 Learning: 2026-03-16T19:52:03.656Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-16T19:52:03.656Z
Learning: Applies to cli/**/*.go : Lint CLI Go code with golangci-lint and go vet; test with go test -race; check vulnerabilities with govulncheck
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.modcli/internal/images/images_test.go
📚 Learning: 2026-03-19T11:30:29.217Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:30:29.217Z
Learning: Applies to cli/**/*.go : Run Go lint via `golangci-lint run`, vet via `go vet`, tests via `go test ./...`, and fuzz via `go test -fuzz=FuzzTarget -fuzztime=30s`
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.modcli/internal/images/images_test.go
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to .github/workflows/cli.yml : CLI workflow: Go lint (golangci-lint + go vet) + test (-race -coverprofile) + build (cross-compile: linux/darwin/windows × amd64/arm64) + govulncheck + fuzz testing (main-only, 30s/target, continue-on-error, matrix over 4 packages). cli-pass gate includes fuzz as informational. GoReleaser release on v* tags. Cosign keyless signing of checksums.txt. SLSA L3 provenance attestations. Sigstore bundle (.sigstore.json) attached. Post-release appends checksums/verification/provenance to draft release notes.
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.modcli/internal/images/images_test.go
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: For CLI Go commands requiring module root as cwd, use `go -C cli` (changes directory internally) instead of `cd cli` (poisons the shell cwd)
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.mod
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Run Go linting with `golangci-lint run` from a subshell (use `(cd cli && golangci-lint run)` instead of `go -C cli lint` which doesn't exist)
Applied to files:
CLAUDE.md.pre-commit-config.yaml
📚 Learning: 2026-03-15T20:45:14.430Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T20:45:14.430Z
Learning: Shell commands: for Go CLI work, cd cli is an exception because Go tooling requires working directory to be the module root. Go commands require `cd cli` for other work, never use `cd`.
Applied to files:
CLAUDE.md.pre-commit-config.yaml
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/go.mod : Go CLI dependencies: Go 1.26+, Cobra (commands), charmbracelet/huh (interactive CLI), charmbracelet/lipgloss (styled output).
Applied to files:
CLAUDE.mdcli/go.modcli/cmd/update_health.go
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to cli/**/*.go : Lint Go code with `golangci-lint` and `go vet`. Run tests with `-race` flag to detect race conditions.
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.mod
📚 Learning: 2026-03-15T21:32:02.880Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T21:32:02.880Z
Learning: Applies to cli/**/*.go : Go CLI (Go 1.26+) uses Cobra for commands, charmbracelet/huh for interactive CLI, charmbracelet/lipgloss for styled output. Cross-platform builds (linux/darwin/windows × amd64/arm64). GoReleaser for releases with cosign keyless signing of checksums.txt. SLSA L3 provenance attestations via actions/attest-build-provenance.
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.modcli/cmd/update_health.go
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Use `go -C cli` to run Go commands in CLI directory (build, test, vet, fuzz) without changing shell cwd
Applied to files:
CLAUDE.md.pre-commit-config.yaml
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Use `go -C cli test -fuzz=FuzzYamlStr -fuzztime=30s ./internal/compose/` for fuzzing Go CLI code
Applied to files:
CLAUDE.mdcli/internal/images/images_test.go
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.
Applied to files:
CLAUDE.md.pre-commit-config.yamlcli/go.mod
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Applies to site/**/*.astro : Use Astro for the synthorg.io landing page; include `/get/` CLI install page, contact form, SEO
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-19T07:12:14.508Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T07:12:14.508Z
Learning: Applies to src/synthorg/**/*.py : Package structure: src/synthorg/ organized as: api/ (REST+WebSocket, Litestar), auth/ (auth subpackage), backup/ (scheduled/manual backups), budget/ (cost tracking, CFO), cli/ (superseded by Go CLI), communication/ (message bus, meetings), config/ (YAML loading), core/ (domain models, resilience config), engine/ (orchestration, task state, coordination, approval gates, stagnation detection, context budget, compaction), hr/ (hiring, performance, promotion), memory/ (pluggable backend, Mem0, retrieval, consolidation), persistence/ (operational data, SQLite, settings), observability/ (logging, correlation, sinks), providers/ (LLM abstraction, LiteLLM, auth types, presets, runtime CRUD), settings/ (runtime-editable, typed definitions, encryption, config bridge), security/ (SecOps, rule engine, output scanning, progressive trust, autonomy levels), templates/ (company templates, personalities), tools/ (registry, built-in tools, git, sandbox, code_runner, MCP...
Applied to files:
CLAUDE.md
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on `cli/**/*.go`) -- fast gate before push, skipped in pre-commit.ci
Applied to files:
.pre-commit-config.yaml
📚 Learning: 2026-03-15T18:17:43.675Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T18:17:43.675Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on cli/**/*.go) (fast gate before push, skipped in pre-commit.ci — dedicated CI jobs already run these).
Applied to files:
.pre-commit-config.yaml
📚 Learning: 2026-03-19T11:30:29.217Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:30:29.217Z
Learning: Applies to cli/**/*.go : Use native `testing.F` fuzz functions (`Fuzz*`) for fuzz testing Go code
Applied to files:
cli/cmd/update_health_test.gocli/internal/images/images_test.go
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to cli/**/*.go : Use native Go testing with `testing.F` fuzz functions (`Fuzz*`) for fuzz testing.
Applied to files:
cli/cmd/update_health_test.gocli/internal/images/images_test.go
📚 Learning: 2026-03-19T11:19:40.044Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T11:19:40.044Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).
Applied to files:
cli/go.modcli/cmd/update_health.go
📚 Learning: 2026-03-22T14:41:20.060Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-22T14:41:20.060Z
Learning: Applies to docker/Dockerfile* : Docker images: backend (Chainguard distroless, non-root), web (nginx-unprivileged, SPA + API proxy), sandbox (Python + Node.js, non-root)
Applied to files:
cli/internal/images/images.go
🧬 Code graph analysis (7)
cli/cmd/update.go (1)
cli/internal/images/images.go (1)
RepoPrefix(15-15)
cli/cmd/update_health_test.go (1)
cli/internal/images/images.go (1)
RefForService(30-36)
cli/internal/diagnostics/collect_test.go (1)
cli/internal/images/images.go (1)
RefForService(30-36)
cli/cmd/update_health.go (1)
cli/internal/images/images.go (3)
ServiceNames(19-24)RefForService(30-36)InspectID(98-104)
cli/cmd/update_cleanup.go (1)
cli/internal/images/images.go (5)
ListLocal(58-66)RepoPrefix(15-15)ServiceNames(19-24)RefForService(30-36)InspectID(98-104)
cli/internal/diagnostics/collect.go (1)
cli/internal/images/images.go (4)
ServiceNames(19-24)RefForService(30-36)InspectID(98-104)RepoPrefix(15-15)
cli/internal/images/images.go (2)
cli/internal/verify/identity.go (2)
RegistryHost(27-27)ImageRepoPrefix(30-30)cli/internal/docker/client.go (1)
RunCmd(116-125)
🪛 GitHub Actions: Dependency Review
cli/go.mod
[error] 1-1: Dependency review detected incompatible licenses. Examples: github.com/alfatraining/structtag@1.0.0 (BSD-3-Clause AND CC-BY-3.0), github.com/denis-tingaikin/go-header@0.5.0 (GPL-3.0 AND GPL-3.0-only), github.com/fatih/structtag@1.2.0 (BSD-3-Clause AND CC-BY-3.0), github.com/ldez/structtags@0.6.1 (GPL-3.0 AND GPL-3.0-only), github.com/leonklingele/grouper@1.1.2 (GPL-3.0 AND GPL-3.0-only), github.com/xen0n/gosmopolitan@1.3.0 (GPL-1.0-or-later AND GPL-3.0 AND GPL-3.0-only), github.com/golangci/golangci-lint/v2@2.11.3 (GPL-3.0).
🔇 Additional comments (21)
.pre-commit-config.yaml (2)
76-82: Hook depends on thetooldirective ingo.mod.The
go -C cli tool golangci-lint runcommand requires thetooldirective added ingo.mod. If the license compliance issue is resolved by removing that directive, this hook entry will need to revert to the previous approach (e.g., ensuringgolangci-lintis installed externally and usingbash -c 'cd cli && golangci-lint run').If the tool directive remains, this change correctly follows the
go -C clipattern. Based on learnings: "For CLI Go commands requiring module root as cwd, usego -C cli(changes directory internally) instead ofcd cli."
84-98: LGTM!The
go vetandgo testhooks correctly usego -C clito run commands in the CLI module directory without changing the shell's working directory.CLAUDE.md (2)
60-68: LGTM!The documentation accurately explains the
go -C clipattern and the golangci-lint tool registration. The note about avoidingcd cliis helpful for maintaining consistent shell behavior.
135-135: LGTM!The
imagessubmodule is correctly added to the internal directory listing, reflecting the new package introduced in this PR.cli/internal/images/images.go (4)
19-24: Note:ServiceNamesreturns a new slice each call (by design).The function returns a fresh slice literal on each invocation, which is intentional to prevent callers from mutating a shared slice. This is validated by
TestServiceNames/"returns fresh slice"in the test file. Good defensive design.
30-36: LGTM!
RefForServicecorrectly prioritizes digest-pinned references when a verified digest exists, falling back to tag-based references. The empty-string check on the digest value prevents malformed refs likerepo@.
58-66: LGTM!
ListLocalandInspectIDproperly delegate todocker.RunCmdand handle the output parsing. The--formattemplate ensures consistent output across Docker versions.InspectIDcorrectly trims whitespace from the output.Also applies to: 98-104
71-94: Use ofstrings.SplitSeqis compatible with Go 1.26 requirement.
strings.SplitSeqwas added in Go 1.24 and is available in Go 1.26+. The parsing logic correctly handles CRLF normalization, skips empty lines and malformed rows, and properly filters to only SynthOrg images by RepoPrefix.cli/cmd/update.go (1)
19-19: LGTM!The import of the new
imagespackage enables the consolidation of image reference logic.cli/internal/images/images_test.go (3)
159-164: Excellent test case documenting the bug fix.The
"digest-only image (no tag) -- the bug this fixes"test case directly validates the core issue this PR addresses: ensuring images pulled by digest (with<none>tag) are correctly discovered.
238-270: LGTM!The fuzz test validates key invariants:
- Output always starts with
RepoPrefix + svc- Separator is always
@or:@is used iff digest is non-emptyThis provides strong guarantees about
RefForServicebehavior across arbitrary inputs.
35-43: Good defensive test for slice independence.Testing that
ServiceNamesreturns independent slices prevents a subtle bug where callers could accidentally mutate shared state.cli/cmd/update_cleanup.go (3)
70-93: LGTM!The refactored
listNonCurrentImagesnow uses the centralizedimages.ListLocalfor image discovery, which correctly finds both tagged and digest-only images. The iteration overimages.LocalImagestruct fields is cleaner than parsing raw output inline.
126-149: LGTM!
collectCurrentImageIDscorrectly:
- Gets service names from
images.ServiceNames- Builds references via
images.RefForService(handling digest vs tag)- Resolves IDs via
images.InspectID- Stores both full (
sha256:...) and short (12-char) IDs for matchingThis ensures cleanup won't accidentally delete current images regardless of how Docker reports IDs.
97-100: LGTM!The display prefix derivation using
strings.TrimPrefix(repo, images.RepoPrefix)followed by re-adding"synthorg-"creates readable output likesynthorg-backend:0.4.6while using the centralized constant.cli/cmd/update_health_test.go (1)
6-6: LGTM!The test correctly imports and calls
images.RefForServiceinstead of the removed local helper. The test cases validate the function behaves correctly from the command layer's perspective.Also applies to: 111-111
cli/internal/diagnostics/collect_test.go (1)
389-458: LGTM! Test correctly validates the compose-ref-first priority.The test accurately replicates the inline priority logic from
checkImages: compose ref takes precedence, then falls back toimages.RefForServicewhich handles digest-vs-tag selection. The test cases comprehensively cover compose-ref priority, digest fallback, tag fallback, and service mismatch scenarios.cli/cmd/update_health.go (1)
120-134: LGTM! Clean consolidation of image detection logic.The refactoring correctly delegates to the centralized
imagespackage:
images.ServiceNamesfor service enumeration (including conditional sandbox)images.RefForServicefor digest-vs-tag reference constructionimages.InspectIDfor local image inspectionThe context cancellation handling (lines 126-130) is appropriately preserved to avoid false positives when Docker is unresponsive.
cli/internal/diagnostics/collect.go (3)
311-324: LGTM! Clean refactoring to centralized image utilities.The
checkImagesfunction correctly delegates to theimagespackage:
- Service enumeration via
images.ServiceNames(sandbox)- Compose-ref-first priority with
images.RefForServicefallback- Image inspection via
images.InspectIDThe priority logic (compose ref > verified digest > tag) is preserved and now consistent with other commands.
338-355: Good documentation and safe path handling.The updated doc comment clearly explains the intentional silent error handling for diagnostics robustness.
The removal of the explicit
..path traversal check is safe becausecomposePathis always constructed internally viacheckComposeFilewhich usesfilepath.Join(dataDir, name)withnamefrom the hardcodedcomposeFileNamesslice anddataDirfromconfig.SecurePath. Thefilepath.Cleancall provides additional normalization.
367-379: LGTM! Consistent use of centralized prefix constant.Using
images.RepoPrefixinstead of a local constant ensures consistency across all image-handling code paths. The suffix extraction logic correctly handles both tag (:) and digest (@) separators.
Docker's --filter "reference=..." misses digest-only images (no tag), causing `synthorg uninstall` and `synthorg cleanup` to skip images like the sandbox that were pulled by digest. Extract shared `internal/images` package with: - ListLocal: lists ALL local SynthOrg images (tagged + digest-only) - RefForService: single source of truth for image ref construction - ServiceNames: canonical service name list - InspectID: shared docker image inspect wrapper Eliminates duplicated image constants and logic across update_cleanup, update_health, diagnostics, and update commands. Also standardizes all Go tooling to use `go -C cli`: - Add golangci-lint as `tool` directive in go.mod - Replace all subshell and bash-c directory-change patterns - Update pre-commit hooks, CLAUDE.md, and examples Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add images package to CLAUDE.md Package Structure section - Remove duplicate FuzzRefForService from cmd package (canonical home is internal/images) - Derive display prefix from images.RepoPrefix instead of hardcoding - Remove misleading path traversal guard, add intentional-fallback doc - Add converse fuzz invariant (no @ when digest is empty) Pre-reviewed by 4 agents, 6 findings addressed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… review CC-BY-3.0 and CC-BY-4.0 are permissive (attribution-only) and broadly compatible -- added to the global allow-licenses list. golangci-lint and its GPL-licensed linter deps are dev-only tool dependencies (go.mod `tool` directive) that never get compiled into the SynthOrg binary. GPL copyleft does not apply. Added per-package exemptions since the action cannot distinguish tool vs runtime deps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update CLAUDE.md CI section: dep review allows weak-copyleft + GPL exemptions, not "permissive only" - Update CLAUDE.md pre-commit hooks: golangci-lint and go vet now run at pre-commit stage (not just pre-push) - Restore 2 dropped test cases in TestDiagnosticImageRefPriority (nil maps, empty digest value) - Rename local var `images` to `result` in parseImageList to avoid shadowing the package identifier Pre-reviewed by 3 local agents + 2 external reviewers, 4 findings fixed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c6bd5cb to
98bbce4
Compare
🤖 I have created a release *beep* *boop* --- ## [0.4.7](v0.4.6...v0.4.7) (2026-03-22) ### Features * add system user for CLI-to-backend authentication ([#710](#710)) ([dc6bd3f](dc6bd3f)) * dev channel builds with incremental pre-releases between stable releases ([#715](#715)) ([0e8a714](0e8a714)) * replace hardcoded name pools with Faker multi-locale name generation ([#714](#714)) ([5edc6ec](5edc6ec)) ### Bug Fixes * dev-release tag creation, dependabot coverage, go -C cli convention ([#730](#730)) ([7634843](7634843)) * improve name generation step UX and fix sentinel expansion bug ([#739](#739)) ([f03fd05](f03fd05)) * settings page UX polish -- toggle bug, source badges, form improvements ([#712](#712)) ([d16a0ac](d16a0ac)) * switch dev tags to semver and use same release pipeline as stable ([#729](#729)) ([4df6b9b](4df6b9b)), closes [#713](#713) * unify CLI image discovery and standardize Go tooling ([#738](#738)) ([712a785](712a785)) * use PAT in dev-release workflow to trigger downstream pipelines ([#716](#716)) ([d767aa3](d767aa3)) ### CI/CD * bump astral-sh/setup-uv from 7.4.0 to 7.6.0 in /.github/actions/setup-python-uv in the minor-and-patch group ([#731](#731)) ([7887257](7887257)) * bump the minor-and-patch group with 3 updates ([#735](#735)) ([7cd253a](7cd253a)) * bump wrangler from 4.75.0 to 4.76.0 in /.github in the minor-and-patch group ([#732](#732)) ([a6cafc7](a6cafc7)) * clean up all dev releases and tags on stable release ([#737](#737)) ([8d90f5c](8d90f5c)) ### Maintenance * bump the minor-and-patch group across 2 directories with 2 updates ([#733](#733)) ([2b60069](2b60069)) * bump the minor-and-patch group with 3 updates ([#734](#734)) ([859bc25](859bc25)) * fix dependabot labels and add scope tags ([#736](#736)) ([677eb15](677eb15)) * remove redundant pytest.mark.timeout(30) markers ([#740](#740)) ([9ec2163](9ec2163)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Summary
--filter "reference=..."misses images pulled by digest only (no tag), causingsynthorg uninstallandsynthorg cleanupto skip the sandbox image. Newinternal/imagespackage lists all images and filters by repo prefix in Go.images.ListLocal,images.RefForService,images.ServiceNames, andimages.InspectID-- replacing 3 duplicate constants and 4 duplicate function implementations acrossupdate_cleanup,update_health,diagnostics, andupdatecommands.go -C cli: Add golangci-lint as atooldirective ingo.mod, replace all(cd cli && ...)andbash -c 'cd cli && ...'patterns in pre-commit hooks and documentation.Test plan
internal/imagespackage has full test coverage:TestServiceNames,TestRefForService,TestLocalImage_ServiceName,TestParseImageList(including digest-only case),TestParseImageListFieldValues,FuzzRefForService,FuzzParseImageListTestRefForServicein cmd,TestDiagnosticImageRefPriorityin diagnostics)go -C cli build ./...passesgo -C cli vet ./...passesgo -C cli test ./...all packages passgo -C cli tool golangci-lint runreports 0 issuesgo -C clipattern)Review coverage
Pre-reviewed by 4 agents (docs-consistency, go-reviewer, go-conventions-enforcer, infra-reviewer). 6 findings addressed:
imagesto CLAUDE.md Package Structureimages.RepoPrefixinstead of hardcoding@when digest is empty)🤖 Generated with Claude Code