detached 8094d01

fix: strip registry domain prefix from image names in routes list

Remove configured registry domain prefix (e.g., 'reg.bnema.dev/') from
image names displayed in the routes list for cleaner output. Images from
external registries remain unchanged.
commit
8094d0190a82e67cf2570c455bc6dd3207539a44
author
brice · · 2026-01-17 14:20 UTC
parent
7db7973
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +77 -0
M internal/usecase/container/service.go +15 -0
@@ -344,6 +344,8 @@ func (s *Service) ListRoutesWithDetails(ctx context.Context) []domain.RouteInfo
344344 image = labelImage
345345 }
346346 }
347+ // Strip registry domain prefix from image for cleaner display
348+ image = s.stripRegistryPrefix(image)
347349 if networkName, err := s.runtime.GetContainerNetwork(ctx, container.ID); err == nil {
348350 network = networkName
349351 }
@@ -362,6 +364,19 @@ func (s *Service) ListRoutesWithDetails(ctx context.Context) []domain.RouteInfo
362364 return results
363365 }
364366
367+// stripRegistryPrefix removes the configured registry domain prefix from an image reference.
368+// For example, "reg.example.com/myapp:latest" becomes "myapp:latest" if registry domain is "reg.example.com".
369+func (s *Service) stripRegistryPrefix(image string) string {
370+ if s.config.RegistryDomain == "" {
371+ return image
372+ }
373+ prefix := strings.TrimSuffix(s.config.RegistryDomain, "/") + "/"
374+ if strings.HasPrefix(image, prefix) {
375+ return strings.TrimPrefix(image, prefix)
376+ }
377+ return image
378+}
379+
365380 // ListAttachments returns attachments for a domain.
366381 func (s *Service) ListAttachments(ctx context.Context, domainName string) []domain.Attachment {
367382 return s.getAttachmentsForDomain(ctx, domainName)
@@ -344,6 +344,8 @@ func (s *Service) ListRoutesWithDetails(ctx context.Context) []domain.RouteInfo
344 image = labelImage344 image = labelImage
345 }345 }
346 }346 }
347+ // Strip registry domain prefix from image for cleaner display
348+ image = s.stripRegistryPrefix(image)
347 if networkName, err := s.runtime.GetContainerNetwork(ctx, container.ID); err == nil {349 if networkName, err := s.runtime.GetContainerNetwork(ctx, container.ID); err == nil {
348 network = networkName350 network = networkName
349 }351 }
@@ -362,6 +364,19 @@ func (s *Service) ListRoutesWithDetails(ctx context.Context) []domain.RouteInfo
362 return results364 return results
363 }365 }
364 366
367+// stripRegistryPrefix removes the configured registry domain prefix from an image reference.
368+// For example, "reg.example.com/myapp:latest" becomes "myapp:latest" if registry domain is "reg.example.com".
369+func (s *Service) stripRegistryPrefix(image string) string {
370+ if s.config.RegistryDomain == "" {
371+ return image
372+ }
373+ prefix := strings.TrimSuffix(s.config.RegistryDomain, "/") + "/"
374+ if strings.HasPrefix(image, prefix) {
375+ return strings.TrimPrefix(image, prefix)
376+ }
377+ return image
378+}
379+
365 // ListAttachments returns attachments for a domain.380 // ListAttachments returns attachments for a domain.
366 func (s *Service) ListAttachments(ctx context.Context, domainName string) []domain.Attachment {381 func (s *Service) ListAttachments(ctx context.Context, domainName string) []domain.Attachment {
367 return s.getAttachmentsForDomain(ctx, domainName)382 return s.getAttachmentsForDomain(ctx, domainName)
M internal/usecase/container/service_test.go +62 -0
@@ -1056,3 +1056,65 @@ func TestService_Deploy_OrphanCleanupRemovesTrueOrphans(t *testing.T) {
10561056 assert.True(t, exists)
10571057 assert.Equal(t, "new-container", tracked.ID)
10581058 }
1059+
1060+func TestService_StripRegistryPrefix(t *testing.T) {
1061+ tests := []struct {
1062+ name string
1063+ registryDomain string
1064+ image string
1065+ expected string
1066+ }{
1067+ {
1068+ name: "strips registry prefix",
1069+ registryDomain: "reg.example.com",
1070+ image: "reg.example.com/myapp:latest",
1071+ expected: "myapp:latest",
1072+ },
1073+ {
1074+ name: "strips registry prefix with trailing slash in domain",
1075+ registryDomain: "reg.example.com/",
1076+ image: "reg.example.com/myapp:v1.0",
1077+ expected: "myapp:v1.0",
1078+ },
1079+ {
1080+ name: "preserves image without registry prefix",
1081+ registryDomain: "reg.example.com",
1082+ image: "nginx:latest",
1083+ expected: "nginx:latest",
1084+ },
1085+ {
1086+ name: "preserves image with different registry",
1087+ registryDomain: "reg.example.com",
1088+ image: "gcr.io/project/image:latest",
1089+ expected: "gcr.io/project/image:latest",
1090+ },
1091+ {
1092+ name: "handles empty registry domain",
1093+ registryDomain: "",
1094+ image: "reg.example.com/myapp:latest",
1095+ expected: "reg.example.com/myapp:latest",
1096+ },
1097+ {
1098+ name: "handles nested paths",
1099+ registryDomain: "reg.example.com",
1100+ image: "reg.example.com/org/repo/app:latest",
1101+ expected: "org/repo/app:latest",
1102+ },
1103+ }
1104+
1105+ for _, tt := range tests {
1106+ t.Run(tt.name, func(t *testing.T) {
1107+ runtime := mocks.NewMockContainerRuntime(t)
1108+ envLoader := mocks.NewMockEnvLoader(t)
1109+ eventBus := mocks.NewMockEventPublisher(t)
1110+
1111+ config := Config{
1112+ RegistryDomain: tt.registryDomain,
1113+ }
1114+ svc := NewService(runtime, envLoader, eventBus, nil, config)
1115+
1116+ result := svc.stripRegistryPrefix(tt.image)
1117+ assert.Equal(t, tt.expected, result)
1118+ })
1119+ }
1120+}
@@ -1056,3 +1056,65 @@ func TestService_Deploy_OrphanCleanupRemovesTrueOrphans(t *testing.T) {
1056 assert.True(t, exists)1056 assert.True(t, exists)
1057 assert.Equal(t, "new-container", tracked.ID)1057 assert.Equal(t, "new-container", tracked.ID)
1058 }1058 }
1059+
1060+func TestService_StripRegistryPrefix(t *testing.T) {
1061+ tests := []struct {
1062+ name string
1063+ registryDomain string
1064+ image string
1065+ expected string
1066+ }{
1067+ {
1068+ name: "strips registry prefix",
1069+ registryDomain: "reg.example.com",
1070+ image: "reg.example.com/myapp:latest",
1071+ expected: "myapp:latest",
1072+ },
1073+ {
1074+ name: "strips registry prefix with trailing slash in domain",
1075+ registryDomain: "reg.example.com/",
1076+ image: "reg.example.com/myapp:v1.0",
1077+ expected: "myapp:v1.0",
1078+ },
1079+ {
1080+ name: "preserves image without registry prefix",
1081+ registryDomain: "reg.example.com",
1082+ image: "nginx:latest",
1083+ expected: "nginx:latest",
1084+ },
1085+ {
1086+ name: "preserves image with different registry",
1087+ registryDomain: "reg.example.com",
1088+ image: "gcr.io/project/image:latest",
1089+ expected: "gcr.io/project/image:latest",
1090+ },
1091+ {
1092+ name: "handles empty registry domain",
1093+ registryDomain: "",
1094+ image: "reg.example.com/myapp:latest",
1095+ expected: "reg.example.com/myapp:latest",
1096+ },
1097+ {
1098+ name: "handles nested paths",
1099+ registryDomain: "reg.example.com",
1100+ image: "reg.example.com/org/repo/app:latest",
1101+ expected: "org/repo/app:latest",
1102+ },
1103+ }
1104+
1105+ for _, tt := range tests {
1106+ t.Run(tt.name, func(t *testing.T) {
1107+ runtime := mocks.NewMockContainerRuntime(t)
1108+ envLoader := mocks.NewMockEnvLoader(t)
1109+ eventBus := mocks.NewMockEventPublisher(t)
1110+
1111+ config := Config{
1112+ RegistryDomain: tt.registryDomain,
1113+ }
1114+ svc := NewService(runtime, envLoader, eventBus, nil, config)
1115+
1116+ result := svc.stripRegistryPrefix(tt.image)
1117+ assert.Equal(t, tt.expected, result)
1118+ })
1119+ }
1120+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close