mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-14 16:46:25 +00:00
feat(manager/gradle): support separate registry URLs for plugins (#19606)
This commit is contained in:
parent
3c207f8e72
commit
0fc1731eed
8 changed files with 198 additions and 22 deletions
|
@ -242,11 +242,7 @@ describe('modules/manager/gradle/extract', () => {
|
|||
deps: [
|
||||
{
|
||||
depType: 'plugin',
|
||||
registryUrls: [
|
||||
'https://repo.maven.apache.org/maven2',
|
||||
'https://example.com',
|
||||
'https://plugins.gradle.org/m2/',
|
||||
],
|
||||
registryUrls: ['https://plugins.gradle.org/m2/'],
|
||||
},
|
||||
{
|
||||
registryUrls: [
|
||||
|
@ -314,6 +310,65 @@ describe('modules/manager/gradle/extract', () => {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('supports separate registry URLs for plugins', async () => {
|
||||
const settingsFile = codeBlock`
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url = "https://foo.bar/plugins" }
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const buildFile = codeBlock`
|
||||
plugins {
|
||||
id "foo.bar" version "1.2.3"
|
||||
}
|
||||
repositories {
|
||||
maven { url = "https://foo.bar/deps" }
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "io.jsonwebtoken:jjwt-api:0.11.2"
|
||||
}
|
||||
`;
|
||||
|
||||
const fsMock = {
|
||||
'build.gradle': buildFile,
|
||||
'settings.gradle': settingsFile,
|
||||
};
|
||||
mockFs(fsMock);
|
||||
|
||||
const res = await extractAllPackageFiles(
|
||||
{} as ExtractConfig,
|
||||
Object.keys(fsMock)
|
||||
);
|
||||
|
||||
expect(res).toMatchObject([
|
||||
{
|
||||
packageFile: 'settings.gradle',
|
||||
deps: [],
|
||||
},
|
||||
{
|
||||
packageFile: 'build.gradle',
|
||||
deps: [
|
||||
{
|
||||
depName: 'foo.bar',
|
||||
depType: 'plugin',
|
||||
registryUrls: ['https://foo.bar/plugins'],
|
||||
},
|
||||
{
|
||||
depName: 'io.jsonwebtoken:jjwt-api',
|
||||
registryUrls: [
|
||||
'https://foo.bar/deps',
|
||||
'https://repo.maven.apache.org/maven2',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('version catalogs', () => {
|
||||
|
|
|
@ -10,8 +10,10 @@ import {
|
|||
usesGcv,
|
||||
} from './extract/consistent-versions-plugin';
|
||||
import { parseGradle, parseProps } from './parser';
|
||||
import { REGISTRY_URLS } from './parser/common';
|
||||
import type {
|
||||
GradleManagerData,
|
||||
PackageRegistry,
|
||||
PackageVariables,
|
||||
VariableRegistry,
|
||||
} from './types';
|
||||
|
@ -26,6 +28,23 @@ import {
|
|||
|
||||
const datasource = MavenDatasource.id;
|
||||
|
||||
function getRegistryUrlsForDep(
|
||||
packageRegistries: PackageRegistry[],
|
||||
dep: PackageDependency<GradleManagerData>
|
||||
): string[] {
|
||||
const scope = dep.depType === 'plugin' ? 'plugin' : 'dep';
|
||||
|
||||
const registryUrls = packageRegistries
|
||||
.filter((item) => item.scope === scope)
|
||||
.map((item) => item.registryUrl);
|
||||
|
||||
if (!registryUrls.length && scope === 'plugin') {
|
||||
registryUrls.push(REGISTRY_URLS.gradlePluginPortal);
|
||||
}
|
||||
|
||||
return [...new Set(registryUrls)];
|
||||
}
|
||||
|
||||
export async function extractAllPackageFiles(
|
||||
config: ExtractConfig,
|
||||
packageFiles: string[]
|
||||
|
@ -33,7 +52,7 @@ export async function extractAllPackageFiles(
|
|||
const extractedDeps: PackageDependency<GradleManagerData>[] = [];
|
||||
const varRegistry: VariableRegistry = {};
|
||||
const packageFilesByName: Record<string, PackageFile> = {};
|
||||
const packageRegistries: string[] = [];
|
||||
const packageRegistries: PackageRegistry[] = [];
|
||||
const reorderedFiles = reorderFiles(packageFiles);
|
||||
const fileContents = await getFileContentMap(packageFiles, true);
|
||||
|
||||
|
@ -75,7 +94,11 @@ export async function extractAllPackageFiles(
|
|||
vars: gradleVars,
|
||||
} = parseGradle(content, vars, packageFile, fileContents);
|
||||
for (const url of urls) {
|
||||
if (!packageRegistries.includes(url)) {
|
||||
const registryAlreadyKnown = packageRegistries.some(
|
||||
(item) =>
|
||||
item.registryUrl === url.registryUrl && item.scope === url.scope
|
||||
);
|
||||
if (!registryAlreadyKnown) {
|
||||
packageRegistries.push(url);
|
||||
}
|
||||
}
|
||||
|
@ -114,9 +137,7 @@ export async function extractAllPackageFiles(
|
|||
};
|
||||
}
|
||||
|
||||
dep.registryUrls = [
|
||||
...new Set([...packageRegistries, ...(dep.registryUrls ?? [])]),
|
||||
];
|
||||
dep.registryUrls = getRegistryUrlsForDep(packageRegistries, dep);
|
||||
|
||||
if (!dep.depType) {
|
||||
dep.depType = key.startsWith('buildSrc')
|
||||
|
|
|
@ -276,7 +276,6 @@ export function parseCatalog(
|
|||
depType: 'plugin',
|
||||
depName,
|
||||
packageName: `${depName}:${depName}.gradle.plugin`,
|
||||
registryUrls: ['https://plugins.gradle.org/m2/'],
|
||||
currentValue,
|
||||
commitMessageTopic: `plugin ${pluginName}`,
|
||||
managerData: { fileReplacePosition },
|
||||
|
|
|
@ -545,7 +545,7 @@ describe('modules/manager/gradle/parser', () => {
|
|||
${'jcenter()'} | ${REGISTRY_URLS.jcenter}
|
||||
`('$input', ({ input, output }) => {
|
||||
const { urls } = parseGradle(input);
|
||||
expect(urls).toStrictEqual([output].filter(Boolean));
|
||||
expect(urls).toMatchObject([{ registryUrl: output }]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -587,11 +587,60 @@ describe('modules/manager/gradle/parser', () => {
|
|||
${''} | ${'maven { setUrl("foo", "bar") }'} | ${null}
|
||||
${'base="https://foo.bar"'} | ${'publishing { repositories { maven("${base}/baz") } }'} | ${null}
|
||||
`('$def | $input', ({ def, input, url }) => {
|
||||
const expected = [url].filter(Boolean);
|
||||
const expected = url ? [{ registryUrl: url }] : [];
|
||||
const { urls } = parseGradle([def, input].join('\n'));
|
||||
expect(urls).toStrictEqual(expected);
|
||||
expect(urls).toMatchObject(expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('pluginManagement', () => {
|
||||
const input = codeBlock`
|
||||
pluginManagement {
|
||||
def fooVersion = "1.2.3"
|
||||
repositories {
|
||||
mavenLocal()
|
||||
maven { url = "https://foo.bar/plugins" }
|
||||
gradlePluginPortal()
|
||||
}
|
||||
plugins {
|
||||
id("foo.bar") version "$fooVersion"
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
maven { url = "https://foo.bar/deps" }
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const { deps, urls } = parseGradle(input);
|
||||
expect(deps).toMatchObject([
|
||||
{
|
||||
depType: 'plugin',
|
||||
depName: 'foo.bar',
|
||||
currentValue: '1.2.3',
|
||||
},
|
||||
]);
|
||||
expect(urls).toMatchObject([
|
||||
{
|
||||
registryUrl: 'https://foo.bar/plugins',
|
||||
scope: 'plugin',
|
||||
},
|
||||
{
|
||||
registryUrl: REGISTRY_URLS.gradlePluginPortal,
|
||||
scope: 'plugin',
|
||||
},
|
||||
{
|
||||
registryUrl: 'https://foo.bar/deps',
|
||||
scope: 'dep',
|
||||
},
|
||||
{
|
||||
registryUrl: REGISTRY_URLS.mavenCentral,
|
||||
scope: 'dep',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('version catalog', () => {
|
||||
|
|
|
@ -10,6 +10,7 @@ import { qVersionCatalogs } from './parser/version-catalogs';
|
|||
import type {
|
||||
Ctx,
|
||||
GradleManagerData,
|
||||
PackageRegistry,
|
||||
PackageVariables,
|
||||
ParseGradleResult,
|
||||
} from './types';
|
||||
|
@ -26,7 +27,7 @@ export function parseGradle(
|
|||
): ParseGradleResult {
|
||||
let vars: PackageVariables = { ...initVars };
|
||||
const deps: PackageDependency<GradleManagerData>[] = [];
|
||||
const urls: string[] = [];
|
||||
const urls: PackageRegistry[] = [];
|
||||
|
||||
const query = q.tree<Ctx>({
|
||||
type: 'root-tree',
|
||||
|
|
|
@ -216,7 +216,6 @@ export function handlePlugin(ctx: Ctx): Ctx {
|
|||
depType: 'plugin',
|
||||
depName,
|
||||
packageName,
|
||||
registryUrls: [REGISTRY_URLS.gradlePluginPortal],
|
||||
commitMessageTopic: `plugin ${depName}`,
|
||||
currentValue: pluginVersion[0].value,
|
||||
managerData: {
|
||||
|
@ -246,11 +245,22 @@ export function handlePlugin(ctx: Ctx): Ctx {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
function isPluginRegistry(ctx: Ctx): boolean {
|
||||
if (ctx.tokenMap.registryScope) {
|
||||
const registryScope = loadFromTokenMap(ctx, 'registryScope')[0].value;
|
||||
return registryScope === 'pluginManagement';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function handlePredefinedRegistryUrl(ctx: Ctx): Ctx {
|
||||
const registryName = loadFromTokenMap(ctx, 'registryUrl')[0].value;
|
||||
ctx.registryUrls.push(
|
||||
REGISTRY_URLS[registryName as keyof typeof REGISTRY_URLS]
|
||||
);
|
||||
|
||||
ctx.registryUrls.push({
|
||||
registryUrl: REGISTRY_URLS[registryName as keyof typeof REGISTRY_URLS],
|
||||
scope: isPluginRegistry(ctx) ? 'plugin' : 'dep',
|
||||
});
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
@ -281,7 +291,10 @@ export function handleCustomRegistryUrl(ctx: Ctx): Ctx {
|
|||
try {
|
||||
const { host, protocol } = url.parse(registryUrl);
|
||||
if (host && protocol) {
|
||||
ctx.registryUrls.push(registryUrl);
|
||||
ctx.registryUrls.push({
|
||||
registryUrl,
|
||||
scope: isPluginRegistry(ctx) ? 'plugin' : 'dep',
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
// no-op
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { query as q } from 'good-enough-parser';
|
||||
import { regEx } from '../../../../util/regex';
|
||||
import type { Ctx } from '../types';
|
||||
import { qApplyFrom } from './apply-from';
|
||||
import { qAssignments } from './assignments';
|
||||
import {
|
||||
REGISTRY_URLS,
|
||||
cleanupTempVars,
|
||||
|
@ -13,6 +15,7 @@ import {
|
|||
handleCustomRegistryUrl,
|
||||
handlePredefinedRegistryUrl,
|
||||
} from './handlers';
|
||||
import { qPlugins } from './plugins';
|
||||
|
||||
// mavenCentral()
|
||||
// mavenCentral { ... }
|
||||
|
@ -94,8 +97,38 @@ const qCustomRegistryUrl = q
|
|||
.handler(handleCustomRegistryUrl)
|
||||
.handler(cleanupTempVars);
|
||||
|
||||
const qPluginManagement = q.sym<Ctx>('pluginManagement', storeVarToken).tree({
|
||||
type: 'wrapped-tree',
|
||||
startsWith: '{',
|
||||
endsWith: '}',
|
||||
preHandler: (ctx) => {
|
||||
ctx.tmpTokenStore.registryScope = ctx.varTokens;
|
||||
ctx.varTokens = [];
|
||||
return ctx;
|
||||
},
|
||||
search: q
|
||||
.handler<Ctx>((ctx) => {
|
||||
if (ctx.tmpTokenStore.registryScope) {
|
||||
ctx.tokenMap.registryScope = ctx.tmpTokenStore.registryScope;
|
||||
}
|
||||
return ctx;
|
||||
})
|
||||
.alt(
|
||||
qAssignments,
|
||||
qApplyFrom,
|
||||
qPlugins,
|
||||
qPredefinedRegistries,
|
||||
qCustomRegistryUrl
|
||||
),
|
||||
postHandler: (ctx) => {
|
||||
delete ctx.tmpTokenStore.registryScope;
|
||||
return ctx;
|
||||
},
|
||||
});
|
||||
|
||||
export const qRegistryUrls = q.alt<Ctx>(
|
||||
q.sym<Ctx>('publishing').tree(),
|
||||
qPluginManagement,
|
||||
qPredefinedRegistries,
|
||||
qCustomRegistryUrl
|
||||
);
|
||||
|
|
|
@ -16,7 +16,7 @@ export type VariableRegistry = Record<string, PackageVariables>;
|
|||
|
||||
export interface ParseGradleResult {
|
||||
deps: PackageDependency<GradleManagerData>[];
|
||||
urls: string[];
|
||||
urls: PackageRegistry[];
|
||||
vars: PackageVariables;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,11 @@ export interface RichVersion {
|
|||
export type GradleVersionPointerTarget = string | RichVersion;
|
||||
export type GradleVersionCatalogVersion = string | VersionPointer | RichVersion;
|
||||
|
||||
export interface PackageRegistry {
|
||||
registryUrl: string;
|
||||
scope: 'dep' | 'plugin';
|
||||
}
|
||||
|
||||
export interface Ctx {
|
||||
readonly packageFile: string;
|
||||
readonly fileContents: Record<string, string | null>;
|
||||
|
@ -74,7 +79,7 @@ export interface Ctx {
|
|||
|
||||
globalVars: PackageVariables;
|
||||
deps: PackageDependency<GradleManagerData>[];
|
||||
registryUrls: string[];
|
||||
registryUrls: PackageRegistry[];
|
||||
|
||||
varTokens: lexer.Token[];
|
||||
tmpTokenStore: Record<string, lexer.Token[]>;
|
||||
|
|
Loading…
Reference in a new issue