fix(images): resolve remaining coderabbit nitpicks
- commit
- 351d7d0b152e62cb53fda40950183b3b46c69e4a
- author
- brice · · 2026-02-08 07:47 UTC
- committer
- brice · · 2026-02-08 09:40 UTC
- parent
- e5e7237
- signature
- unsigned
4 files · +28 -2
M docs/cli/images.md +2 -0
| @@ -37,6 +37,8 @@ Flags: | |||
| 37 | 37 | | `--keep` | `0` | Number of latest tags to keep per repository (`0` disables registry cleanup) | | |
| 38 | 38 | | `--runtime-only` | `false` | Prune dangling runtime images only; forces registry cleanup off | | |
| 39 | 39 | ||
| 40 | + | `--keep` defaults to `0` for ad-hoc CLI safety (registry cleanup off by default), while scheduled pruning uses `images.prune.keep_last` from config (default `3`). Use config for recurring behavior; when a CLI `--keep` value is provided, that request value is used. | |
| 41 | + | ||
| 40 | 42 | Behavior notes: | |
| 41 | 43 | ||
| 42 | 44 | - `--runtime-only` forces `keep_last = 0`. | |
| @@ -37,6 +37,8 @@ Flags: | |||||
| 37 | | `--keep` | `0` | Number of latest tags to keep per repository (`0` disables registry cleanup) | | 37 | | `--keep` | `0` | Number of latest tags to keep per repository (`0` disables registry cleanup) | | ||
| 38 | | `--runtime-only` | `false` | Prune dangling runtime images only; forces registry cleanup off | | 38 | | `--runtime-only` | `false` | Prune dangling runtime images only; forces registry cleanup off | | ||
| 39 | 39 | ||||
| 40 | + | `--keep` defaults to `0` for ad-hoc CLI safety (registry cleanup off by default), while scheduled pruning uses `images.prune.keep_last` from config (default `3`). Use config for recurring behavior; when a CLI `--keep` value is provided, that request value is used. | |||
| 41 | + | ||||
| 40 | Behavior notes: | 42 | Behavior notes: | ||
| 41 | 43 | ||||
| 42 | - `--runtime-only` forces `keep_last = 0`. | 44 | - `--runtime-only` forces `keep_last = 0`. | ||
M internal/adapters/out/docker/runtime.go +1 -1
| @@ -597,7 +597,7 @@ func (r *Runtime) PruneImages(ctx context.Context, danglingOnly bool) (runtimepk | |||
| 597 | 597 | ||
| 598 | 598 | pruneFilters := filters.NewArgs() | |
| 599 | 599 | if danglingOnly { | |
| 600 | - | pruneFilters.Add("dangling", strconv.FormatBool(true)) | |
| 600 | + | pruneFilters.Add("dangling", "true") | |
| 601 | 601 | } | |
| 602 | 602 | ||
| 603 | 603 | pruneResult, err := r.client.ImagesPrune(ctx, pruneFilters) | |
| @@ -597,7 +597,7 @@ func (r *Runtime) PruneImages(ctx context.Context, danglingOnly bool) (runtimepk | |||||
| 597 | 597 | ||||
| 598 | pruneFilters := filters.NewArgs() | 598 | pruneFilters := filters.NewArgs() | ||
| 599 | if danglingOnly { | 599 | if danglingOnly { | ||
| 600 | - | pruneFilters.Add("dangling", strconv.FormatBool(true)) | 600 | + | pruneFilters.Add("dangling", "true") |
| 601 | } | 601 | } | ||
| 602 | 602 | ||||
| 603 | pruneResult, err := r.client.ImagesPrune(ctx, pruneFilters) | 603 | pruneResult, err := r.client.ImagesPrune(ctx, pruneFilters) | ||
M internal/usecase/images/service.go +2 -1
| @@ -353,7 +353,8 @@ func splitRepoTag(repoTag string) (string, string) { | |||
| 353 | 353 | } | |
| 354 | 354 | ||
| 355 | 355 | idx := strings.LastIndex(repoTag, ":") | |
| 356 | - | if idx <= 0 || idx >= len(repoTag)-1 { | |
| 356 | + | slashIdx := strings.LastIndex(repoTag, "/") | |
| 357 | + | if idx <= slashIdx || idx >= len(repoTag)-1 { | |
| 357 | 358 | return repoTag, "" | |
| 358 | 359 | } | |
| 359 | 360 | ||
| @@ -353,7 +353,8 @@ func splitRepoTag(repoTag string) (string, string) { | |||||
| 353 | } | 353 | } | ||
| 354 | 354 | ||||
| 355 | idx := strings.LastIndex(repoTag, ":") | 355 | idx := strings.LastIndex(repoTag, ":") | ||
| 356 | - | if idx <= 0 || idx >= len(repoTag)-1 { | 356 | + | slashIdx := strings.LastIndex(repoTag, "/") |
| 357 | + | if idx <= slashIdx || idx >= len(repoTag)-1 { | |||
| 357 | return repoTag, "" | 358 | return repoTag, "" | ||
| 358 | } | 359 | } | ||
| 359 | 360 | ||||
M internal/usecase/images/service_test.go +23 -0
| @@ -614,4 +614,27 @@ func (f *fakeBlobStorage) DeleteBlob(digest string) error { | |||
| 614 | 614 | return nil | |
| 615 | 615 | } | |
| 616 | 616 | ||
| 617 | + | func TestSplitRepoTag(t *testing.T) { | |
| 618 | + | tests := []struct { | |
| 619 | + | name string | |
| 620 | + | input string | |
| 621 | + | wantRepo string | |
| 622 | + | wantTag string | |
| 623 | + | }{ | |
| 624 | + | {name: "repository and tag", input: "alpine:latest", wantRepo: "alpine", wantTag: "latest"}, | |
| 625 | + | {name: "registry port and tag", input: "localhost:5000/repo:v1", wantRepo: "localhost:5000/repo", wantTag: "v1"}, | |
| 626 | + | {name: "registry port without tag", input: "localhost:5000/repo", wantRepo: "localhost:5000/repo", wantTag: ""}, | |
| 627 | + | {name: "missing tag", input: "alpine", wantRepo: "alpine", wantTag: ""}, | |
| 628 | + | {name: "trailing colon", input: "alpine:", wantRepo: "alpine:", wantTag: ""}, | |
| 629 | + | } | |
| 630 | + | ||
| 631 | + | for _, tt := range tests { | |
| 632 | + | t.Run(tt.name, func(t *testing.T) { | |
| 633 | + | repo, tag := splitRepoTag(tt.input) | |
| 634 | + | assert.Equal(t, tt.wantRepo, repo) | |
| 635 | + | assert.Equal(t, tt.wantTag, tag) | |
| 636 | + | }) | |
| 637 | + | } | |
| 638 | + | } | |
| 639 | + | ||
| 617 | 640 | var _ pkgruntime.Runtime = (*fakeRuntime)(nil) | |
| @@ -614,4 +614,27 @@ func (f *fakeBlobStorage) DeleteBlob(digest string) error { | |||||
| 614 | return nil | 614 | return nil | ||
| 615 | } | 615 | } | ||
| 616 | 616 | ||||
| 617 | + | func TestSplitRepoTag(t *testing.T) { | |||
| 618 | + | tests := []struct { | |||
| 619 | + | name string | |||
| 620 | + | input string | |||
| 621 | + | wantRepo string | |||
| 622 | + | wantTag string | |||
| 623 | + | }{ | |||
| 624 | + | {name: "repository and tag", input: "alpine:latest", wantRepo: "alpine", wantTag: "latest"}, | |||
| 625 | + | {name: "registry port and tag", input: "localhost:5000/repo:v1", wantRepo: "localhost:5000/repo", wantTag: "v1"}, | |||
| 626 | + | {name: "registry port without tag", input: "localhost:5000/repo", wantRepo: "localhost:5000/repo", wantTag: ""}, | |||
| 627 | + | {name: "missing tag", input: "alpine", wantRepo: "alpine", wantTag: ""}, | |||
| 628 | + | {name: "trailing colon", input: "alpine:", wantRepo: "alpine:", wantTag: ""}, | |||
| 629 | + | } | |||
| 630 | + | ||||
| 631 | + | for _, tt := range tests { | |||
| 632 | + | t.Run(tt.name, func(t *testing.T) { | |||
| 633 | + | repo, tag := splitRepoTag(tt.input) | |||
| 634 | + | assert.Equal(t, tt.wantRepo, repo) | |||
| 635 | + | assert.Equal(t, tt.wantTag, tag) | |||
| 636 | + | }) | |||
| 637 | + | } | |||
| 638 | + | } | |||
| 639 | + | ||||
| 617 | var _ pkgruntime.Runtime = (*fakeRuntime)(nil) | 640 | var _ pkgruntime.Runtime = (*fakeRuntime)(nil) | ||