/
index.ts
104 lines (90 loc) · 3.26 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
import { logger } from '../../../logger';
import { cache } from '../../../util/cache/package/decorator';
import { clone } from '../../../util/clone';
import { Datasource } from '../datasource';
import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
import type {
JenkinsPluginsInfoResponse,
JenkinsPluginsVersionsResponse,
} from './types';
export class JenkinsPluginsDatasource extends Datasource {
static readonly id = 'jenkins-plugins';
constructor() {
super(JenkinsPluginsDatasource.id);
}
override readonly defaultRegistryUrls = ['https://updates.jenkins.io'];
override readonly registryStrategy = 'hunt';
private static readonly packageInfoUrl =
'https://updates.jenkins.io/current/update-center.actual.json';
private static readonly packageVersionsUrl =
'https://updates.jenkins.io/current/plugin-versions.json';
async getReleases({
packageName,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const plugins = await this.getJenkinsPluginInfo();
const plugin = plugins[packageName];
if (!plugin) {
return null;
}
const result = structuredClone(plugin);
const versions = await this.getJenkinsPluginVersions();
const releases = versions[packageName];
result.releases = releases ? clone(releases) : [];
return result;
}
@cache({
namespace: JenkinsPluginsDatasource.id,
key: 'info',
ttlMinutes: 1440,
})
async getJenkinsPluginInfo(): Promise<Record<string, ReleaseResult>> {
const { plugins } =
await this.getJenkinsUpdateCenterResponse<JenkinsPluginsInfoResponse>(
JenkinsPluginsDatasource.packageInfoUrl
);
const info: Record<string, ReleaseResult> = {};
for (const name of Object.keys(plugins ?? [])) {
info[name] = {
releases: [], // releases
sourceUrl: plugins[name]?.scm,
};
}
return info;
}
@cache({ namespace: JenkinsPluginsDatasource.id, key: 'versions' })
async getJenkinsPluginVersions(): Promise<Record<string, Release[]>> {
const { plugins } =
await this.getJenkinsUpdateCenterResponse<JenkinsPluginsVersionsResponse>(
JenkinsPluginsDatasource.packageVersionsUrl
);
const versions: Record<string, Release[]> = {};
for (const name of Object.keys(plugins ?? [])) {
versions[name] = Object.keys(plugins[name]).map((version) => ({
version,
downloadUrl: plugins[name][version]?.url,
releaseTimestamp: plugins[name][version]?.buildDate
? // TODO: types (#7154)
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
new Date(`${plugins[name][version].buildDate} UTC`)
: null,
}));
}
return versions;
}
private async getJenkinsUpdateCenterResponse<T>(url: string): Promise<T> {
let response: T;
try {
logger.debug(`jenkins-plugins: Fetching Jenkins plugins from ${url}`);
const startTime = Date.now();
response = (await this.http.getJson<T>(url)).body;
const durationMs = Math.round(Date.now() - startTime);
logger.debug(
{ durationMs },
`jenkins-plugins: Fetched Jenkins plugins from ${url}`
);
} catch (err) /* istanbul ignore next */ {
this.handleGenericErrors(err);
}
return response;
}
}