Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(datasource): Simplify merge registry logic #31430

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 42 additions & 31 deletions lib/modules/datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { coerceArray } from '../../util/array';
import * as memCache from '../../util/cache/memory';
import * as packageCache from '../../util/cache/package';
import { clone } from '../../util/clone';
import { filterMap } from '../../util/filter-map';
import { AsyncResult, Result } from '../../util/result';
import { DatasourceCacheStats } from '../../util/stats';
import { trimTrailingSlash } from '../../util/url';
Expand Down Expand Up @@ -161,53 +162,63 @@ async function mergeRegistries(
registryUrls: string[],
): Promise<ReleaseResult | null> {
let combinedRes: ReleaseResult | undefined;
let caughtError: Error | undefined;
let lastErr: Error | undefined;
let commonRegistryUrl = true;
for (const registryUrl of registryUrls) {
try {
const res = await getRegistryReleases(datasource, config, registryUrl);
if (!res) {
continue;
}
if (combinedRes) {
for (const existingRelease of coerceArray(combinedRes.releases)) {
existingRelease.registryUrl ??= combinedRes.registryUrl;
}
for (const additionalRelease of coerceArray(res.releases)) {
additionalRelease.registryUrl = res.registryUrl;
}
combinedRes = { ...res, ...combinedRes };
delete combinedRes.registryUrl;
combinedRes.releases = [...combinedRes.releases, ...res.releases];
} else {

if (!combinedRes) {
combinedRes = res;
continue;
}

if (commonRegistryUrl) {
for (const release of coerceArray(combinedRes.releases)) {
release.registryUrl ??= combinedRes.registryUrl;
}
commonRegistryUrl = false;
rarkins marked this conversation as resolved.
Show resolved Hide resolved
}

const releases = coerceArray(res.releases);
for (const release of releases) {
release.registryUrl ??= res.registryUrl;
}

combinedRes.releases.push(...releases);
combinedRes = { ...res, ...combinedRes };
delete combinedRes.registryUrl;
} catch (err) {
if (err instanceof ExternalHostError) {
throw err;
}
// We'll always save the last-thrown error
caughtError = err;

lastErr = err;
logger.trace({ err }, 'datasource merge failure');
}
}
// De-duplicate releases
if (combinedRes?.releases?.length) {
const seenVersions = new Set<string>();
combinedRes.releases = combinedRes.releases.filter((release) => {
if (seenVersions.has(release.version)) {
return false;
}
seenVersions.add(release.version);
return true;
});
}
if (combinedRes) {
return combinedRes;
}
if (caughtError) {
throw caughtError;

if (!combinedRes) {
if (lastErr) {
throw lastErr;
}

return null;
}
return null;

const seenVersions = new Set<string>();
combinedRes.releases = filterMap(combinedRes.releases, (release) => {
if (seenVersions.has(release.version)) {
return null;
}
seenVersions.add(release.version);
return release;
});

return combinedRes;
}

function massageRegistryUrls(registryUrls: string[]): string[] {
Expand Down