Skip to content

Commit

Permalink
feat(manager/maven): support .mvn/extensions.xml (#28893)
Browse files Browse the repository at this point in the history
  • Loading branch information
RahulGautamSingh committed May 8, 2024
1 parent 96f760a commit 468b0d1
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
63 changes: 63 additions & 0 deletions lib/modules/manager/maven/extract.spec.ts
Expand Up @@ -3,6 +3,7 @@ import { Fixtures } from '../../../../test/fixtures';
import { fs } from '../../../../test/util';
import {
extractAllPackageFiles,
extractExtensions,
extractPackage,
extractRegistries,
resolveParents,
Expand Down Expand Up @@ -365,6 +366,27 @@ describe('modules/manager/maven/extract', () => {
});
});

describe('extractExtensions', () => {
it('returns null for invalid xml files', () => {
expect(extractExtensions('', '.mvn/extensions.xml')).toBeNull();
expect(
extractExtensions('invalid xml content', '.mvn/extensions.xml'),
).toBeNull();
expect(
extractExtensions('<foobar></foobar>', '.mvn/extensions.xml'),
).toBeNull();
expect(
extractExtensions('<extensions></extensions>', '.mvn/extensions.xml'),
).toBeNull();
expect(
extractExtensions(
'<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0"></extensions>',
'.mvn/extensions.xml',
),
).toBeNull();
});
});

describe('extractAllPackageFiles', () => {
it('should return empty if package has no content', async () => {
fs.readLocalFile.mockResolvedValueOnce('');
Expand Down Expand Up @@ -706,6 +728,47 @@ describe('modules/manager/maven/extract', () => {
]);
});

it('should extract from .mvn/extensions.xml file', async () => {
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
<extension>
<groupId>io.jenkins.tools.incrementals</groupId>
<artifactId>git-changelist-maven-extension</artifactId>
<version>1.6</version>
</extension>
</extensions>
`);
const res = await extractAllPackageFiles({}, ['.mvn/extensions.xml']);
expect(res).toMatchObject([
{
packageFile: '.mvn/extensions.xml',
deps: [
{
datasource: 'maven',
depName:
'io.jenkins.tools.incrementals:git-changelist-maven-extension',
currentValue: '1.6',
depType: 'build',
fileReplacePosition: 372,
registryUrls: ['https://repo.maven.apache.org/maven2'],
},
],
},
]);
});

it('should return empty array if extensions file is invalid or empty', async () => {
fs.readLocalFile
.mockResolvedValueOnce('')
.mockResolvedValueOnce('invalid xml content');
expect(
await extractAllPackageFiles({}, [
'.mvn/extensions.xml',
'grp/.mvn/extensions.xml',
]),
).toBeEmptyArray();
});

describe('root pom handling', () => {
it('should skip root pom.xml', async () => {
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
Expand Down
58 changes: 58 additions & 0 deletions lib/modules/manager/maven/extract.ts
Expand Up @@ -15,6 +15,12 @@ const supportedNamespaces = [
'http://maven.apache.org/SETTINGS/1.2.0',
];

const supportedExtensionsNamespaces = [
'http://maven.apache.org/EXTENSIONS/1.0.0',
'http://maven.apache.org/EXTENSIONS/1.1.0',
'http://maven.apache.org/EXTENSIONS/1.2.0',
];

function parsePom(raw: string, packageFile: string): XmlDocument | null {
let project: XmlDocument;
try {
Expand All @@ -39,6 +45,27 @@ function parsePom(raw: string, packageFile: string): XmlDocument | null {
return null;
}

function parseExtensions(raw: string, packageFile: string): XmlDocument | null {
let extensions: XmlDocument;
try {
extensions = new XmlDocument(raw);
} catch (err) {
logger.debug({ packageFile }, `Failed to parse as XML`);
return null;
}
const { name, attr, children } = extensions;
if (name !== 'extensions') {
return null;
}
if (!supportedExtensionsNamespaces.includes(attr.xmlns)) {
return null;
}
if (!is.nonEmptyArray(children)) {
return null;
}
return extensions;
}

function containsPlaceholder(str: string | null | undefined): boolean {
return !!str && regEx(/\${[^}]*?}/).test(str);
}
Expand Down Expand Up @@ -476,6 +503,30 @@ function cleanResult(packageFiles: MavenInterimPackageFile[]): PackageFile[] {
return packageFiles;
}

export function extractExtensions(
rawContent: string,
packageFile: string,
): PackageFile | null {
if (!rawContent) {
return null;
}

const extensions = parseExtensions(rawContent, packageFile);
if (!extensions) {
return null;
}

const result: MavenInterimPackageFile = {
datasource: MavenDatasource.id,
packageFile,
deps: [],
};

result.deps = deepExtract(extensions);

return result;
}

export async function extractAllPackageFiles(
_config: ExtractConfig,
packageFiles: string[],
Expand All @@ -498,6 +549,13 @@ export async function extractAllPackageFiles(
);
additionalRegistryUrls.push(...registries);
}
} else if (packageFile.endsWith('.mvn/extensions.xml')) {
const extensions = extractExtensions(content, packageFile);
if (extensions) {
packages.push(extensions);
} else {
logger.trace({ packageFile }, 'can not read extensions');
}
} else {
const pkg = extractPackage(content, packageFile);
if (pkg) {
Expand Down
6 changes: 5 additions & 1 deletion lib/modules/manager/maven/index.ts
Expand Up @@ -6,7 +6,11 @@ export { extractAllPackageFiles } from './extract';
export { bumpPackageVersion, updateDependency } from './update';

export const defaultConfig = {
fileMatch: ['(^|/|\\.)pom\\.xml$', '^(((\\.mvn)|(\\.m2))/)?settings\\.xml$'],
fileMatch: [
'(^|/|\\.)pom\\.xml$',
'^(((\\.mvn)|(\\.m2))/)?settings\\.xml$',
'(^|/)\\.mvn/extensions\\.xml$',
],
versioning: mavenVersioning.id,
};

Expand Down

0 comments on commit 468b0d1

Please sign in to comment.