-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
index.ts
122 lines (108 loc) · 3.56 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { logger } from '../../../logger';
import { cache } from '../../../util/cache/package/decorator';
import { GithubReleasesDatasource } from '../github-releases';
import { getApiBaseUrl, getSourceUrl } from '../github-releases/common';
import type {
DigestConfig,
GetReleasesConfig,
Release,
ReleaseResult,
} from '../types';
import { CacheableGithubTags } from './cache';
export class GithubTagsDatasource extends GithubReleasesDatasource {
static override readonly id = 'github-tags';
private tagsCache: CacheableGithubTags;
constructor() {
super(GithubTagsDatasource.id);
this.tagsCache = new CacheableGithubTags(this.http);
}
async getTagCommit(
registryUrl: string | undefined,
packageName: string,
tag: string
): Promise<string | null> {
let result: string | null = null;
const tagReleases = await this.tagsCache.getItems({
packageName,
registryUrl,
});
const tagRelease = tagReleases.find(({ version }) => version === tag);
if (tagRelease) {
result = tagRelease.hash;
}
return result;
}
@cache({
ttlMinutes: 10,
namespace: `datasource-${GithubTagsDatasource.id}`,
key: (registryUrl: string, githubRepo: string) =>
`${registryUrl}:${githubRepo}:commit`,
})
async getCommit(
registryUrl: string | undefined,
githubRepo: string
): Promise<string | null> {
const apiBaseUrl = getApiBaseUrl(registryUrl);
let digest: string | null = null;
try {
const url = `${apiBaseUrl}repos/${githubRepo}/commits?per_page=1`;
const res = await this.http.getJson<{ sha: string }[]>(url);
digest = res.body[0].sha;
} catch (err) {
logger.debug(
{ githubRepo: githubRepo, err, registryUrl },
'Error getting latest commit from GitHub repo'
);
}
return digest;
}
/**
* github.getDigest
*
* The `newValue` supplied here should be a valid tag for the docker image.
*
* Returns the latest commit hash for the repository.
*/
override getDigest(
{ packageName: repo, registryUrl }: Partial<DigestConfig>,
newValue?: string
): Promise<string | null> {
return newValue
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
this.getTagCommit(registryUrl, repo!, newValue)
: // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
this.getCommit(registryUrl, repo!);
}
override async getReleases(
config: GetReleasesConfig
): Promise<ReleaseResult | null> {
const tagReleases = await this.tagsCache.getItems(config);
// istanbul ignore if
if (!tagReleases.length) {
return null;
}
const tagsResult: ReleaseResult = {
sourceUrl: getSourceUrl(config.packageName, config.registryUrl),
releases: tagReleases.map((item) => ({ ...item, gitRef: item.version })),
};
try {
// Fetch additional data from releases endpoint when possible
const releasesResult = await super.getReleases(config);
type PartialRelease = Omit<Release, 'version'>;
const releaseByVersion: Record<string, PartialRelease> = {};
releasesResult?.releases?.forEach((release) => {
const { version, ...value } = release;
releaseByVersion[version] = value;
});
const mergedReleases: Release[] = [];
tagsResult.releases.forEach((tag) => {
const release = releaseByVersion[tag.version];
mergedReleases.push({ ...release, ...tag });
});
tagsResult.releases = mergedReleases;
} catch (e) {
// no-op
}
return tagsResult;
}
}