mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 02:00:10 +00:00
9717259ffc
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if as errors in .oxlintrc.json and fix all 131 pre-existing violations (91 no-else-return, 40 unicorn/no-lonely-if) across 98 files. The no-else-return violations were fixed with the oxlint autofix (iterated to a fixpoint, plus two else-if chains that required --fix-dangerously) followed by Prettier formatting. One comment dropped by the autofix in lib/modules/manager/pub/artifacts.ts was restored manually. The unicorn/no-lonely-if violations were merged by hand, preserving comments and coverage-ignore hints. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
186 lines
5.7 KiB
TypeScript
186 lines
5.7 KiB
TypeScript
import { isTruthy } from '@sindresorhus/is';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { withCache } from '../../../util/cache/package/with-cache.ts';
|
|
import { HttpError } from '../../../util/http/index.ts';
|
|
import * as p from '../../../util/promises.ts';
|
|
import { regEx } from '../../../util/regex.ts';
|
|
import { ensureTrailingSlash, joinUrlParts } from '../../../util/url.ts';
|
|
import * as pep440Versioning from '../../versioning/pep440/index.ts';
|
|
import { Datasource } from '../datasource.ts';
|
|
import type { GetReleasesConfig, Release, ReleaseResult } from '../types.ts';
|
|
import {
|
|
GalaxyV3,
|
|
GalaxyV3DetailedVersion,
|
|
GalaxyV3Versions,
|
|
} from './schema.ts';
|
|
|
|
const ansibleProtocolRegex = regEx(/^\S+\/api\/ansible\/.+/);
|
|
const repositoryRegex = regEx(
|
|
/^\S+\/api\/galaxy\/content\/(?<repository>[^/]+)/,
|
|
);
|
|
|
|
export class GalaxyCollectionDatasource extends Datasource {
|
|
static readonly id = 'galaxy-collection';
|
|
|
|
constructor() {
|
|
super(GalaxyCollectionDatasource.id);
|
|
}
|
|
|
|
override readonly customRegistrySupport = true;
|
|
|
|
override readonly registryStrategy = 'hunt';
|
|
|
|
override readonly defaultRegistryUrls = ['https://galaxy.ansible.com/api/'];
|
|
|
|
override readonly defaultVersioning = pep440Versioning.id;
|
|
|
|
override readonly releaseTimestampSupport = true;
|
|
override releaseTimestampNote =
|
|
'The release timestamp is determined from the `created_at` field in the results.';
|
|
// sourceUrl is returned in each release as well as the ReleaseResult
|
|
// the one present in release result is the sourceUrl of the latest release
|
|
override readonly sourceUrlSupport = 'release';
|
|
override readonly sourceUrlNote =
|
|
'The `sourceUrl` is determined from the `repository` field in the results.';
|
|
|
|
private async _getReleases({
|
|
packageName,
|
|
registryUrl,
|
|
}: GetReleasesConfig): Promise<ReleaseResult | null> {
|
|
const baseUrl = this.constructBaseUrl(registryUrl!, packageName);
|
|
|
|
const { val: baseProject, err: baseErr } = await this.http
|
|
.getJsonSafe(baseUrl, GalaxyV3)
|
|
.onError((err) => {
|
|
if (!(err instanceof HttpError && err.response?.statusCode === 404)) {
|
|
logger.warn(
|
|
{ url: baseUrl, datasource: this.id, packageName, err },
|
|
'Error fetching from url',
|
|
);
|
|
}
|
|
})
|
|
.unwrap();
|
|
if (baseErr) {
|
|
this.handleGenericErrors(baseErr);
|
|
}
|
|
|
|
const versionsUrl = ensureTrailingSlash(joinUrlParts(baseUrl, 'versions'));
|
|
|
|
const { val: rawReleases, err: versionsErr } = await this.http
|
|
.getJsonSafe(versionsUrl, GalaxyV3Versions)
|
|
.onError((err) => {
|
|
logger.warn(
|
|
{ url: versionsUrl, datasource: this.id, packageName, err },
|
|
'Error fetching from url',
|
|
);
|
|
})
|
|
.unwrap();
|
|
if (versionsErr) {
|
|
this.handleGenericErrors(versionsErr);
|
|
}
|
|
|
|
const releases = rawReleases.map((value) => {
|
|
return {
|
|
...value,
|
|
isDeprecated: baseProject.deprecated,
|
|
};
|
|
});
|
|
|
|
// asynchronously get release details
|
|
const enrichedReleases = await p.map(
|
|
releases,
|
|
(release) => this.getVersionDetails(packageName, versionsUrl, release),
|
|
{ concurrency: 4 },
|
|
);
|
|
|
|
// filter failed versions
|
|
const filteredReleases = enrichedReleases.filter(isTruthy);
|
|
// extract base information which are only provided on the release from the newest release
|
|
|
|
// Find the source URL of the highest version release
|
|
const sourceUrlOfHighestRelease = enrichedReleases.find(
|
|
(release) => baseProject.highest_version.version === release.version,
|
|
)?.sourceUrl;
|
|
|
|
return {
|
|
releases: filteredReleases,
|
|
sourceUrl: sourceUrlOfHighestRelease,
|
|
};
|
|
}
|
|
|
|
getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {
|
|
return withCache(
|
|
{
|
|
namespace: `datasource-${GalaxyCollectionDatasource.id}`,
|
|
key: `getReleases:${config.packageName}`,
|
|
fallback: true,
|
|
},
|
|
() => this._getReleases(config),
|
|
);
|
|
}
|
|
|
|
constructBaseUrl(registryUrl: string, packageName: string): string {
|
|
const [namespace, projectName] = packageName.split('.');
|
|
if (ansibleProtocolRegex.test(registryUrl)) {
|
|
return ensureTrailingSlash(
|
|
joinUrlParts(registryUrl, 'api/v3/collections', namespace, projectName),
|
|
);
|
|
}
|
|
const repository =
|
|
repositoryRegex.exec(registryUrl)?.groups?.repository ?? 'published';
|
|
return ensureTrailingSlash(
|
|
joinUrlParts(
|
|
registryUrl,
|
|
'v3/plugin/ansible/content',
|
|
repository,
|
|
'collections/index',
|
|
namespace,
|
|
projectName,
|
|
),
|
|
);
|
|
}
|
|
|
|
private async _getVersionDetails(
|
|
packageName: string,
|
|
versionsUrl: string,
|
|
basicRelease: Release,
|
|
): Promise<Release> {
|
|
const detailedVersionUrl = ensureTrailingSlash(
|
|
joinUrlParts(versionsUrl, basicRelease.version),
|
|
);
|
|
const { val: rawDetailedVersion, err: versionsErr } = await this.http
|
|
.getJsonSafe(detailedVersionUrl, GalaxyV3DetailedVersion)
|
|
.onError((err) => {
|
|
logger.warn(
|
|
{ url: versionsUrl, datasource: this.id, packageName, err },
|
|
'Error fetching from url',
|
|
);
|
|
})
|
|
.unwrap();
|
|
if (versionsErr) {
|
|
this.handleGenericErrors(versionsErr);
|
|
}
|
|
|
|
return {
|
|
...rawDetailedVersion,
|
|
isDeprecated: basicRelease.isDeprecated,
|
|
releaseTimestamp: basicRelease.releaseTimestamp,
|
|
};
|
|
}
|
|
|
|
getVersionDetails(
|
|
packageName: string,
|
|
versionsUrl: string,
|
|
basicRelease: Release,
|
|
): Promise<Release> {
|
|
return withCache(
|
|
{
|
|
namespace: `datasource-${GalaxyCollectionDatasource.id}`,
|
|
key: `getVersionDetails:${versionsUrl}:${basicRelease.version}`,
|
|
ttlMinutes: 10080, // 1 week
|
|
},
|
|
() => this._getVersionDetails(packageName, versionsUrl, basicRelease),
|
|
);
|
|
}
|
|
}
|