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(sbt): Decouple sbt-package and sbt-plugin datasources #31835

Merged
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion lib/modules/datasource/sbt-package/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
import { extractPageLinks, getLatestVersion } from './util';

export class SbtPackageDatasource extends MavenDatasource {
static override id = 'sbt-package';
static override readonly id = 'sbt-package';

override readonly defaultRegistryUrls = [MAVEN_REPO];

Expand Down
137 changes: 130 additions & 7 deletions lib/modules/datasource/sbt-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { XmlDocument } from 'xmldoc';
import { logger } from '../../../logger';
import { Http } from '../../../util/http';
import { regEx } from '../../../util/regex';
import { ensureTrailingSlash } from '../../../util/url';
import * as ivyVersioning from '../../versioning/ivy';
import { compare } from '../../versioning/maven/compare';
import { Datasource } from '../datasource';
import { MAVEN_REPO } from '../maven/common';
import { downloadHttpProtocol } from '../maven/util';
import { SbtPackageDatasource } from '../sbt-package';
import { extractPageLinks, getLatestVersion } from '../sbt-package/util';
import type {
GetReleasesConfig,
Expand All @@ -17,17 +18,15 @@ import type {
export const SBT_PLUGINS_REPO =
'https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases';

export const defaultRegistryUrls = [SBT_PLUGINS_REPO, MAVEN_REPO];
export class SbtPluginDatasource extends Datasource {
static readonly id = 'sbt-plugin';

export class SbtPluginDatasource extends SbtPackageDatasource {
static override readonly id = 'sbt-plugin';
override readonly defaultRegistryUrls = [SBT_PLUGINS_REPO, MAVEN_REPO];

override readonly defaultRegistryUrls = defaultRegistryUrls;
override readonly defaultVersioning = ivyVersioning.id;

override readonly registryStrategy: RegistryStrategy = 'merge';

override readonly defaultVersioning = ivyVersioning.id;

override readonly sourceUrlSupport = 'package';
override readonly sourceUrlNote =
'The source URL is determined from the `scm` tags in the results.';
Expand All @@ -37,6 +36,130 @@ export class SbtPluginDatasource extends SbtPackageDatasource {
this.http = new Http('sbt');
}

// istanbul ignore next: to be rewritten
async getArtifactSubdirs(
searchRoot: string,
artifact: string,
scalaVersion: string,
): Promise<string[] | null> {
const pkgUrl = ensureTrailingSlash(searchRoot);
const res = await downloadHttpProtocol(this.http, pkgUrl);
const indexContent = res?.body;
if (indexContent) {
const rootPath = new URL(pkgUrl).pathname;
let artifactSubdirs = extractPageLinks(indexContent, (href) => {
const path = href.replace(rootPath, '');
if (
path.startsWith(`${artifact}_native`) ||
path.startsWith(`${artifact}_sjs`)
) {
return null;
}

if (path === artifact || path.startsWith(`${artifact}_`)) {
return path;
}

return null;
});

if (
scalaVersion &&
artifactSubdirs.includes(`${artifact}_${scalaVersion}`)
) {
artifactSubdirs = [`${artifact}_${scalaVersion}`];
}
return artifactSubdirs;
}

return null;
}

// istanbul ignore next: to be rewritten
async getPackageReleases(
searchRoot: string,
artifactSubdirs: string[] | null,
): Promise<string[] | null> {
if (artifactSubdirs) {
const releases: string[] = [];
for (const searchSubdir of artifactSubdirs) {
const pkgUrl = ensureTrailingSlash(`${searchRoot}/${searchSubdir}`);
const res = await downloadHttpProtocol(this.http, pkgUrl);
const content = res?.body;
if (content) {
const rootPath = new URL(pkgUrl).pathname;
const subdirReleases = extractPageLinks(content, (href) => {
const path = href.replace(rootPath, '');
if (path.startsWith('.')) {
return null;
}

return path;
});

subdirReleases.forEach((x) => releases.push(x));
}
}
if (releases.length) {
return [...new Set(releases)].sort(compare);
}
}

return null;
}

// istanbul ignore next: to be rewritten
async getUrls(
searchRoot: string,
artifactDirs: string[] | null,
version: string | null,
): Promise<Partial<ReleaseResult>> {
const result: Partial<ReleaseResult> = {};

if (!artifactDirs?.length) {
return result;
}

if (!version) {
return result;
}

for (const artifactDir of artifactDirs) {
const [artifact] = artifactDir.split('_');
const pomFileNames = [
`${artifactDir}-${version}.pom`,
`${artifact}-${version}.pom`,
];

for (const pomFileName of pomFileNames) {
const pomUrl = `${searchRoot}/${artifactDir}/${version}/${pomFileName}`;
const res = await downloadHttpProtocol(this.http, pomUrl);
const content = res?.body;
if (content) {
const pomXml = new XmlDocument(content);

const homepage = pomXml.valueWithPath('url');
if (homepage) {
result.homepage = homepage;
}

const sourceUrl = pomXml.valueWithPath('scm.url');
if (sourceUrl) {
result.sourceUrl = sourceUrl
.replace(regEx(/^scm:/), '')
.replace(regEx(/^git:/), '')
.replace(regEx(/^[email protected]:/), 'https://github.com/')
.replace(regEx(/\.git$/), '');
}

return result;
}
}
}

return result;
}

async resolvePluginReleases(
rootUrl: string,
artifact: string,
Expand Down