Skip to content

Commit

Permalink
fix(datasource/docker): use digest from header if available (#29065)
Browse files Browse the repository at this point in the history
  • Loading branch information
viceice committed May 14, 2024
1 parent 91e8a86 commit 3bcafbb
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 15 deletions.
77 changes: 77 additions & 0 deletions lib/modules/datasource/docker/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,83 @@ describe('modules/datasource/docker/index', () => {
);
});

it('supports architecture-specific digest whithout manifest list', async () => {
const currentDigest =
'sha256:81c09f6d42c2db8121bcd759565ea244cedc759f36a0f090ec7da9de4f7f8fe4';

httpMock
.scope(authUrl)
.get(
'/token?service=registry.docker.io&scope=repository:library/some-dep:pull',
)
.times(4)
.reply(200, { token: 'some-token' });
httpMock
.scope(baseUrl)
.get('/')
.times(3)
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/some-dep:pull"',
})
.head('/library/some-dep/manifests/' + currentDigest)
.reply(200, '', {
'content-type':
'application/vnd.docker.distribution.manifest.v2+json',
})
.get('/library/some-dep/manifests/' + currentDigest)
.reply(200, {
schemaVersion: 2,
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
config: {
digest: 'some-config-digest',
mediaType: 'application/vnd.docker.container.image.v1+json',
},
})
.get('/library/some-dep/blobs/some-config-digest')
.reply(200, {
architecture: 'amd64',
});
httpMock
.scope(baseUrl)
.get('/')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/some-dep:pull"',
})
.get('/library/some-dep/manifests/some-new-value')
.reply(
200,
{
schemaVersion: 2,
mediaType: 'application/vnd.docker.distribution.manifest.v2+json',
config: {
mediaType: 'application/vnd.docker.container.image.v1+json',
size: 2917,
digest:
'sha256:4591c431eb2fcf90ebb32476db6cfe342617fc3d3ca9653b9e0c47859cac1cf9',
},
},
{
'docker-content-digest': 'some-new-digest',
},
);

const res = await getDigest(
{
datasource: 'docker',
packageName: 'some-dep',
currentDigest,
},
'some-new-value',
);

expect(logger.logger.debug).toHaveBeenCalledWith(
`Current digest ${currentDigest} relates to architecture amd64`,
);
expect(res).toBe('some-new-digest');
});

it('handles missing architecture-specific digest', async () => {
const currentDigest =
'sha256:81c09f6d42c2db8121bcd759565ea244cedc759f36a0f090ec7da9de4f7f8fe4';
Expand Down
59 changes: 44 additions & 15 deletions lib/modules/datasource/docker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,14 @@ export class DockerDatasource extends Datasource {
const parsed = ManifestJson.safeParse(manifestResponse.body);
if (!parsed.success) {
logger.debug(
{ registry, dockerRepository, tag, err: parsed.error },
{
registry,
dockerRepository,
tag,
body: manifestResponse.body,
headers: manifestResponse.headers,
err: parsed.error,
},
'Invalid manifest response',
);
return null;
Expand Down Expand Up @@ -856,23 +863,45 @@ export class DockerDatasource extends Datasource {
);

if (architecture && manifestResponse) {
const parse = ManifestJson.safeParse(manifestResponse.body);
const manifestList = parse.success
? parse.data
: /* istanbul ignore next: hard to test */ null;
if (
manifestList &&
(manifestList.mediaType ===
'application/vnd.docker.distribution.manifest.list.v2+json' ||
const parsed = ManifestJson.safeParse(manifestResponse.body);
/* istanbul ignore else: hard to test */
if (parsed.success) {
const manifestList = parsed.data;
if (
manifestList.mediaType ===
'application/vnd.oci.image.index.v1+json')
) {
for (const manifest of manifestList.manifests) {
if (manifest.platform?.architecture === architecture) {
digest = manifest.digest;
break;
'application/vnd.docker.distribution.manifest.list.v2+json' ||
manifestList.mediaType ===
'application/vnd.oci.image.index.v1+json'
) {
for (const manifest of manifestList.manifests) {
if (manifest.platform?.architecture === architecture) {
digest = manifest.digest;
break;
}
}
// TODO: return null if no matching architecture digest found
// https://github.com/renovatebot/renovate/discussions/22639
} else if (
hasKey('docker-content-digest', manifestResponse.headers)
) {
// TODO: return null if no matching architecture, requires to fetch the config manifest
// https://github.com/renovatebot/renovate/discussions/22639
digest = manifestResponse.headers[
'docker-content-digest'
] as string;
}
} else {
logger.debug(
{
registryHost,
dockerRepository,
newTag,
body: manifestResponse.body,
headers: manifestResponse.headers,
err: parsed.error,
},
'Failed to parse manifest response',
);
}
}

Expand Down

0 comments on commit 3bcafbb

Please sign in to comment.