Compact container image names

This commit is contained in:
rcourtman 2026-05-19 15:41:34 +01:00
parent 00b98cf08e
commit 4d11449cd8
4 changed files with 16 additions and 15 deletions

View file

@ -263,6 +263,10 @@ regression protection.
Docker, Podman, and future container runtimes keep the same identity tones
across Workloads, Docker, and infrastructure surfaces without adding
per-row styling branches to the hot path.
App-container image cells must use the shared compact image formatter to
show the image leaf plus tag/version while preserving the full registry and
namespace reference in tooltip/detail metadata; table rows should optimize
for container/version scanning, not registry path inspection.
11. Extend workload drawer derivations and runtime wiring through `frontend-modern/src/components/Workloads/guestDrawerModel.ts` and `frontend-modern/src/components/Workloads/useGuestDrawerState.ts`, and extend drawer overview rendering through `frontend-modern/src/components/Workloads/GuestDrawerOverview.tsx`, rather than rebuilding canonical guest identity, discovery routing, or drawer-local normalization inside `frontend-modern/src/components/Workloads/GuestDrawer.tsx`
Drawer history charts belong to `frontend-modern/src/components/Workloads/GuestDrawerHistory.tsx`.
History cards must let the plot area stretch to the card height instead of

View file

@ -593,12 +593,13 @@ describe('GuestRow', () => {
guest: makeGuest({
type: 'app-container',
workloadType: 'app-container',
image: 'nginx:latest',
image: 'ghcr.io/library/nginx:latest',
}),
visibleColumnIds: ['name', 'image'],
});
// getShortImageName truncates the image
expect(screen.getByText('nginx:latest')).toBeTruthy();
const image = screen.getByText('nginx:latest');
expect(image).toBeTruthy();
expect(image.getAttribute('title')).toBe('ghcr.io/library/nginx:latest');
});
it('shows update button for app-container guests', () => {
@ -1203,8 +1204,7 @@ describe('info merged column', () => {
}),
visibleColumnIds: ['name', 'info'],
});
// getShortImageName('library/nginx:latest') returns 'library/nginx:latest' (last 2 parts)
expect(screen.getByText('library/nginx:latest')).toBeTruthy();
expect(screen.getByText('nginx:latest')).toBeTruthy();
});
it('shows namespace for pod workloads in info column', () => {

View file

@ -101,9 +101,9 @@ describe('getShortImageName', () => {
expect(getShortImageName('nginx:latest')).toBe('nginx:latest');
});
it('returns last two components for registry URLs', () => {
expect(getShortImageName('ghcr.io/owner/image:tag')).toBe('owner/image:tag');
expect(getShortImageName('docker.io/library/nginx:latest')).toBe('library/nginx:latest');
it('returns image leaf and tag for registry URLs', () => {
expect(getShortImageName('ghcr.io/owner/image:tag')).toBe('image:tag');
expect(getShortImageName('docker.io/library/nginx:latest')).toBe('nginx:latest');
});
it('strips sha256 digest', () => {
@ -111,7 +111,7 @@ describe('getShortImageName', () => {
});
it('handles complex registry paths', () => {
expect(getShortImageName('registry.example.com/foo/bar/myapp:v1.0')).toBe('bar/myapp:v1.0');
expect(getShortImageName('registry.example.com/foo/bar/myapp:v1.0')).toBe('myapp:v1.0');
});
});

View file

@ -274,18 +274,15 @@ export function formatAnomalyRatio(
}
/**
* Shorten image registry URLs to show only the last two name components (repo/name).
* e.g., "ghcr.io/rcourtman/pulse:latest" -> "rcourtman/pulse:latest"
* Shorten image registry URLs to the image leaf plus tag.
* e.g., "ghcr.io/rcourtman/pulse:latest" -> "pulse:latest"
*/
export function getShortImageName(fullImage: string | undefined): string {
if (!fullImage) return '—';
// Handle case with @sha256: digests
const cleanImage = fullImage.split('@')[0];
const parts = cleanImage.split('/');
if (parts.length >= 2) {
return parts.slice(-2).join('/');
}
return cleanImage;
return parts.at(-1) || cleanImage || '—';
}
/**