renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
232 lines • 10.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SbtPackageDatasource = void 0;
const tslib_1 = require("tslib");
const upath_1 = tslib_1.__importDefault(require("upath"));
const xmldoc_1 = require("xmldoc");
const logger_1 = require("../../../logger");
const packageCache = tslib_1.__importStar(require("../../../util/cache/package"));
const decorator_1 = require("../../../util/cache/package/decorator");
const http_1 = require("../../../util/http");
const regex_1 = require("../../../util/regex");
const timestamp_1 = require("../../../util/timestamp");
const url_1 = require("../../../util/url");
const ivyVersioning = tslib_1.__importStar(require("../../versioning/ivy"));
const compare_1 = require("../../versioning/maven/compare");
const maven_1 = require("../maven");
const common_1 = require("../maven/common");
const util_1 = require("../maven/util");
const util_2 = require("./util");
class SbtPackageDatasource extends maven_1.MavenDatasource {
static id = 'sbt-package';
defaultRegistryUrls = [common_1.MAVEN_REPO];
defaultVersioning = ivyVersioning.id;
registryStrategy = 'hunt';
sourceUrlSupport = 'package';
sourceUrlNote = 'The source URL is determined from the `scm` tags in the results.';
constructor(id = SbtPackageDatasource.id) {
super(id);
this.http = new http_1.Http('sbt');
}
static parseDepCoordinate(packageName) {
const [groupId, javaArtifactId] = packageName.split(':');
const [artifactId, scalaVersion] = javaArtifactId.split('_');
return { groupId, artifactId, scalaVersion };
}
async getSbtReleases(registryUrl, packageName) {
const { groupId, artifactId, scalaVersion } = SbtPackageDatasource.parseDepCoordinate(packageName);
const groupIdSplit = groupId.split('.');
const repoRootUrl = (0, url_1.ensureTrailingSlash)(registryUrl);
const validRootUrlKey = `valid-root-url:${registryUrl}:${packageName}`;
const validRootUrl = await packageCache.get('datasource-sbt-package', validRootUrlKey);
const packageRootUrls = [];
// istanbul ignore if: not easily testable
if (validRootUrl) {
packageRootUrls.push(validRootUrl);
}
else {
const packageRootUrlWith = (sep) => `${repoRootUrl}${groupIdSplit.join(sep)}`;
packageRootUrls.push((0, url_1.ensureTrailingSlash)(packageRootUrlWith('/')));
packageRootUrls.push((0, url_1.ensureTrailingSlash)(packageRootUrlWith('.')));
}
let dependencyUrl;
let packageUrls;
for (const packageRootUrl of packageRootUrls) {
const packageRootContent = await (0, util_1.downloadHttpContent)(this.http, packageRootUrl);
if (!packageRootContent) {
continue;
}
await packageCache.set('datasource-sbt-package', validRootUrlKey, packageRootUrl, 30 * 24 * 60);
dependencyUrl = (0, url_1.trimTrailingSlash)(packageRootUrl);
const rootPath = new URL(packageRootUrl).pathname;
const artifactSubdirs = (0, util_2.extractPageLinks)(packageRootContent, (href) => {
const path = href.replace(rootPath, '');
if (path.startsWith(`${artifactId}_native`) ||
path.startsWith(`${artifactId}_sjs`)) {
return null;
}
if (path === artifactId || path.startsWith(`${artifactId}_`)) {
return (0, url_1.ensureTrailingSlash)(`${packageRootUrl}${path}`);
}
return null;
});
if (scalaVersion) {
const scalaSubdir = artifactSubdirs.find((x) => x.endsWith(`/${artifactId}_${scalaVersion}/`));
if (scalaSubdir) {
packageUrls = [scalaSubdir];
break;
}
}
packageUrls = artifactSubdirs;
break;
}
if (!packageUrls) {
return null;
}
const invalidPackageUrlsKey = `invalid-package-urls:${registryUrl}:${packageName}`;
const invalidPackageUrls = new Set(await packageCache.get('datasource-sbt-package', invalidPackageUrlsKey));
packageUrls = packageUrls.filter((url) => !invalidPackageUrls.has(url));
const allVersions = new Set();
for (const pkgUrl of packageUrls) {
const packageContent = await (0, util_1.downloadHttpContent)(this.http, pkgUrl);
// istanbul ignore if
if (!packageContent) {
invalidPackageUrls.add(pkgUrl);
continue;
}
const rootPath = new URL(pkgUrl).pathname;
const versions = (0, util_2.extractPageLinks)(packageContent, (href) => {
const path = href.replace(rootPath, '');
if (path.startsWith('.')) {
return null;
}
return path;
});
for (const version of versions) {
allVersions.add(version);
}
}
if (invalidPackageUrls.size > 0) {
await packageCache.set('datasource-sbt-package', invalidPackageUrlsKey, [...invalidPackageUrls], 30 * 24 * 60);
}
if (packageUrls.length > 0) {
const packageUrlsKey = `package-urls:${registryUrl}:${packageName}`;
await packageCache.set('datasource-sbt-package', packageUrlsKey, packageUrls, 30 * 24 * 60);
}
const versions = [...allVersions];
if (!versions.length) {
return null;
}
const releases = [...allVersions]
.sort(compare_1.compare)
.map((version) => ({ version }));
const res = { releases, dependencyUrl };
const latestVersion = (0, util_2.getLatestVersion)(versions);
const pomInfo = await this.getPomInfo(registryUrl, packageName, latestVersion, packageUrls);
if (pomInfo?.homepage) {
res.homepage = pomInfo.homepage;
}
if (pomInfo?.sourceUrl) {
res.sourceUrl = pomInfo.sourceUrl;
}
return res;
}
async getPomInfo(registryUrl, packageName, version, pkgUrls) {
const packageUrlsKey = `package-urls:${registryUrl}:${packageName}`;
// istanbul ignore next: will be covered later
const packageUrls = pkgUrls ??
(await packageCache.get('datasource-sbt-package', packageUrlsKey));
// istanbul ignore if
if (!packageUrls?.length) {
return null;
}
// istanbul ignore if
if (!version) {
return null;
}
const invalidPomFilesKey = `invalid-pom-files:${registryUrl}:${packageName}:${version}`;
const invalidPomFiles = new Set(await packageCache.get('datasource-sbt-package', invalidPomFilesKey));
const saveCache = async () => {
if (invalidPomFiles.size > 0) {
await packageCache.set('datasource-sbt-package', invalidPomFilesKey, [...invalidPomFiles], 30 * 24 * 60);
}
};
for (const packageUrl of packageUrls) {
const artifactDir = upath_1.default.basename(packageUrl);
const [artifact] = artifactDir.split('_');
for (const pomFilePrefix of [artifactDir, artifact]) {
const pomFileName = `${pomFilePrefix}-${version}.pom`;
const pomUrl = `${packageUrl}${version}/${pomFileName}`;
if (invalidPomFiles.has(pomUrl)) {
continue;
}
const res = await (0, util_1.downloadHttpProtocol)(this.http, pomUrl);
const { val } = res.unwrap();
if (!val) {
invalidPomFiles.add(pomUrl);
continue;
}
const result = {};
const releaseTimestamp = (0, timestamp_1.asTimestamp)(val.lastModified);
if (releaseTimestamp) {
result.releaseTimestamp = releaseTimestamp;
}
const pomXml = new xmldoc_1.XmlDocument(val.data);
const homepage = pomXml.valueWithPath('url');
if (homepage) {
result.homepage = homepage;
}
const sourceUrl = pomXml.valueWithPath('scm.url');
if (sourceUrl) {
result.sourceUrl = sourceUrl
.replace((0, regex_1.regEx)(/^scm:/), '')
.replace((0, regex_1.regEx)(/^git:/), '')
.replace((0, regex_1.regEx)(/^git@github.com:/), 'https://github.com/')
.replace((0, regex_1.regEx)(/\.git$/), '');
}
await saveCache();
return result;
}
}
await saveCache();
return null;
}
async getReleases(config) {
const { packageName, registryUrl } = config;
// istanbul ignore if
if (!registryUrl) {
return null;
}
const sbtReleases = await this.getSbtReleases(registryUrl, packageName);
if (sbtReleases) {
return sbtReleases;
}
logger_1.logger.debug(`Sbt: no versions discovered for ${packageName} listing organization root package folder, fallback to maven datasource for version discovery`);
const mavenReleaseResult = await super.getReleases(config);
if (mavenReleaseResult) {
return mavenReleaseResult;
}
logger_1.logger.debug(`Sbt: no versions found for "${packageName}"`);
return null;
}
async postprocessRelease(config, release) {
/* v8 ignore next 3 -- should never happen */
if (!config.registryUrl) {
return release;
}
const res = await this.getPomInfo(config.registryUrl, config.packageName, release.version);
if (res?.releaseTimestamp) {
release.releaseTimestamp = res.releaseTimestamp;
}
return release;
}
}
exports.SbtPackageDatasource = SbtPackageDatasource;
tslib_1.__decorate([
(0, decorator_1.cache)({
namespace: 'datasource-sbt-package',
key: ({ registryUrl, packageName }, { version }) => `postprocessRelease:${registryUrl}:${packageName}:${version}`,
ttlMinutes: 30 * 24 * 60,
})
], SbtPackageDatasource.prototype, "postprocessRelease", null);
//# sourceMappingURL=index.js.map