|
6 | 6 | isSensitiveKey, |
7 | 7 | redactContainerRuntimeEnv, |
8 | 8 | redactContainersRuntimeEnv, |
| 9 | + resolveContainerImageFullName, |
9 | 10 | } from './shared.js'; |
10 | 11 |
|
11 | 12 | describe('api/container/shared', () => { |
@@ -231,4 +232,74 @@ describe('api/container/shared', () => { |
231 | 232 | expect(descriptor?.enumerable).toBe(false); |
232 | 233 | }); |
233 | 234 | }); |
| 235 | + |
| 236 | + describe('resolveContainerImageFullName', () => { |
| 237 | + function makeContainer( |
| 238 | + registryName: string, |
| 239 | + registryUrl: string, |
| 240 | + imageName: string, |
| 241 | + tagValue: string, |
| 242 | + ) { |
| 243 | + return { |
| 244 | + image: { |
| 245 | + registry: { name: registryName, url: registryUrl }, |
| 246 | + name: imageName, |
| 247 | + tag: { value: tagValue }, |
| 248 | + }, |
| 249 | + } as never; |
| 250 | + } |
| 251 | + |
| 252 | + test('normalizes a Docker Hub v2 API base URL in the fallback branch (issue #374 regression guard)', () => { |
| 253 | + const container = makeContainer( |
| 254 | + 'hub', |
| 255 | + 'https://registry-1.docker.io/v2', |
| 256 | + 'dgtlmoon/sockpuppetbrowser', |
| 257 | + '0.0.3', |
| 258 | + ); |
| 259 | + const result = resolveContainerImageFullName(container, {}); |
| 260 | + expect(result).toBe('registry-1.docker.io/dgtlmoon/sockpuppetbrowser:0.0.3'); |
| 261 | + expect(result.startsWith('https://')).toBe(false); |
| 262 | + expect(result).not.toContain('/v2/'); |
| 263 | + }); |
| 264 | + |
| 265 | + test('normalizes a ghcr.io v2 API base URL in the fallback branch', () => { |
| 266 | + const container = makeContainer( |
| 267 | + 'ghcr', |
| 268 | + 'https://ghcr.io/v2', |
| 269 | + 'codeswhat/drydock', |
| 270 | + '1.5.0-rc.22', |
| 271 | + ); |
| 272 | + const result = resolveContainerImageFullName(container, {}); |
| 273 | + expect(result).toBe('ghcr.io/codeswhat/drydock:1.5.0-rc.22'); |
| 274 | + }); |
| 275 | + |
| 276 | + test('leaves a plain registry host unchanged in the fallback branch', () => { |
| 277 | + const container = makeContainer('hub', 'fallback-registry', 'test/app', '1.2.3'); |
| 278 | + const result = resolveContainerImageFullName(container, {}); |
| 279 | + expect(result).toBe('fallback-registry/test/app:1.2.3'); |
| 280 | + }); |
| 281 | + |
| 282 | + test('uses an @ separator when the tag override is a digest', () => { |
| 283 | + const container = makeContainer('ghcr', 'https://ghcr.io/v2', 'codeswhat/drydock', '1.0.0'); |
| 284 | + const result = resolveContainerImageFullName(container, {}, 'sha256:abc123'); |
| 285 | + expect(result).toBe('ghcr.io/codeswhat/drydock@sha256:abc123'); |
| 286 | + }); |
| 287 | + |
| 288 | + test("delegates to the registry component's getImageFullName when available", () => { |
| 289 | + const container = makeContainer( |
| 290 | + 'hub', |
| 291 | + 'https://registry-1.docker.io/v2', |
| 292 | + 'library/nginx', |
| 293 | + '1.25', |
| 294 | + ); |
| 295 | + const registryState = { |
| 296 | + hub: { |
| 297 | + getImageFullName: (image: { name: string }, tag: string) => |
| 298 | + `resolved:${image.name}:${tag}`, |
| 299 | + }, |
| 300 | + }; |
| 301 | + const result = resolveContainerImageFullName(container, registryState as never); |
| 302 | + expect(result).toBe('resolved:library/nginx:1.25'); |
| 303 | + }); |
| 304 | + }); |
234 | 305 | }); |
0 commit comments