fd3783cc8d
+ added test coverage
48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
type Tag = {
|
|
name: string;
|
|
digest: string;
|
|
};
|
|
|
|
class DockerHub {
|
|
getLatestVersions = async (imageName: string): Promise<string[]> => {
|
|
const imagePath = imageName.includes("/")
|
|
? imageName
|
|
: `library/${imageName}`;
|
|
|
|
const tagsResponse = await this.fetch(
|
|
`/${imagePath}/tags?page_size=10&ordering=last_updated`
|
|
).then((res) => res.json());
|
|
|
|
const tags: Tag[] = tagsResponse.results;
|
|
if (tags.length === 0) {
|
|
throw new Error(`No tags found for ${imageName}`);
|
|
}
|
|
|
|
const latestTag = tags.find((tag) => tag.name === "latest");
|
|
if (!latestTag) {
|
|
return [];
|
|
}
|
|
|
|
const latestTags = tags
|
|
.filter((tag) => tag.digest === latestTag.digest)
|
|
.map((tag) => tag.name);
|
|
|
|
// Example: "1.0.0-alpine" is a variant of "1.0.0"
|
|
const isVariant = (tag: Tag) => {
|
|
return latestTags.some((latestTag) => tag.name.includes(latestTag + "-"));
|
|
};
|
|
return latestTags
|
|
.concat(tags.filter(isVariant).map((tag) => tag.name))
|
|
.map((tag) => `${imageName}:${tag}`)
|
|
.sort();
|
|
};
|
|
|
|
private fetch = async (url: string): Promise<Response> => {
|
|
const fullUrl = `https://hub.docker.com/v2/repositories${url}`;
|
|
console.debug("-> Docker: Fetching", fullUrl);
|
|
return fetch(fullUrl);
|
|
};
|
|
}
|
|
|
|
export default DockerHub;
|