renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
108 lines (107 loc) • 5.27 kB
JavaScript
import { logger } from "../../../logger/index.js";
import { ensureTrailingSlash } from "../../../util/url.js";
import { compare } from "../../versioning/maven/compare.js";
import api, { id } from "../../versioning/maven/index.js";
import { get, set } from "../../../util/cache/package/index.js";
import { asTimestamp } from "../../../util/timestamp.js";
import { Datasource } from "../datasource.js";
import { MAVEN_CENTRAL_URLS, MAVEN_REPO } from "./common.js";
import { createUrlForDependencyPom, downloadMaven, downloadMavenXml, getDependencyInfo, getDependencyParts, getMavenUrl } from "./util.js";
//#region lib/modules/datasource/maven/index.ts
function getLatestSuitableVersion(releases) {
/* v8 ignore next 3 -- TODO: add test */
if (!releases?.length) return null;
const allVersions = releases.map(({ version }) => version);
const stableVersions = allVersions.filter((x) => api.isStable(x));
return (stableVersions.length ? stableVersions : allVersions).reduce((latestVersion, version) => compare(version, latestVersion) === 1 ? version : /* istanbul ignore next: hard to test */ latestVersion);
}
function extractVersions(metadata) {
const res = {};
const elements = metadata.descendantWithPath("versioning.versions")?.childrenNamed("version");
if (!elements) return res;
res.versions = elements.map((el) => el.val);
const latest = metadata.descendantWithPath("versioning.latest");
if (latest?.val) {
res.tags ??= {};
res.tags.latest = latest.val;
}
const release = metadata.descendantWithPath("versioning.release");
if (release?.val) {
res.tags ??= {};
res.tags.release = release.val;
}
return res;
}
const defaultRegistryUrls = [MAVEN_REPO];
var MavenDatasource = class MavenDatasource extends Datasource {
static id = "maven";
caching = true;
defaultRegistryUrls = defaultRegistryUrls;
defaultVersioning = id;
registryStrategy = "merge";
releaseTimestampSupport = true;
releaseTimestampNote = "The release timestamp is determined from the `Last-Modified` header or the `lastModified` field in the results.";
sourceUrlSupport = "package";
sourceUrlNote = "The source URL is determined from the `scm` tags in the results.";
constructor(id = MavenDatasource.id) {
super(id);
}
async fetchVersionsFromMetadata(dependency, repoUrl) {
const metadataUrl = getMavenUrl(dependency, repoUrl, "maven-metadata.xml");
return (await downloadMavenXml(this.http, metadataUrl)).transform(({ data: metadata }) => extractVersions(metadata)).onError((err) => {
logger.debug(`Maven: error fetching versions for "${dependency.display}": ${err.type}`);
}).unwrapOr({});
}
async getReleases({ packageName, registryUrl }) {
/* v8 ignore next 3 -- should never happen */
if (!registryUrl) return null;
const dependency = getDependencyParts(packageName);
const repoUrl = ensureTrailingSlash(registryUrl);
if ((packageName.includes(".gradle.plugin:") || packageName.endsWith(".gradle.plugin")) && MAVEN_CENTRAL_URLS.some((url) => repoUrl === ensureTrailingSlash(url))) {
logger.debug(`Maven: skipping Maven Central for suspected Gradle plugin "${packageName}"`);
return null;
}
logger.debug(`Looking up ${dependency.display} in repository ${repoUrl}`);
const metadata = await this.fetchVersionsFromMetadata(dependency, repoUrl);
if (!metadata.versions?.length) return null;
const releases = metadata.versions.map((version) => ({ version }));
logger.debug(`Found ${releases.length} new releases for ${dependency.display} in repository ${repoUrl}`);
const latestSuitableVersion = getLatestSuitableVersion(releases);
const dependencyInfo = latestSuitableVersion && await getDependencyInfo(this.http, dependency, repoUrl, latestSuitableVersion);
const result = {
...dependency,
...dependencyInfo,
releases
};
if (metadata.tags) {
result.tags = metadata.tags;
if (result.tags.latest) {
logger.debug(`Setting respectLatest=false for maven ${packageName}`);
result.respectLatest = false;
}
}
if (!this.defaultRegistryUrls.includes(registryUrl)) result.isPrivate = true;
return result;
}
async postprocessRelease({ packageName, registryUrl }, release) {
const { version, versionOrig } = release;
const cacheKey = versionOrig ? `postprocessRelease:${registryUrl}:${packageName}:${versionOrig}:${version}` : `postprocessRelease:${registryUrl}:${packageName}:${version}`;
const cachedResult = await get("datasource-maven:postprocess-reject", cacheKey);
/* v8 ignore if: hard to test */
if (cachedResult) return cachedResult;
if (!packageName || !registryUrl) return release;
const dependency = getDependencyParts(packageName);
const artifactUrl = getMavenUrl(dependency, registryUrl, await createUrlForDependencyPom(this.http, release.versionOrig ?? release.version, dependency, registryUrl));
const { val, err } = (await downloadMaven(this.http, artifactUrl)).unwrap();
if (err) {
const result = err.type === "not-found" ? "reject" : release;
if (result === "reject") await set("datasource-maven:postprocess-reject", cacheKey, result, 1440);
return result;
}
if (val.lastModified) release.releaseTimestamp = asTimestamp(val.lastModified);
return release;
}
};
//#endregion
export { MavenDatasource };
//# sourceMappingURL=index.js.map