Support Maven mirrors in generated settings.xml

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 59df028a-0d1b-49cb-8126-ab26408663e4
This commit is contained in:
Bruno Borges
2026-10-16 09:39:48 -04:00
parent b843ebf9b9
commit df4305dee7
10 changed files with 445 additions and 9 deletions

View File

@@ -882,6 +882,162 @@ describe('auth tests', () => {
]);
});
it.each([
'*',
'central',
'external:*',
'external:http:*',
'*,!internal',
'external:*,!internal',
'!internal,external:http:*',
'external:*,!external:http:*'
])('preserves the mirror selector %s and URL colons', mirrorOf => {
expect(
auth.parseMavenMirrors([
'',
' \t ',
` private : https://[2001:db8::1]:8443/maven : ${mirrorOf} `,
'public:https://repo.example.com:443/releases:central'
])
).toEqual([
{
id: 'private',
url: 'https://[2001:db8::1]:8443/maven',
mirrorOf
},
{
id: 'public',
url: 'https://repo.example.com:443/releases',
mirrorOf: 'central'
}
]);
});
it.each([
'private',
'private:https://repo.example.com',
':https://repo.example.com:*',
'private::*',
'private:https://repo.example.com:',
'private: :*',
'private:https://repo.example.com: '
])('rejects malformed mirror entry %s with a line number', entry => {
expect(() => auth.parseMavenMirrors(['', entry])).toThrow(
'Invalid mvn-mirrors entry at line 2.'
);
});
it('rejects duplicate mirror IDs after trimming', () => {
expect(() =>
auth.parseMavenMirrors([
'private:https://first.example.com:*',
' private :https://second.example.com:central'
])
).toThrow("Duplicate mirror-id 'private' in mvn-mirrors input at line 2");
});
it('leaves settings unchanged for absent or blank mirrors', () => {
const servers = credentials('github', 'USERNAME', 'PASSWORD');
expect(auth.parseMavenMirrors(['', ' ', '\t'])).toEqual([]);
expect(auth.generate(servers, undefined, undefined, [])).toBe(
auth.generate(servers)
);
expect(auth.generate(servers)).not.toContain('<mirrors>');
});
it('generates public mirrors without credentials or repository profiles', () => {
const mirrors = auth.parseMavenMirrors([
'public:https://repo.example.com:external:*',
'fallback:https://other.example.com:central'
]);
const xml = auth.generate([], undefined, undefined, mirrors);
expect(parseXmlObject(xml)).toMatchObject({
settings: {mirrors: {mirror: mirrors}}
});
expect(xml).not.toContain('<profiles>');
expect(xml).not.toContain('<activeProfiles>');
});
it('escapes all mirror fields as XML text', () => {
const mirror = {
id: 'private<&>',
url: 'https://repo.example.com/maven?a=1&b=<value>',
mirrorOf: '*,!internal<&>'
};
const xml = auth.generate([], undefined, undefined, [mirror]);
expect(xml).toContain('<id>private&lt;&amp;&gt;</id>');
expect(xml).toContain('a=1&amp;b=&lt;value&gt;');
expect(xml).toContain('<mirrorOf>*,!internal&lt;&amp;&gt;</mirrorOf>');
expect(parseXmlObject(xml)).toMatchObject({
settings: {mirrors: {mirror}}
});
});
it.each([
{combined: false, overwrite: true},
{combined: true, overwrite: true},
{combined: true, overwrite: false}
])(
'configures mirrors with combined=$combined and overwrite=$overwrite',
async ({combined, overwrite}) => {
const directory = path.join(m2Dir, 'mirrors');
const location = path.join(directory, MVN_SETTINGS_FILE);
fs.mkdirSync(directory, {recursive: true});
fs.writeFileSync(location, 'EXISTING SETTINGS');
const url = 'https://maven.example.com/releases';
const inputs: Record<string, string> = {
'settings-path': directory,
'overwrite-settings': String(overwrite),
'mvn-repositories-include-central': 'false',
...(combined ? {'gpg-passphrase-env-var': 'GPG_PASSPHRASE'} : {})
};
const multilineInputs: Record<string, string[]> = {
'mvn-server-credentials': ['private:PRIVATE_USERNAME:PRIVATE_TOKEN'],
'mvn-mirrors': [`private:${url}:*`],
...(combined
? {
'mvn-repositories': [`private:${url}:false`],
'mvn-plugin-repositories': [`private:${url}:false`]
}
: {})
};
jest.mocked(core.getInput).mockImplementation(name => inputs[name] ?? '');
jest
.mocked(core.getMultilineInput)
.mockImplementation(name => multilineInputs[name] ?? []);
await auth.configureAuthentication();
const xml = fs.readFileSync(location, 'utf8');
if (!overwrite) {
expect(xml).toBe('EXISTING SETTINGS');
return;
}
expect(parseXmlObject(xml)).toMatchObject({
settings: {
mirrors: {mirror: {id: 'private', url, mirrorOf: '*'}},
servers: {
server: {
id: 'private',
username: '${env.PRIVATE_USERNAME}',
password: '${env.PRIVATE_TOKEN}'
}
}
}
});
if (combined) {
expect(xml).toContain('<repositories>');
expect(xml).toContain('<pluginRepositories>');
expect(xml).toContain('<gpg.passphraseEnvName>GPG_PASSPHRASE');
} else {
expect(xml).not.toContain('<profiles>');
expect(core.getInput).not.toHaveBeenCalledWith(
'mvn-repositories-include-central'
);
}
}
);
it.each(repositoryInputs)(
'parses %s while preserving colons in URLs',
inputName => {