0
0
Fork 0
mirror of https://github.com/renovatebot/renovate.git synced 2025-01-11 13:48:55 +00:00
renovatebot_renovate/lib/modules/datasource/azure-pipelines-tasks/index.ts

131 lines
3.8 KiB
TypeScript

import type { TypeOf, ZodType } from 'zod';
import { GlobalConfig } from '../../../config/global';
import { cache } from '../../../util/cache/package/decorator';
import * as hostRules from '../../../util/host-rules';
import type { HttpOptions } from '../../../util/http/types';
import { id as versioning } from '../../versioning/loose';
import { Datasource } from '../datasource';
import type { GetReleasesConfig, ReleaseResult } from '../types';
import {
AzurePipelinesFallbackTasks,
AzurePipelinesJSON,
AzurePipelinesTaskVersion,
} from './schema';
const TASKS_URL_BASE =
'https://raw.githubusercontent.com/renovatebot/azure-devops-marketplace/main';
const BUILT_IN_TASKS_URL = `${TASKS_URL_BASE}/azure-pipelines-builtin-tasks.json`;
const MARKETPLACE_TASKS_URL = `${TASKS_URL_BASE}/azure-pipelines-marketplace-tasks.json`;
export class AzurePipelinesTasksDatasource extends Datasource {
static readonly id = 'azure-pipelines-tasks';
constructor() {
super(AzurePipelinesTasksDatasource.id);
}
override readonly customRegistrySupport = false;
override readonly defaultVersioning = versioning;
async getReleases({
packageName,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const platform = GlobalConfig.get('platform');
const endpoint = GlobalConfig.get('endpoint');
const { token } = hostRules.find({
hostType: AzurePipelinesTasksDatasource.id,
url: endpoint,
});
if (platform === 'azure' && endpoint && token) {
const auth = Buffer.from(`renovate:${token}`).toString('base64');
const opts: HttpOptions = {
headers: { authorization: `Basic ${auth}` },
};
const results = await this.getTasks(
`${endpoint}/_apis/distributedtask/tasks/`,
opts,
AzurePipelinesJSON,
);
const result: ReleaseResult = { releases: [] };
results.value
.filter((task) => task.name === packageName)
.sort(AzurePipelinesTasksDatasource.compareSemanticVersions('version'))
.forEach((task) => {
result.releases.push({
version: `${task.version!.major}.${task.version!.minor}.${task.version!.patch}`,
isDeprecated: task.deprecated,
});
});
return result;
} else {
const versions =
(
await this.getTasks(
BUILT_IN_TASKS_URL,
{},
AzurePipelinesFallbackTasks,
)
)[packageName.toLowerCase()] ??
(
await this.getTasks(
MARKETPLACE_TASKS_URL,
{},
AzurePipelinesFallbackTasks,
)
)[packageName.toLowerCase()];
if (versions) {
const releases = versions.map((version) => ({ version }));
return { releases };
}
}
return null;
}
@cache({
namespace: `datasource-${AzurePipelinesTasksDatasource.id}`,
key: (url: string) => url,
ttlMinutes: 24 * 60,
})
async getTasks<ResT, Schema extends ZodType<ResT> = ZodType<ResT>>(
url: string,
opts: HttpOptions,
schema: Schema,
): Promise<TypeOf<Schema>> {
const { body } = await this.http.getJson(url, opts, schema);
return body;
}
static compareSemanticVersions = (key: string) => (a: any, b: any) => {
const a1Version = AzurePipelinesTaskVersion.safeParse(a[key]).data;
const b1Version = AzurePipelinesTaskVersion.safeParse(b[key]).data;
const a1 =
a1Version === undefined
? ''
: `${a1Version.major}.${a1Version.minor}.${a1Version.patch}`;
const b1 =
b1Version === undefined
? ''
: `${b1Version.major}.${b1Version.minor}.${b1Version.patch}`;
const len = Math.min(a1.length, b1.length);
for (let i = 0; i < len; i++) {
const a2 = +a1[i] || 0;
const b2 = +b1[i] || 0;
if (a2 !== b2) {
return a2 > b2 ? 1 : -1;
}
}
return b1.length - a1.length;
};
}