mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-13 07:26:26 +00:00
feat(docker): use Docker Hub tags api (#23876)
This commit is contained in:
parent
da7fc430ed
commit
a1f79bcf39
3 changed files with 61 additions and 16 deletions
|
@ -21,6 +21,7 @@ const ecrMock = mockClient(ECRClient);
|
|||
const baseUrl = 'https://index.docker.io/v2';
|
||||
const authUrl = 'https://auth.docker.io';
|
||||
const amazonUrl = 'https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2';
|
||||
const dockerHubUrl = 'https://hub.docker.com/v2/repositories';
|
||||
|
||||
function mockEcrAuthResolve(
|
||||
res: Partial<GetAuthorizationTokenCommandOutput> = {}
|
||||
|
@ -41,6 +42,7 @@ describe('modules/datasource/docker/index', () => {
|
|||
});
|
||||
hostRules.hosts.mockReturnValue([]);
|
||||
delete process.env.RENOVATE_X_DOCKER_MAX_PAGES;
|
||||
delete process.env.RENOVATE_X_DOCKER_HUB_TAGS;
|
||||
});
|
||||
|
||||
describe('getDigest', () => {
|
||||
|
@ -1520,7 +1522,12 @@ describe('modules/datasource/docker/index', () => {
|
|||
});
|
||||
|
||||
it('adds library/ prefix for Docker Hub (implicit)', async () => {
|
||||
process.env.RENOVATE_X_DOCKER_HUB_TAGS = 'true';
|
||||
const tags = ['1.0.0'];
|
||||
httpMock
|
||||
.scope(dockerHubUrl)
|
||||
.get('/library/node/tags?page_size=100')
|
||||
.reply(404);
|
||||
httpMock
|
||||
.scope(baseUrl)
|
||||
.get('/library/node/tags/list?n=10000')
|
||||
|
@ -1548,31 +1555,29 @@ describe('modules/datasource/docker/index', () => {
|
|||
});
|
||||
|
||||
it('adds library/ prefix for Docker Hub (explicit)', async () => {
|
||||
const tags = ['1.0.0'];
|
||||
process.env.RENOVATE_X_DOCKER_HUB_TAGS = 'true';
|
||||
httpMock
|
||||
.scope(dockerHubUrl)
|
||||
.get('/library/node/tags?page_size=100')
|
||||
.reply(200, {
|
||||
next: `${dockerHubUrl}/library/node/tags?page=2&page_size=100`,
|
||||
results: [{ name: '1.0.0' }],
|
||||
})
|
||||
.get('/library/node/tags?page=2&page_size=100')
|
||||
.reply(200, {
|
||||
results: [{ name: '0.9.0' }],
|
||||
});
|
||||
httpMock
|
||||
.scope(baseUrl)
|
||||
.get('/library/node/tags/list?n=10000')
|
||||
.reply(401, '', {
|
||||
'www-authenticate':
|
||||
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/node:pull"',
|
||||
})
|
||||
.get('/library/node/tags/list?n=10000')
|
||||
.reply(200, { tags }, {})
|
||||
.get('/')
|
||||
.reply(200)
|
||||
.get('/library/node/manifests/1.0.0')
|
||||
.reply(200);
|
||||
httpMock
|
||||
.scope(authUrl)
|
||||
.get(
|
||||
'/token?service=registry.docker.io&scope=repository:library/node:pull'
|
||||
)
|
||||
.reply(200, { token: 'test' });
|
||||
const res = await getPkgReleases({
|
||||
datasource: DockerDatasource.id,
|
||||
packageName: 'docker.io/node',
|
||||
});
|
||||
expect(res?.releases).toHaveLength(1);
|
||||
expect(res?.releases).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('adds no library/ prefix for other registries', async () => {
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
} from './common';
|
||||
import { ecrPublicRegex, ecrRegex, isECRMaxResultsError } from './ecr';
|
||||
import type { Manifest, OciImageConfig } from './schema';
|
||||
import type { DockerHubTags } from './types';
|
||||
|
||||
const defaultConfig = {
|
||||
commitMessageTopic: '{{{depName}}} Docker tag',
|
||||
|
@ -819,6 +820,36 @@ export class DockerDatasource extends Datasource {
|
|||
return digest;
|
||||
}
|
||||
|
||||
async getDockerHubTags(dockerRepository: string): Promise<string[] | null> {
|
||||
if (!process.env.RENOVATE_X_DOCKER_HUB_TAGS) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
let index = 0;
|
||||
let tags: string[] = [];
|
||||
let url:
|
||||
| string
|
||||
| undefined = `https://hub.docker.com/v2/repositories/${dockerRepository}/tags?page_size=100`;
|
||||
do {
|
||||
const res: DockerHubTags = (await this.http.getJson<DockerHubTags>(url))
|
||||
.body;
|
||||
tags = tags.concat(res.results.map((tag) => tag.name));
|
||||
url = res.next;
|
||||
index += 1;
|
||||
} while (url && index < 100);
|
||||
logger.debug(
|
||||
`getDockerHubTags(${dockerRepository}): found ${tags.length} tags`
|
||||
);
|
||||
return tags;
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
{ dockerRepository, errMessage: err.message },
|
||||
`No Docker Hub tags result - falling back to docker.io api`
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* docker.getReleases
|
||||
*
|
||||
|
@ -838,7 +869,11 @@ export class DockerDatasource extends Datasource {
|
|||
packageName,
|
||||
registryUrl!
|
||||
);
|
||||
const tags = await this.getTags(registryHost, dockerRepository);
|
||||
let tags: string[] | null = null;
|
||||
if (registryHost === 'https://index.docker.io') {
|
||||
tags = await this.getDockerHubTags(dockerRepository);
|
||||
}
|
||||
tags ??= await this.getTags(registryHost, dockerRepository);
|
||||
if (!tags) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -2,3 +2,8 @@ export interface RegistryRepository {
|
|||
registryHost: string;
|
||||
dockerRepository: string;
|
||||
}
|
||||
|
||||
export interface DockerHubTags {
|
||||
next?: string;
|
||||
results: { name: string }[];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue