mirror of
https://github.com/actions/setup-java.git
synced 2026-07-31 16:12:59 +00:00
Optimize Maven configuration warm path (#1182)
* Optimize Maven configuration warm path Avoid eager Maven XML initialization on warm JDK runs by using deterministic serializers for new Maven settings/toolchains files, lazy-loading xmlbuilder2 for existing toolchains merges, and deferring Maven configuration modules until after Java setup. Add targeted tests for XML escaping, lazy xmlbuilder2 loading, concurrent Maven configuration, and a manual benchmark workflow for warm-path validation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b * Address Maven optimization PR feedback Make the toolchain XML generator consistently async, remove redundant Maven configuration await handling, and reuse the existing XML test helper. Configure CodeQL to skip generated dist output so newly split vendored chunks do not report duplicate generated-code alerts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b * Apply rubber duck review suggestions Document XML attribute escaping, simplify Maven configuration awaiting, and add a regression test that feeds fast-path toolchains output into the merge path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b * Delete .github/codeql/codeql-config.yml * Update codeql-analysis.yml * Replace xmlbuilder2 in Maven toolchain merge Use fast-xml-parser for existing toolchains.xml parsing and serialize merged Maven toolchains deterministically. This removes the bundled xmlbuilder2 DOM/XML builder chunk from dist while preserving merge behavior for custom attributes, custom toolchains, partial entries, duplicate filtering, and escaping. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b * Move Maven benchmark out of setup-java Remove the Maven warm-path benchmark workflow and helper script from setup-java. Benchmark coverage is being moved to actions/setup-java-benchmarks so this action repository only carries the runtime optimization, tests, and generated distribution artifacts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b --------- Copilot-Session: 4dc58426-5e20-44cb-af16-8da0965fac3b
This commit is contained in:
@@ -13,6 +13,7 @@ import * as io from '@actions/io';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import {XMLParser} from 'fast-xml-parser';
|
||||||
|
|
||||||
// Mock @actions/core before importing source modules that depend on it
|
// Mock @actions/core before importing source modules that depend on it
|
||||||
jest.unstable_mockModule('@actions/core', () => ({
|
jest.unstable_mockModule('@actions/core', () => ({
|
||||||
@@ -271,6 +272,41 @@ describe('auth tests', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('escapes settings.xml values while preserving parsed semantics', () => {
|
||||||
|
const id = `packages&<>"'é`;
|
||||||
|
const username = `USER&<>"'é`;
|
||||||
|
const password = `TOKEN&<>"'é`;
|
||||||
|
const gpgPassphrase = `GPG&<>"'é`;
|
||||||
|
|
||||||
|
const xml = auth.generate(id, username, password, gpgPassphrase);
|
||||||
|
const parsed = parseXmlObject(xml) as any;
|
||||||
|
|
||||||
|
expect(parsed.settings.interactiveMode).toBe('false');
|
||||||
|
expect(xmlElementText(xml, 'id')).toBe(id);
|
||||||
|
expect(xmlElementText(xml, 'username')).toBe(`\${env.${username}}`);
|
||||||
|
expect(xmlElementText(xml, 'password')).toBe(`\${env.${password}}`);
|
||||||
|
expect(xmlElementText(xml, 'gpg.passphraseEnvName')).toBe(gpgPassphrase);
|
||||||
|
expect(parsed.settings.activeProfiles.activeProfile).toBe('setup-java-gpg');
|
||||||
|
});
|
||||||
|
|
||||||
|
function xmlElementText(xml: string, tagName: string): string {
|
||||||
|
const match = new RegExp(`<${tagName}>([\\s\\S]*?)</${tagName}>`).exec(xml);
|
||||||
|
expect(match).not.toBeNull();
|
||||||
|
return (parseXmlObject(`<value>${match?.[1]}</value>`) as {value: string})
|
||||||
|
.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseXmlObject(xml: string): unknown {
|
||||||
|
const parser = new XMLParser({
|
||||||
|
ignoreAttributes: false,
|
||||||
|
attributeNamePrefix: '@',
|
||||||
|
parseAttributeValue: false,
|
||||||
|
parseTagValue: false,
|
||||||
|
trimValues: true
|
||||||
|
});
|
||||||
|
return parser.parse(xml);
|
||||||
|
}
|
||||||
|
|
||||||
it('uses deprecated input aliases and warns', () => {
|
it('uses deprecated input aliases and warns', () => {
|
||||||
const mockGetInput = core.getInput as jest.MockedFunction<
|
const mockGetInput = core.getInput as jest.MockedFunction<
|
||||||
typeof core.getInput
|
typeof core.getInput
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import {describe, expect, it, jest} from '@jest/globals';
|
||||||
|
|
||||||
|
const mockXmlBuilderFactory = jest.fn();
|
||||||
|
const mockParse = jest.fn(() => ({
|
||||||
|
toolchains: {
|
||||||
|
toolchain: [
|
||||||
|
{
|
||||||
|
type: 'foo',
|
||||||
|
provides: {id: 'custom'},
|
||||||
|
configuration: {fooHome: '/opt/foo'}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule('fast-xml-parser', () => {
|
||||||
|
mockXmlBuilderFactory();
|
||||||
|
return {
|
||||||
|
XMLParser: jest.fn().mockImplementation(() => ({
|
||||||
|
parse: mockParse
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const toolchains = await import('../src/toolchains.js');
|
||||||
|
|
||||||
|
describe('Maven XML loading', () => {
|
||||||
|
it('does not load fast-xml-parser for new toolchains.xml generation', async () => {
|
||||||
|
const xml = await toolchains.generateToolchainDefinition(
|
||||||
|
'',
|
||||||
|
'21',
|
||||||
|
'temurin',
|
||||||
|
'temurin_21',
|
||||||
|
'/opt/java/21'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(xml).toContain('<id>temurin_21</id>');
|
||||||
|
expect(mockXmlBuilderFactory).not.toHaveBeenCalled();
|
||||||
|
expect(mockParse).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads fast-xml-parser for existing toolchains.xml merge generation', async () => {
|
||||||
|
await expect(
|
||||||
|
toolchains.generateToolchainDefinition(
|
||||||
|
'<toolchains><toolchain><type>foo</type></toolchain></toolchains>',
|
||||||
|
'21',
|
||||||
|
'temurin',
|
||||||
|
'temurin_21',
|
||||||
|
'/opt/java/21'
|
||||||
|
)
|
||||||
|
).resolves.toContain('<id>temurin_21</id>');
|
||||||
|
|
||||||
|
expect(mockXmlBuilderFactory).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockParse).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -41,6 +41,10 @@ jest.unstable_mockModule('../src/toolchains.js', () => ({
|
|||||||
configureToolchains: jest.fn()
|
configureToolchains: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule('../src/toolchain-ids.js', () => ({
|
||||||
|
validateToolchainIds: jest.fn()
|
||||||
|
}));
|
||||||
|
|
||||||
jest.unstable_mockModule('../src/cache.js', () => ({
|
jest.unstable_mockModule('../src/cache.js', () => ({
|
||||||
restore: jest.fn()
|
restore: jest.fn()
|
||||||
}));
|
}));
|
||||||
@@ -72,6 +76,7 @@ const core = await import('@actions/core');
|
|||||||
const fs = (await import('fs')).default;
|
const fs = (await import('fs')).default;
|
||||||
const util = await import('../src/util.js');
|
const util = await import('../src/util.js');
|
||||||
const toolchains = await import('../src/toolchains.js');
|
const toolchains = await import('../src/toolchains.js');
|
||||||
|
const toolchainIds = await import('../src/toolchain-ids.js');
|
||||||
const cache = await import('../src/cache.js');
|
const cache = await import('../src/cache.js');
|
||||||
const cacheFeature = await import('../src/cache-feature.js');
|
const cacheFeature = await import('../src/cache-feature.js');
|
||||||
const factory = await import('../src/distributions/distribution-factory.js');
|
const factory = await import('../src/distributions/distribution-factory.js');
|
||||||
@@ -109,6 +114,9 @@ describe('setup action orchestration', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
(cacheFeature.isCacheFeatureAvailable as jest.Mock).mockReturnValue(true);
|
(cacheFeature.isCacheFeatureAvailable as jest.Mock).mockReturnValue(true);
|
||||||
|
(toolchainIds.validateToolchainIds as jest.Mock).mockImplementation(
|
||||||
|
() => undefined
|
||||||
|
);
|
||||||
(toolchains.configureToolchains as jest.Mock).mockResolvedValue(undefined);
|
(toolchains.configureToolchains as jest.Mock).mockResolvedValue(undefined);
|
||||||
(auth.configureAuthentication as jest.Mock).mockResolvedValue(undefined);
|
(auth.configureAuthentication as jest.Mock).mockResolvedValue(undefined);
|
||||||
(cache.restore as jest.Mock).mockResolvedValue(undefined);
|
(cache.restore as jest.Mock).mockResolvedValue(undefined);
|
||||||
@@ -215,7 +223,7 @@ describe('setup action orchestration', () => {
|
|||||||
},
|
},
|
||||||
'/tmp/java.tar.gz'
|
'/tmp/java.tar.gz'
|
||||||
);
|
);
|
||||||
expect(toolchains.validateToolchainIds).toHaveBeenCalledWith(
|
expect(toolchainIds.validateToolchainIds).toHaveBeenCalledWith(
|
||||||
[],
|
[],
|
||||||
'.sdkmanrc',
|
'.sdkmanrc',
|
||||||
['file-jdk']
|
['file-jdk']
|
||||||
@@ -342,23 +350,29 @@ describe('setup action orchestration', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
(problemMatcher.configureProblemMatcher as jest.Mock).mock
|
||||||
|
.invocationCallOrder[0]
|
||||||
|
).toBeLessThan(
|
||||||
|
(auth.configureAuthentication as jest.Mock).mock.invocationCallOrder[0]
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
(problemMatcher.configureProblemMatcher as jest.Mock).mock
|
||||||
|
.invocationCallOrder[0]
|
||||||
|
).toBeLessThan(
|
||||||
(toolchains.configureToolchains as jest.Mock).mock
|
(toolchains.configureToolchains as jest.Mock).mock
|
||||||
.invocationCallOrder[0]
|
.invocationCallOrder[0]
|
||||||
).toBeLessThan(
|
|
||||||
(problemMatcher.configureProblemMatcher as jest.Mock).mock
|
|
||||||
.invocationCallOrder[0]
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
(problemMatcher.configureProblemMatcher as jest.Mock).mock
|
|
||||||
.invocationCallOrder[0]
|
|
||||||
).toBeLessThan(
|
|
||||||
(auth.configureAuthentication as jest.Mock).mock.invocationCallOrder[0]
|
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
(auth.configureAuthentication as jest.Mock).mock.invocationCallOrder[0]
|
(auth.configureAuthentication as jest.Mock).mock.invocationCallOrder[0]
|
||||||
).toBeLessThan(
|
).toBeLessThan(
|
||||||
(mavenArgs.configureMavenArgs as jest.Mock).mock.invocationCallOrder[0]
|
(mavenArgs.configureMavenArgs as jest.Mock).mock.invocationCallOrder[0]
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
(toolchains.configureToolchains as jest.Mock).mock
|
||||||
|
.invocationCallOrder[0]
|
||||||
|
).toBeLessThan(
|
||||||
|
(mavenArgs.configureMavenArgs as jest.Mock).mock.invocationCallOrder[0]
|
||||||
|
);
|
||||||
|
|
||||||
let completed = false;
|
let completed = false;
|
||||||
runPromise.then(() => {
|
runPromise.then(() => {
|
||||||
@@ -375,6 +389,54 @@ describe('setup action orchestration', () => {
|
|||||||
expect(core.setFailed).not.toHaveBeenCalled();
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('overlaps independent Maven settings and toolchains configuration', async () => {
|
||||||
|
inputs.set('distribution', 'temurin');
|
||||||
|
multilineInputs.set('java-version', ['21']);
|
||||||
|
(factory.getJavaDistribution as jest.Mock).mockReturnValue({
|
||||||
|
setupJava: jest.fn(async () => ({
|
||||||
|
version: '21.0.4+7',
|
||||||
|
path: '/opt/java/21'
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
const authentication = deferred<void>();
|
||||||
|
const toolchainConfiguration = deferred<void>();
|
||||||
|
(auth.configureAuthentication as jest.Mock).mockReturnValue(
|
||||||
|
authentication.promise
|
||||||
|
);
|
||||||
|
(toolchains.configureToolchains as jest.Mock).mockReturnValue(
|
||||||
|
toolchainConfiguration.promise
|
||||||
|
);
|
||||||
|
|
||||||
|
const runPromise = run();
|
||||||
|
try {
|
||||||
|
await tick();
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
expect(auth.configureAuthentication).toHaveBeenCalled();
|
||||||
|
expect(toolchains.configureToolchains).toHaveBeenCalledWith(
|
||||||
|
'21',
|
||||||
|
'temurin',
|
||||||
|
'/opt/java/21',
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
expect(mavenArgs.configureMavenArgs).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
authentication.resolve();
|
||||||
|
await tick();
|
||||||
|
expect(mavenArgs.configureMavenArgs).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
toolchainConfiguration.resolve();
|
||||||
|
await runPromise;
|
||||||
|
} finally {
|
||||||
|
authentication.resolve();
|
||||||
|
toolchainConfiguration.resolve();
|
||||||
|
await runPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(mavenArgs.configureMavenArgs).toHaveBeenCalled();
|
||||||
|
expect(core.setFailed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('skips cache restoration when the cache feature is unavailable', async () => {
|
it('skips cache restoration when the cache feature is unavailable', async () => {
|
||||||
inputs.set('distribution', 'temurin');
|
inputs.set('distribution', 'temurin');
|
||||||
inputs.set('cache', 'maven');
|
inputs.set('cache', 'maven');
|
||||||
|
|||||||
+137
-24
@@ -13,6 +13,7 @@ import * as fs from 'fs';
|
|||||||
import os from 'os';
|
import os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
|
import {XMLParser} from 'fast-xml-parser';
|
||||||
|
|
||||||
// Mock @actions/core before importing source modules that depend on it
|
// Mock @actions/core before importing source modules that depend on it
|
||||||
jest.unstable_mockModule('@actions/core', () => ({
|
jest.unstable_mockModule('@actions/core', () => ({
|
||||||
@@ -95,7 +96,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(altHome)).toBe(true);
|
expect(fs.existsSync(altHome)).toBe(true);
|
||||||
expect(fs.existsSync(altToolchainsFile)).toBe(true);
|
expect(fs.existsSync(altToolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(altToolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(altToolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
'',
|
'',
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -140,7 +141,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
'',
|
'',
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -149,7 +150,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
'',
|
'',
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -221,7 +222,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -230,7 +231,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -306,7 +307,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -315,7 +316,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -383,7 +384,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -392,7 +393,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -453,7 +454,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -462,7 +463,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -545,7 +546,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -554,7 +555,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -604,7 +605,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -613,7 +614,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -662,7 +663,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -671,7 +672,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -745,7 +746,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -754,7 +755,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -824,7 +825,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -833,7 +834,7 @@ describe('toolchains tests', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
originalFile,
|
originalFile,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -888,7 +889,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(updated).toContain(`<jdkHome>${jdkInfo.jdkHome}</jdkHome>`);
|
expect(updated).toContain(`<jdkHome>${jdkInfo.jdkHome}</jdkHome>`);
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
|
||||||
it('generates valid toolchains.xml with minimal configuration', () => {
|
it('generates valid toolchains.xml with minimal configuration', async () => {
|
||||||
const jdkInfo = {
|
const jdkInfo = {
|
||||||
version: 'JAVA_VERSION',
|
version: 'JAVA_VERSION',
|
||||||
vendor: 'JAVA_VENDOR',
|
vendor: 'JAVA_VENDOR',
|
||||||
@@ -914,7 +915,7 @@ describe('toolchains tests', () => {
|
|||||||
</toolchains>`;
|
</toolchains>`;
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
'',
|
'',
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -924,6 +925,29 @@ describe('toolchains tests', () => {
|
|||||||
).toEqual(expectedToolchains);
|
).toEqual(expectedToolchains);
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
|
||||||
|
it('escapes new toolchains.xml values while preserving parsed semantics', () => {
|
||||||
|
const jdkInfo = {
|
||||||
|
version: `21&<>"'é`,
|
||||||
|
vendor: `Temurin&<>"'é`,
|
||||||
|
id: `temurin&<>"'é`,
|
||||||
|
jdkHome: `/opt/java&<>"'é`
|
||||||
|
};
|
||||||
|
|
||||||
|
const xml = toolchains.generateNewToolchainDefinition(
|
||||||
|
jdkInfo.version,
|
||||||
|
jdkInfo.vendor,
|
||||||
|
jdkInfo.id,
|
||||||
|
jdkInfo.jdkHome
|
||||||
|
);
|
||||||
|
const parsed = parseXmlObject(xml) as any;
|
||||||
|
|
||||||
|
expect(parsed.toolchains.toolchain[0].type).toBe('jdk');
|
||||||
|
expect(xmlElementText(xml, 'version')).toBe(jdkInfo.version);
|
||||||
|
expect(xmlElementText(xml, 'vendor')).toBe(jdkInfo.vendor);
|
||||||
|
expect(xmlElementText(xml, 'id')).toBe(jdkInfo.id);
|
||||||
|
expect(xmlElementText(xml, 'jdkHome')).toBe(jdkInfo.jdkHome);
|
||||||
|
});
|
||||||
|
|
||||||
it('creates toolchains.xml with correct id when none is supplied', async () => {
|
it('creates toolchains.xml with correct id when none is supplied', async () => {
|
||||||
const version = '17';
|
const version = '17';
|
||||||
const distributionName = 'temurin';
|
const distributionName = 'temurin';
|
||||||
@@ -946,7 +970,7 @@ describe('toolchains tests', () => {
|
|||||||
expect(fs.existsSync(m2Dir)).toBe(true);
|
expect(fs.existsSync(m2Dir)).toBe(true);
|
||||||
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
expect(fs.existsSync(toolchainsFile)).toBe(true);
|
||||||
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
expect(fs.readFileSync(toolchainsFile, 'utf-8')).toEqual(
|
||||||
toolchains.generateToolchainDefinition(
|
await toolchains.generateToolchainDefinition(
|
||||||
'',
|
'',
|
||||||
version,
|
version,
|
||||||
distributionName,
|
distributionName,
|
||||||
@@ -956,6 +980,75 @@ describe('toolchains tests', () => {
|
|||||||
);
|
);
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
|
||||||
|
it('merges a second JDK into a toolchains.xml produced by the new-file fast path', async () => {
|
||||||
|
const firstJdk = {
|
||||||
|
version: '17',
|
||||||
|
vendor: 'temurin',
|
||||||
|
id: 'temurin_17',
|
||||||
|
jdkHome: '/opt/java/17'
|
||||||
|
};
|
||||||
|
const secondJdk = {
|
||||||
|
version: '21',
|
||||||
|
vendor: 'temurin',
|
||||||
|
id: 'temurin_21',
|
||||||
|
jdkHome: '/opt/java/21'
|
||||||
|
};
|
||||||
|
|
||||||
|
const firstToolchains = await toolchains.generateToolchainDefinition(
|
||||||
|
'',
|
||||||
|
firstJdk.version,
|
||||||
|
firstJdk.vendor,
|
||||||
|
firstJdk.id,
|
||||||
|
firstJdk.jdkHome
|
||||||
|
);
|
||||||
|
const mergedToolchains = await toolchains.generateToolchainDefinition(
|
||||||
|
firstToolchains,
|
||||||
|
secondJdk.version,
|
||||||
|
secondJdk.vendor,
|
||||||
|
secondJdk.id,
|
||||||
|
secondJdk.jdkHome
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const jdk of [firstJdk, secondJdk]) {
|
||||||
|
expect(mergedToolchains).toContain(`<id>${jdk.id}</id>`);
|
||||||
|
expect(mergedToolchains).toContain(`<jdkHome>${jdk.jdkHome}</jdkHome>`);
|
||||||
|
}
|
||||||
|
expect((mergedToolchains.match(/<toolchain>/g) || []).length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('preserves custom attributes and elements when merging existing toolchains.xml', async () => {
|
||||||
|
const originalFile = `<toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.0.0" customRoot="A & B">
|
||||||
|
<toolchain customAttr="custom & value">
|
||||||
|
<type>foo</type>
|
||||||
|
<provides customProvides="yes">
|
||||||
|
<custom attr="custom " attr">baz & qux</custom>
|
||||||
|
</provides>
|
||||||
|
<configuration>
|
||||||
|
<fooHome>/usr/local/bin/foo</fooHome>
|
||||||
|
</configuration>
|
||||||
|
</toolchain>
|
||||||
|
</toolchains>`;
|
||||||
|
|
||||||
|
const mergedToolchains = await toolchains.generateToolchainDefinition(
|
||||||
|
originalFile,
|
||||||
|
'21&<>"\'',
|
||||||
|
'Temurin&<>"\'',
|
||||||
|
'temurin_21&<>"\'',
|
||||||
|
'/opt/java/21&<>"\''
|
||||||
|
);
|
||||||
|
const parsed = parseXmlObject(mergedToolchains) as any;
|
||||||
|
const merged = parsed.toolchains.toolchain;
|
||||||
|
|
||||||
|
expect(parsed.toolchains['@customRoot']).toBe('A & B');
|
||||||
|
expect(merged).toHaveLength(2);
|
||||||
|
expect(merged[0].provides.id).toBe('temurin_21&<>"\'');
|
||||||
|
expect(merged[0].configuration.jdkHome).toBe('/opt/java/21&<>"\'');
|
||||||
|
expect(merged[1]['@customAttr']).toBe('custom & value');
|
||||||
|
expect(merged[1].provides['@customProvides']).toBe('yes');
|
||||||
|
expect(merged[1].provides.custom['#text']).toBe('baz & qux');
|
||||||
|
expect(merged[1].provides.custom['@attr']).toBe('custom " attr');
|
||||||
|
});
|
||||||
|
|
||||||
it('preserves toolchains from previous executions across multiple setup-java runs', async () => {
|
it('preserves toolchains from previous executions across multiple setup-java runs', async () => {
|
||||||
// Regression test for https://github.com/actions/setup-java/issues/1099
|
// Regression test for https://github.com/actions/setup-java/issues/1099
|
||||||
// Running setup-java several times in the same job (e.g. multiple steps / multiple
|
// Running setup-java several times in the same job (e.g. multiple steps / multiple
|
||||||
@@ -1071,3 +1164,23 @@ describe('validateToolchainIds', () => {
|
|||||||
).toThrow(expectedMessage);
|
).toThrow(expectedMessage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function xmlElementText(xml: string, tagName: string): string {
|
||||||
|
const match = new RegExp(`<${tagName}>([\\s\\S]*?)</${tagName}>`).exec(xml);
|
||||||
|
expect(match).not.toBeNull();
|
||||||
|
return (parseXmlObject(`<value>${match?.[1]}</value>`) as {value: string})
|
||||||
|
.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseXmlObject(xml: string): unknown {
|
||||||
|
const parser = new XMLParser({
|
||||||
|
ignoreAttributes: false,
|
||||||
|
attributeNamePrefix: '@',
|
||||||
|
textNodeName: '#text',
|
||||||
|
parseAttributeValue: false,
|
||||||
|
parseTagValue: false,
|
||||||
|
trimValues: true,
|
||||||
|
isArray: tagName => tagName === 'toolchain'
|
||||||
|
});
|
||||||
|
return parser.parse(xml);
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+63
@@ -0,0 +1,63 @@
|
|||||||
|
export const id = 172;
|
||||||
|
export const ids = [172];
|
||||||
|
export const modules = {
|
||||||
|
|
||||||
|
/***/ 8172:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ configureMavenArgs: () => (/* binding */ configureMavenArgs)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3838);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4527);
|
||||||
|
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7242);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the MAVEN_ARGS environment variable so that Maven suppresses
|
||||||
|
* artifact transfer/download progress output by default, producing cleaner
|
||||||
|
* CI logs.
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - When `show-download-progress` is `false` (the default), `-ntp`
|
||||||
|
* (`--no-transfer-progress`) is appended to any existing MAVEN_ARGS value.
|
||||||
|
* - When `show-download-progress` is `true`, MAVEN_ARGS is left untouched so
|
||||||
|
* the user's own configuration (and Maven's default progress output) is
|
||||||
|
* preserved.
|
||||||
|
*
|
||||||
|
* The change is idempotent: if MAVEN_ARGS already disables transfer progress
|
||||||
|
* (via `-ntp` or `--no-transfer-progress`) nothing is added. Any pre-existing
|
||||||
|
* MAVEN_ARGS value is preserved.
|
||||||
|
*
|
||||||
|
* MAVEN_ARGS is honored by Maven 3.9.0+ and the Maven Wrapper; older Maven
|
||||||
|
* versions ignore it, so this is a no-op there. It has no effect on non-Maven
|
||||||
|
* builds such as Gradle or sbt.
|
||||||
|
*/
|
||||||
|
function configureMavenArgs() {
|
||||||
|
const showDownloadProgress = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .INPUT_SHOW_DOWNLOAD_PROGRESS */ .wX, false);
|
||||||
|
if (showDownloadProgress) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .debug */ .Yz(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .INPUT_SHOW_DOWNLOAD_PROGRESS */ .wX} is true; leaving ${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_ARGS_ENV */ .qm} unchanged`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const existingArgs = (process.env[_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_ARGS_ENV */ .qm] ?? '').trim();
|
||||||
|
const alreadyDisabled = existingArgs
|
||||||
|
.split(/\s+/)
|
||||||
|
.some(arg => arg === _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_NO_TRANSFER_PROGRESS_FLAG */ .ti ||
|
||||||
|
arg === _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_NO_TRANSFER_PROGRESS_LONG_FLAG */ .kN);
|
||||||
|
if (alreadyDisabled) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .debug */ .Yz(`${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_ARGS_ENV */ .qm} already disables transfer progress; leaving it unchanged`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const updatedArgs = existingArgs
|
||||||
|
? `${existingArgs} ${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_NO_TRANSFER_PROGRESS_FLAG */ .ti}`
|
||||||
|
: _constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_NO_TRANSFER_PROGRESS_FLAG */ .ti;
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .exportVariable */ .dN(_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_ARGS_ENV */ .qm, updatedArgs);
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_0__/* .info */ .pq(`Configured ${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_ARGS_ENV */ .qm} to include ${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .MAVEN_NO_TRANSFER_PROGRESS_FLAG */ .ti} to suppress Maven transfer progress logs. ` +
|
||||||
|
`Set '${_constants_js__WEBPACK_IMPORTED_MODULE_2__/* .INPUT_SHOW_DOWNLOAD_PROGRESS */ .wX}: true' to keep the download progress output.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
};
|
||||||
Vendored
+109
@@ -163,6 +163,115 @@ class MicrosoftDistributions extends base_installer/* JavaBase */.O {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 8343:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ Fh: () => (/* binding */ importKey),
|
||||||
|
/* harmony export */ Yi: () => (/* binding */ verifyPackageSignature)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* unused harmony exports PRIVATE_KEY_FILE, toGpgPath, deleteKey */
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var _actions_exec__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5260);
|
||||||
|
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PRIVATE_KEY_FILE = path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'private-key.asc');
|
||||||
|
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
|
||||||
|
// Convert a Windows path (D:\a\_temp\...) to a POSIX path (/d/a/_temp/...).
|
||||||
|
// The Git-bundled GPG on Windows (MSYS2-based) uses POSIX path conventions
|
||||||
|
// internally. Passing Windows paths with backslashes can cause fatal GPG errors
|
||||||
|
// (exit code 2), so all paths passed to GPG must be in POSIX format on Windows.
|
||||||
|
function toGpgPath(p) {
|
||||||
|
if (process.platform !== 'win32')
|
||||||
|
return p;
|
||||||
|
return p
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.replace(/^([A-Za-z]):\//, (_, drive) => `/${drive.toLowerCase()}/`);
|
||||||
|
}
|
||||||
|
async function importKey(privateKey) {
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
let output = '';
|
||||||
|
const options = {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
output += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--batch',
|
||||||
|
'--import-options',
|
||||||
|
'import-show',
|
||||||
|
'--import',
|
||||||
|
PRIVATE_KEY_FILE
|
||||||
|
], options);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(PRIVATE_KEY_FILE);
|
||||||
|
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
|
||||||
|
return match && match[0];
|
||||||
|
}
|
||||||
|
async function deleteKey(keyFingerprint) {
|
||||||
|
await exec.exec('gpg', ['--batch', '--yes', '--delete-secret-and-public-key', keyFingerprint], {
|
||||||
|
silent: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
|
||||||
|
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .downloadTool */ .bq(signatureUrl);
|
||||||
|
let gpgHome;
|
||||||
|
try {
|
||||||
|
gpgHome = fs__WEBPACK_IMPORTED_MODULE_0__.mkdtempSync(path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'verify-signature-gpg-home-'));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
try {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore cleanup failures
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to create temporary GPG home directory for signature verification: ${error.message}`, { cause: error });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const publicKeyFile = path__WEBPACK_IMPORTED_MODULE_1__.join(gpgHome, 'public-key.asc');
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(publicKeyFile, publicKeyContent, { encoding: 'utf-8' });
|
||||||
|
const options = { silent: true };
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--import',
|
||||||
|
toGpgPath(publicKeyFile)
|
||||||
|
], options);
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--verify',
|
||||||
|
toGpgPath(signaturePath),
|
||||||
|
toGpgPath(archivePath)
|
||||||
|
], options);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(gpgHome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+1
-1
@@ -141,7 +141,7 @@ var external_os_default = /*#__PURE__*/__webpack_require__.n(external_os_);
|
|||||||
// EXTERNAL MODULE: external "crypto"
|
// EXTERNAL MODULE: external "crypto"
|
||||||
var external_crypto_ = __webpack_require__(6982);
|
var external_crypto_ = __webpack_require__(6982);
|
||||||
// EXTERNAL MODULE: external "stream/promises"
|
// EXTERNAL MODULE: external "stream/promises"
|
||||||
var promises_ = __webpack_require__(4548);
|
var promises_ = __webpack_require__(9786);
|
||||||
;// CONCATENATED MODULE: ./src/checksum.ts
|
;// CONCATENATED MODULE: ./src/checksum.ts
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -13,7 +13,7 @@ export const modules = {
|
|||||||
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(857);
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(857);
|
||||||
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_1__);
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5767);
|
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6971);
|
||||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
||||||
/* harmony import */ var _actions_glob__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2377);
|
/* harmony import */ var _actions_glob__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2377);
|
||||||
/**
|
/**
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ export const modules = {
|
|||||||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
/* harmony export */ isCacheFeatureAvailable: () => (/* binding */ isCacheFeatureAvailable)
|
/* harmony export */ isCacheFeatureAvailable: () => (/* binding */ isCacheFeatureAvailable)
|
||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5767);
|
/* harmony import */ var _actions_cache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6971);
|
||||||
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3838);
|
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3838);
|
||||||
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4527);
|
||||||
|
|
||||||
|
|||||||
Vendored
+262
@@ -0,0 +1,262 @@
|
|||||||
|
export const id = 451;
|
||||||
|
export const ids = [451];
|
||||||
|
export const modules = {
|
||||||
|
|
||||||
|
/***/ 9451:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ configureToolchains: () => (/* binding */ configureToolchains),
|
||||||
|
/* harmony export */ createToolchainsSettings: () => (/* binding */ createToolchainsSettings),
|
||||||
|
/* harmony export */ generateNewToolchainDefinition: () => (/* binding */ generateNewToolchainDefinition),
|
||||||
|
/* harmony export */ generateToolchainDefinition: () => (/* binding */ generateToolchainDefinition),
|
||||||
|
/* harmony export */ validateToolchainIds: () => (/* reexport safe */ _toolchain_ids_js__WEBPACK_IMPORTED_MODULE_5__.O)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(857);
|
||||||
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
|
||||||
|
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3838);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7242);
|
||||||
|
/* harmony import */ var _toolchain_ids_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7083);
|
||||||
|
/* harmony import */ var _xml_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(22);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function configureToolchains(version, distributionName, jdkHome, toolchainId) {
|
||||||
|
const vendor = _actions_core__WEBPACK_IMPORTED_MODULE_3__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_6__/* .INPUT_MVN_TOOLCHAIN_VENDOR */ .m7) || distributionName;
|
||||||
|
const id = toolchainId || `${vendor}_${version}`;
|
||||||
|
const settingsDirectory = _actions_core__WEBPACK_IMPORTED_MODULE_3__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_6__/* .INPUT_SETTINGS_PATH */ .Xh) ||
|
||||||
|
path__WEBPACK_IMPORTED_MODULE_2__.join(os__WEBPACK_IMPORTED_MODULE_1__.homedir(), _constants_js__WEBPACK_IMPORTED_MODULE_6__/* .M2_DIR */ .iT);
|
||||||
|
await createToolchainsSettings({
|
||||||
|
jdkInfo: {
|
||||||
|
version,
|
||||||
|
vendor,
|
||||||
|
id,
|
||||||
|
jdkHome
|
||||||
|
},
|
||||||
|
settingsDirectory
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function createToolchainsSettings({ jdkInfo, settingsDirectory }) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .info */ .pq(`Creating ${_constants_js__WEBPACK_IMPORTED_MODULE_6__/* .MVN_TOOLCHAINS_FILE */ .qs} for JDK version ${jdkInfo.version} from ${jdkInfo.vendor}`);
|
||||||
|
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
||||||
|
// otherwise use the home/.m2/ path
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_4__/* .mkdirP */ .U$(settingsDirectory);
|
||||||
|
const originalToolchains = await readExistingToolchainsFile(settingsDirectory);
|
||||||
|
const updatedToolchains = await generateToolchainDefinition(originalToolchains, jdkInfo.version, jdkInfo.vendor, jdkInfo.id, jdkInfo.jdkHome);
|
||||||
|
await writeToolchainsFileToDisk(settingsDirectory, updatedToolchains);
|
||||||
|
}
|
||||||
|
// only exported for testing purposes
|
||||||
|
async function generateToolchainDefinition(original, version, vendor, id, jdkHome) {
|
||||||
|
if (!original?.length) {
|
||||||
|
return generateNewToolchainDefinition(version, vendor, id, jdkHome);
|
||||||
|
}
|
||||||
|
return generateMergedToolchainDefinition(original, version, vendor, id, jdkHome);
|
||||||
|
}
|
||||||
|
async function generateMergedToolchainDefinition(original, version, vendor, id, jdkHome) {
|
||||||
|
let jsToolchains = [
|
||||||
|
{
|
||||||
|
type: 'jdk',
|
||||||
|
provides: {
|
||||||
|
version: `${version}`,
|
||||||
|
vendor: `${vendor}`,
|
||||||
|
id: `${id}`
|
||||||
|
},
|
||||||
|
configuration: {
|
||||||
|
jdkHome: `${jdkHome}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
// default root attributes, used when the existing file does not declare its own
|
||||||
|
let rootAttributes = {
|
||||||
|
'@xmlns': 'http://maven.apache.org/TOOLCHAINS/1.1.0',
|
||||||
|
'@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||||
|
'@xsi:schemaLocation': 'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd'
|
||||||
|
};
|
||||||
|
const { XMLParser } = await __webpack_require__.e(/* import() */ 824).then(__webpack_require__.bind(__webpack_require__, 5824));
|
||||||
|
const parser = new XMLParser({
|
||||||
|
ignoreAttributes: false,
|
||||||
|
attributeNamePrefix: '@',
|
||||||
|
parseAttributeValue: false,
|
||||||
|
parseTagValue: false,
|
||||||
|
trimValues: true,
|
||||||
|
isArray: tagName => tagName === 'toolchain'
|
||||||
|
});
|
||||||
|
const jsObj = parser.parse(original);
|
||||||
|
if (isToolchainsRoot(jsObj.toolchains)) {
|
||||||
|
// preserve the existing root attributes (xmlns, schemaLocation, …) so we don't
|
||||||
|
// silently rewrite user-managed metadata or change the effective XML namespace;
|
||||||
|
// fast-xml-parser exposes attributes as `@`-prefixed keys on the element object
|
||||||
|
const existingAttributes = Object.fromEntries(Object.entries(jsObj.toolchains).filter(([key, value]) => key.startsWith('@') && typeof value === 'string'));
|
||||||
|
// fall back to the defaults only for attributes the existing file is missing
|
||||||
|
rootAttributes = { ...rootAttributes, ...existingAttributes };
|
||||||
|
if (jsObj.toolchains.toolchain) {
|
||||||
|
jsToolchains.push(...jsObj.toolchains.toolchain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove potential duplicates based on type & id (which should be a unique combination);
|
||||||
|
// self.findIndex will only return the first occurrence, ensuring duplicates are skipped
|
||||||
|
jsToolchains = jsToolchains.filter((value, index, self) =>
|
||||||
|
// ensure non-jdk toolchains are kept in the results, we must not touch them because they belong to the user
|
||||||
|
value.type !== 'jdk' ||
|
||||||
|
// keep toolchains that lack a usable string id (e.g. partially-formed user files);
|
||||||
|
// we cannot safely deduplicate them and must not crash while reading them
|
||||||
|
typeof value.provides?.id !== 'string' ||
|
||||||
|
index ===
|
||||||
|
self.findIndex(t => t.type === value.type && t.provides?.id === value.provides?.id));
|
||||||
|
return serializeToolchains(rootAttributes, jsToolchains);
|
||||||
|
}
|
||||||
|
function generateNewToolchainDefinition(version, vendor, id, jdkHome) {
|
||||||
|
return [
|
||||||
|
'<?xml version="1.0"?>',
|
||||||
|
'<toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0"',
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
|
||||||
|
' xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd">',
|
||||||
|
' <toolchain>',
|
||||||
|
' <type>jdk</type>',
|
||||||
|
' <provides>',
|
||||||
|
` <version>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(version)}</version>`,
|
||||||
|
` <vendor>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(vendor)}</vendor>`,
|
||||||
|
` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(id)}</id>`,
|
||||||
|
' </provides>',
|
||||||
|
' <configuration>',
|
||||||
|
` <jdkHome>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(jdkHome)}</jdkHome>`,
|
||||||
|
' </configuration>',
|
||||||
|
' </toolchain>',
|
||||||
|
'</toolchains>'
|
||||||
|
].join('\n');
|
||||||
|
}
|
||||||
|
async function readExistingToolchainsFile(directory) {
|
||||||
|
const location = path__WEBPACK_IMPORTED_MODULE_2__.join(directory, _constants_js__WEBPACK_IMPORTED_MODULE_6__/* .MVN_TOOLCHAINS_FILE */ .qs);
|
||||||
|
if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(location)) {
|
||||||
|
return fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(location, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'r'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
async function writeToolchainsFileToDisk(directory, settings) {
|
||||||
|
const location = path__WEBPACK_IMPORTED_MODULE_2__.join(directory, _constants_js__WEBPACK_IMPORTED_MODULE_6__/* .MVN_TOOLCHAINS_FILE */ .qs);
|
||||||
|
const settingsExists = fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(location);
|
||||||
|
// The toolchains file is produced by a non-destructive merge (existing JDK,
|
||||||
|
// custom, and non-jdk toolchains are preserved – see generateToolchainDefinition),
|
||||||
|
// so it is always safe to write it. Unlike settings.xml, it is therefore not
|
||||||
|
// gated behind the `overwrite-settings` input; that would prevent subsequent
|
||||||
|
// setup-java runs from registering additional JDKs and silently drop the
|
||||||
|
// toolchain entries created by earlier runs.
|
||||||
|
if (settingsExists) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .info */ .pq(`Updating existing file ${location}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_3__/* .info */ .pq(`Writing to ${location}`);
|
||||||
|
}
|
||||||
|
return fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(location, settings, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function serializeToolchains(rootAttributes, toolchains) {
|
||||||
|
return [
|
||||||
|
'<?xml version="1.0"?>',
|
||||||
|
serializeOpeningTag('toolchains', rootAttributes, 0),
|
||||||
|
...toolchains.flatMap(toolchain => serializeXmlElement('toolchain', toolchain, 1)),
|
||||||
|
'</toolchains>'
|
||||||
|
].join('\n');
|
||||||
|
}
|
||||||
|
function serializeOpeningTag(name, attributes, depth) {
|
||||||
|
const indent = ' '.repeat(depth);
|
||||||
|
const attributeEntries = Object.entries(attributes);
|
||||||
|
if (!attributeEntries.length) {
|
||||||
|
return `${indent}<${name}>`;
|
||||||
|
}
|
||||||
|
const [firstAttribute, ...restAttributes] = attributeEntries;
|
||||||
|
const lines = [
|
||||||
|
`${indent}<${name} ${formatXmlAttribute(firstAttribute)}`,
|
||||||
|
...restAttributes.map(([attributeName, value]) => {
|
||||||
|
return `${indent} ${formatXmlAttribute([attributeName, value])}`;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
lines[lines.length - 1] += '>';
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
function serializeXmlElement(name, value, depth) {
|
||||||
|
const indent = ' '.repeat(depth);
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.flatMap(item => serializeXmlElement(name, item, depth));
|
||||||
|
}
|
||||||
|
if (!isXmlElementObject(value)) {
|
||||||
|
return [
|
||||||
|
`${indent}<${name}>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(String(value ?? ''))}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const attributes = Object.fromEntries(Object.entries(value)
|
||||||
|
.filter(([key, attributeValue]) => {
|
||||||
|
return key.startsWith('@') && typeof attributeValue === 'string';
|
||||||
|
})
|
||||||
|
.map(([key, attributeValue]) => [key, attributeValue]));
|
||||||
|
const childEntries = Object.entries(value).filter(([key]) => !key.startsWith('@') && key !== '#text');
|
||||||
|
const textValue = value['#text'];
|
||||||
|
if (!childEntries.length) {
|
||||||
|
if (textValue !== undefined) {
|
||||||
|
return [
|
||||||
|
`${serializeOpeningTag(name, attributes, depth)}${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(String(textValue ?? ''))}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [`${serializeOpeningTag(name, attributes, depth)}</${name}>`];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
serializeOpeningTag(name, attributes, depth),
|
||||||
|
...(textValue === undefined
|
||||||
|
? []
|
||||||
|
: [`${' '.repeat(depth + 1)}${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlText */ .I)(String(textValue ?? ''))}`]),
|
||||||
|
...childEntries.flatMap(([childName, childValue]) => serializeXmlElement(childName, childValue, depth + 1)),
|
||||||
|
`${indent}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
function formatXmlAttribute([name, value]) {
|
||||||
|
return `${name.slice(1)}="${(0,_xml_js__WEBPACK_IMPORTED_MODULE_7__/* .escapeXmlAttribute */ .R)(value)}"`;
|
||||||
|
}
|
||||||
|
function isToolchainsRoot(value) {
|
||||||
|
return isXmlElementObject(value);
|
||||||
|
}
|
||||||
|
function isXmlElementObject(value) {
|
||||||
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 22:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ I: () => (/* binding */ escapeXmlText),
|
||||||
|
/* harmony export */ R: () => (/* binding */ escapeXmlAttribute)
|
||||||
|
/* harmony export */ });
|
||||||
|
function escapeXmlText(value) {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>');
|
||||||
|
}
|
||||||
|
// Use for user-controlled values written into XML attributes. Text nodes should
|
||||||
|
// use escapeXmlText so quotes remain byte-compatible with previous output.
|
||||||
|
function escapeXmlAttribute(value) {
|
||||||
|
return escapeXmlText(value).replace(/"/g, '"').replace(/'/g, ''');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
};
|
||||||
Vendored
+109
@@ -264,6 +264,115 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 8343:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ Fh: () => (/* binding */ importKey),
|
||||||
|
/* harmony export */ Yi: () => (/* binding */ verifyPackageSignature)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* unused harmony exports PRIVATE_KEY_FILE, toGpgPath, deleteKey */
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var _actions_exec__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5260);
|
||||||
|
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PRIVATE_KEY_FILE = path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'private-key.asc');
|
||||||
|
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
|
||||||
|
// Convert a Windows path (D:\a\_temp\...) to a POSIX path (/d/a/_temp/...).
|
||||||
|
// The Git-bundled GPG on Windows (MSYS2-based) uses POSIX path conventions
|
||||||
|
// internally. Passing Windows paths with backslashes can cause fatal GPG errors
|
||||||
|
// (exit code 2), so all paths passed to GPG must be in POSIX format on Windows.
|
||||||
|
function toGpgPath(p) {
|
||||||
|
if (process.platform !== 'win32')
|
||||||
|
return p;
|
||||||
|
return p
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.replace(/^([A-Za-z]):\//, (_, drive) => `/${drive.toLowerCase()}/`);
|
||||||
|
}
|
||||||
|
async function importKey(privateKey) {
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
let output = '';
|
||||||
|
const options = {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
output += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--batch',
|
||||||
|
'--import-options',
|
||||||
|
'import-show',
|
||||||
|
'--import',
|
||||||
|
PRIVATE_KEY_FILE
|
||||||
|
], options);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(PRIVATE_KEY_FILE);
|
||||||
|
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
|
||||||
|
return match && match[0];
|
||||||
|
}
|
||||||
|
async function deleteKey(keyFingerprint) {
|
||||||
|
await exec.exec('gpg', ['--batch', '--yes', '--delete-secret-and-public-key', keyFingerprint], {
|
||||||
|
silent: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
|
||||||
|
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .downloadTool */ .bq(signatureUrl);
|
||||||
|
let gpgHome;
|
||||||
|
try {
|
||||||
|
gpgHome = fs__WEBPACK_IMPORTED_MODULE_0__.mkdtempSync(path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'verify-signature-gpg-home-'));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
try {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore cleanup failures
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to create temporary GPG home directory for signature verification: ${error.message}`, { cause: error });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const publicKeyFile = path__WEBPACK_IMPORTED_MODULE_1__.join(gpgHome, 'public-key.asc');
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(publicKeyFile, publicKeyContent, { encoding: 'utf-8' });
|
||||||
|
const options = { silent: true };
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--import',
|
||||||
|
toGpgPath(publicKeyFile)
|
||||||
|
], options);
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--verify',
|
||||||
|
toGpgPath(signaturePath),
|
||||||
|
toGpgPath(archivePath)
|
||||||
|
], options);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(gpgHome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+4
-4
@@ -5784,7 +5784,7 @@ exports.colors = [6, 2, 3, 4, 5, 1];
|
|||||||
try {
|
try {
|
||||||
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
const supportsColor = __webpack_require__(9069);
|
const supportsColor = __webpack_require__(1450);
|
||||||
|
|
||||||
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
||||||
exports.colors = [
|
exports.colors = [
|
||||||
@@ -6020,7 +6020,7 @@ formatters.O = function (v) {
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 6194:
|
/***/ 3813:
|
||||||
/***/ ((module) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
|
||||||
@@ -6651,13 +6651,13 @@ function plural(ms, msAbs, n, name) {
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 9069:
|
/***/ 1450:
|
||||||
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
||||||
|
|
||||||
|
|
||||||
const os = __webpack_require__(857);
|
const os = __webpack_require__(857);
|
||||||
const tty = __webpack_require__(2018);
|
const tty = __webpack_require__(2018);
|
||||||
const hasFlag = __webpack_require__(6194);
|
const hasFlag = __webpack_require__(3813);
|
||||||
|
|
||||||
const {env} = process;
|
const {env} = process;
|
||||||
|
|
||||||
|
|||||||
Vendored
+253
@@ -0,0 +1,253 @@
|
|||||||
|
export const id = 81;
|
||||||
|
export const ids = [81];
|
||||||
|
export const modules = {
|
||||||
|
|
||||||
|
/***/ 9081:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ configureAuthentication: () => (/* binding */ configureAuthentication),
|
||||||
|
/* harmony export */ createAuthenticationSettings: () => (/* binding */ createAuthenticationSettings),
|
||||||
|
/* harmony export */ generate: () => (/* binding */ generate),
|
||||||
|
/* harmony export */ getInputWithDeprecatedAlias: () => (/* binding */ getInputWithDeprecatedAlias)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3838);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_3__);
|
||||||
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(857);
|
||||||
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_4__);
|
||||||
|
/* harmony import */ var _constants_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(7242);
|
||||||
|
/* harmony import */ var _gpg_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8343);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4527);
|
||||||
|
/* harmony import */ var _xml_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(22);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function configureAuthentication() {
|
||||||
|
const id = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_ID */ .fd);
|
||||||
|
const usernameEnvVar = getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_ENV_VAR */ .sc, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_USERNAME_DEPRECATED */ .sp, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_USERNAME */ .Wj);
|
||||||
|
const passwordEnvVar = getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_ENV_VAR */ .r4, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SERVER_PASSWORD_DEPRECATED */ .Vt, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_SERVER_PASSWORD */ .xp);
|
||||||
|
const settingsDirectory = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_SETTINGS_PATH */ .Xh) ||
|
||||||
|
path__WEBPACK_IMPORTED_MODULE_0__.join(os__WEBPACK_IMPORTED_MODULE_4__.homedir(), _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .M2_DIR */ .iT);
|
||||||
|
const overwriteSettings = (0,_util_js__WEBPACK_IMPORTED_MODULE_6__/* .getBooleanInput */ .Vt)(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_OVERWRITE_SETTINGS */ .TS, true);
|
||||||
|
const gpgPrivateKey = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_GPG_PRIVATE_KEY */ .wz) ||
|
||||||
|
_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_GPG_PRIVATE_KEY */ .OD;
|
||||||
|
const gpgPassphraseEnvVar = getInputWithDeprecatedAlias(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_GPG_PASSPHRASE_ENV_VAR */ .db, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_GPG_PASSPHRASE_DEPRECATED */ .TY, gpgPrivateKey ? _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .INPUT_DEFAULT_GPG_PASSPHRASE */ .RX : undefined);
|
||||||
|
if (gpgPrivateKey) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .setSecret */ .Pq(gpgPrivateKey);
|
||||||
|
}
|
||||||
|
await createAuthenticationSettings(id, usernameEnvVar, passwordEnvVar, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar);
|
||||||
|
if (gpgPrivateKey) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq('Importing private gpg key');
|
||||||
|
const keyFingerprint = (await _gpg_js__WEBPACK_IMPORTED_MODULE_5__/* .importKey */ .Fh(gpgPrivateKey)) || '';
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .saveState */ .LZ(_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .STATE_GPG_PRIVATE_KEY_FINGERPRINT */ .wm, keyFingerprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getInputWithDeprecatedAlias(inputName, deprecatedInputName, defaultValue) {
|
||||||
|
const value = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(inputName);
|
||||||
|
const deprecatedValue = _actions_core__WEBPACK_IMPORTED_MODULE_1__/* .getInput */ .V4(deprecatedInputName);
|
||||||
|
if (deprecatedValue) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .warning */ .$e(`The '${deprecatedInputName}' input is deprecated and may be removed in a future release. Please use '${inputName}' instead.`);
|
||||||
|
}
|
||||||
|
return value || deprecatedValue || defaultValue || '';
|
||||||
|
}
|
||||||
|
async function createAuthenticationSettings(id, usernameEnvVar, passwordEnvVar, settingsDirectory, overwriteSettings, gpgPassphraseEnvVar = undefined) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Creating ${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MVN_SETTINGS_FILE */ .vO} with server-id: ${id}`);
|
||||||
|
// when an alternate m2 location is specified use only that location (no .m2 directory)
|
||||||
|
// otherwise use the home/.m2/ path
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .mkdirP */ .U$(settingsDirectory);
|
||||||
|
await write(settingsDirectory, generate(id, usernameEnvVar, passwordEnvVar, gpgPassphraseEnvVar), overwriteSettings);
|
||||||
|
}
|
||||||
|
// only exported for testing purposes
|
||||||
|
function generate(id, usernameEnvVar, passwordEnvVar, gpgPassphraseEnvVar) {
|
||||||
|
// The maven-gpg-plugin reads the passphrase from the environment variable
|
||||||
|
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
||||||
|
// Only configure it when the requested env var name differs from that default;
|
||||||
|
// otherwise the plugin already reads the right variable and no extra settings
|
||||||
|
// are needed. Writing `gpg.passphrase` to settings.xml is deprecated and fails
|
||||||
|
// when the plugin's `bestPractices` mode is enabled.
|
||||||
|
const includeGpgPassphraseProfile = gpgPassphraseEnvVar &&
|
||||||
|
gpgPassphraseEnvVar !== _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MAVEN_GPG_PASSPHRASE_DEFAULT_ENV */ .ko;
|
||||||
|
const lines = [
|
||||||
|
'<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"',
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
|
||||||
|
' xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">',
|
||||||
|
' <interactiveMode>false</interactiveMode>',
|
||||||
|
' <servers>',
|
||||||
|
' <server>',
|
||||||
|
` <id>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(id)}</id>`,
|
||||||
|
` <username>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${usernameEnvVar}}`)}</username>`,
|
||||||
|
` <password>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(`\${env.${passwordEnvVar}}`)}</password>`,
|
||||||
|
' </server>',
|
||||||
|
' </servers>'
|
||||||
|
];
|
||||||
|
if (includeGpgPassphraseProfile) {
|
||||||
|
lines.push(' <profiles>', ' <profile>', ` <id>${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .GPG_PASSPHRASE_PROFILE_ID */ .K$}</id>`, ' <properties>', ` <gpg.passphraseEnvName>${(0,_xml_js__WEBPACK_IMPORTED_MODULE_8__/* .escapeXmlText */ .I)(gpgPassphraseEnvVar)}</gpg.passphraseEnvName>`, ' </properties>', ' </profile>', ' </profiles>', ' <activeProfiles>', ` <activeProfile>${_constants_js__WEBPACK_IMPORTED_MODULE_7__/* .GPG_PASSPHRASE_PROFILE_ID */ .K$}</activeProfile>`, ' </activeProfiles>');
|
||||||
|
}
|
||||||
|
lines.push('</settings>');
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
async function write(directory, settings, overwriteSettings) {
|
||||||
|
const location = path__WEBPACK_IMPORTED_MODULE_0__.join(directory, _constants_js__WEBPACK_IMPORTED_MODULE_7__/* .MVN_SETTINGS_FILE */ .vO);
|
||||||
|
const settingsExists = fs__WEBPACK_IMPORTED_MODULE_3__.existsSync(location);
|
||||||
|
if (settingsExists && overwriteSettings) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Overwriting existing file ${location}`);
|
||||||
|
}
|
||||||
|
else if (!settingsExists) {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Writing to ${location}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_actions_core__WEBPACK_IMPORTED_MODULE_1__/* .info */ .pq(`Skipping generation ${location} because file already exists and overwriting is not required`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return fs__WEBPACK_IMPORTED_MODULE_3__.writeFileSync(location, settings, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 8343:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ Fh: () => (/* binding */ importKey),
|
||||||
|
/* harmony export */ Yi: () => (/* binding */ verifyPackageSignature)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* unused harmony exports PRIVATE_KEY_FILE, toGpgPath, deleteKey */
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var _actions_exec__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5260);
|
||||||
|
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PRIVATE_KEY_FILE = path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'private-key.asc');
|
||||||
|
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
|
||||||
|
// Convert a Windows path (D:\a\_temp\...) to a POSIX path (/d/a/_temp/...).
|
||||||
|
// The Git-bundled GPG on Windows (MSYS2-based) uses POSIX path conventions
|
||||||
|
// internally. Passing Windows paths with backslashes can cause fatal GPG errors
|
||||||
|
// (exit code 2), so all paths passed to GPG must be in POSIX format on Windows.
|
||||||
|
function toGpgPath(p) {
|
||||||
|
if (process.platform !== 'win32')
|
||||||
|
return p;
|
||||||
|
return p
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.replace(/^([A-Za-z]):\//, (_, drive) => `/${drive.toLowerCase()}/`);
|
||||||
|
}
|
||||||
|
async function importKey(privateKey) {
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
let output = '';
|
||||||
|
const options = {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
output += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--batch',
|
||||||
|
'--import-options',
|
||||||
|
'import-show',
|
||||||
|
'--import',
|
||||||
|
PRIVATE_KEY_FILE
|
||||||
|
], options);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(PRIVATE_KEY_FILE);
|
||||||
|
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
|
||||||
|
return match && match[0];
|
||||||
|
}
|
||||||
|
async function deleteKey(keyFingerprint) {
|
||||||
|
await exec.exec('gpg', ['--batch', '--yes', '--delete-secret-and-public-key', keyFingerprint], {
|
||||||
|
silent: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
|
||||||
|
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .downloadTool */ .bq(signatureUrl);
|
||||||
|
let gpgHome;
|
||||||
|
try {
|
||||||
|
gpgHome = fs__WEBPACK_IMPORTED_MODULE_0__.mkdtempSync(path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'verify-signature-gpg-home-'));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
try {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore cleanup failures
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to create temporary GPG home directory for signature verification: ${error.message}`, { cause: error });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const publicKeyFile = path__WEBPACK_IMPORTED_MODULE_1__.join(gpgHome, 'public-key.asc');
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(publicKeyFile, publicKeyContent, { encoding: 'utf-8' });
|
||||||
|
const options = { silent: true };
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--import',
|
||||||
|
toGpgPath(publicKeyFile)
|
||||||
|
], options);
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--verify',
|
||||||
|
toGpgPath(signaturePath),
|
||||||
|
toGpgPath(archivePath)
|
||||||
|
], options);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(gpgHome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 22:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ I: () => (/* binding */ escapeXmlText),
|
||||||
|
/* harmony export */ R: () => (/* binding */ escapeXmlAttribute)
|
||||||
|
/* harmony export */ });
|
||||||
|
function escapeXmlText(value) {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>');
|
||||||
|
}
|
||||||
|
// Use for user-controlled values written into XML attributes. Text nodes should
|
||||||
|
// use escapeXmlText so quotes remain byte-compatible with previous output.
|
||||||
|
function escapeXmlAttribute(value) {
|
||||||
|
return escapeXmlText(value).replace(/"/g, '"').replace(/'/g, ''');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
};
|
||||||
Vendored
+7109
File diff suppressed because it is too large
Load Diff
Vendored
+109
@@ -466,6 +466,115 @@ class TemurinDistribution extends base_installer/* JavaBase */.O {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 8343:
|
||||||
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||||||
|
/* harmony export */ Fh: () => (/* binding */ importKey),
|
||||||
|
/* harmony export */ Yi: () => (/* binding */ verifyPackageSignature)
|
||||||
|
/* harmony export */ });
|
||||||
|
/* unused harmony exports PRIVATE_KEY_FILE, toGpgPath, deleteKey */
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9896);
|
||||||
|
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6928);
|
||||||
|
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var _actions_io__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8701);
|
||||||
|
/* harmony import */ var _actions_exec__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5260);
|
||||||
|
/* harmony import */ var _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9805);
|
||||||
|
/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4527);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PRIVATE_KEY_FILE = path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'private-key.asc');
|
||||||
|
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
|
||||||
|
// Convert a Windows path (D:\a\_temp\...) to a POSIX path (/d/a/_temp/...).
|
||||||
|
// The Git-bundled GPG on Windows (MSYS2-based) uses POSIX path conventions
|
||||||
|
// internally. Passing Windows paths with backslashes can cause fatal GPG errors
|
||||||
|
// (exit code 2), so all paths passed to GPG must be in POSIX format on Windows.
|
||||||
|
function toGpgPath(p) {
|
||||||
|
if (process.platform !== 'win32')
|
||||||
|
return p;
|
||||||
|
return p
|
||||||
|
.replace(/\\/g, '/')
|
||||||
|
.replace(/^([A-Za-z]):\//, (_, drive) => `/${drive.toLowerCase()}/`);
|
||||||
|
}
|
||||||
|
async function importKey(privateKey) {
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
flag: 'w'
|
||||||
|
});
|
||||||
|
let output = '';
|
||||||
|
const options = {
|
||||||
|
silent: true,
|
||||||
|
listeners: {
|
||||||
|
stdout: (data) => {
|
||||||
|
output += data.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--batch',
|
||||||
|
'--import-options',
|
||||||
|
'import-show',
|
||||||
|
'--import',
|
||||||
|
PRIVATE_KEY_FILE
|
||||||
|
], options);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(PRIVATE_KEY_FILE);
|
||||||
|
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
|
||||||
|
return match && match[0];
|
||||||
|
}
|
||||||
|
async function deleteKey(keyFingerprint) {
|
||||||
|
await exec.exec('gpg', ['--batch', '--yes', '--delete-secret-and-public-key', keyFingerprint], {
|
||||||
|
silent: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function verifyPackageSignature(archivePath, signatureUrl, publicKeyContent) {
|
||||||
|
const signaturePath = await _actions_tool_cache__WEBPACK_IMPORTED_MODULE_4__/* .downloadTool */ .bq(signatureUrl);
|
||||||
|
let gpgHome;
|
||||||
|
try {
|
||||||
|
gpgHome = fs__WEBPACK_IMPORTED_MODULE_0__.mkdtempSync(path__WEBPACK_IMPORTED_MODULE_1__.join(_util_js__WEBPACK_IMPORTED_MODULE_5__/* .getTempDir */ .G4(), 'verify-signature-gpg-home-'));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
try {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore cleanup failures
|
||||||
|
}
|
||||||
|
throw new Error(`Failed to create temporary GPG home directory for signature verification: ${error.message}`, { cause: error });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const publicKeyFile = path__WEBPACK_IMPORTED_MODULE_1__.join(gpgHome, 'public-key.asc');
|
||||||
|
fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(publicKeyFile, publicKeyContent, { encoding: 'utf-8' });
|
||||||
|
const options = { silent: true };
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--import',
|
||||||
|
toGpgPath(publicKeyFile)
|
||||||
|
], options);
|
||||||
|
await _actions_exec__WEBPACK_IMPORTED_MODULE_3__/* .exec */ .m('gpg', [
|
||||||
|
'--homedir',
|
||||||
|
toGpgPath(gpgHome),
|
||||||
|
'--batch',
|
||||||
|
'--verify',
|
||||||
|
toGpgPath(signaturePath),
|
||||||
|
toGpgPath(archivePath)
|
||||||
|
], options);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(signaturePath);
|
||||||
|
await _actions_io__WEBPACK_IMPORTED_MODULE_2__/* .rmRF */ .Yz(gpgHome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ })
|
/***/ })
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+55523
File diff suppressed because it is too large
Load Diff
Vendored
+55
-31425
File diff suppressed because it is too large
Load Diff
Generated
+2
-93
@@ -16,8 +16,8 @@
|
|||||||
"@actions/http-client": "^4.0.1",
|
"@actions/http-client": "^4.0.1",
|
||||||
"@actions/io": "^3.0.2",
|
"@actions/io": "^3.0.2",
|
||||||
"@actions/tool-cache": "^4.0.0",
|
"@actions/tool-cache": "^4.0.0",
|
||||||
"semver": "^7.8.5",
|
"fast-xml-parser": "^5.10.1",
|
||||||
"xmlbuilder2": "^4.0.3"
|
"semver": "^7.8.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
@@ -1566,54 +1566,6 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@oozcitak/dom": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@oozcitak/infra": "^2.0.2",
|
|
||||||
"@oozcitak/url": "^3.0.0",
|
|
||||||
"@oozcitak/util": "^10.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@oozcitak/infra": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@oozcitak/util": "^10.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@oozcitak/url": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@oozcitak/infra": "^2.0.2",
|
|
||||||
"@oozcitak/util": "^10.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@oozcitak/util": {
|
|
||||||
"version": "10.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-10.0.0.tgz",
|
|
||||||
"integrity": "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@pkgr/core": {
|
"node_modules/@pkgr/core": {
|
||||||
"version": "0.3.6",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz",
|
||||||
@@ -6042,49 +5994,6 @@
|
|||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/xmlbuilder2": {
|
|
||||||
"version": "4.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-4.0.3.tgz",
|
|
||||||
"integrity": "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@oozcitak/dom": "^2.0.2",
|
|
||||||
"@oozcitak/infra": "^2.0.2",
|
|
||||||
"@oozcitak/util": "^10.0.0",
|
|
||||||
"js-yaml": "^4.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xmlbuilder2/node_modules/argparse": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
|
||||||
"license": "Python-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/xmlbuilder2/node_modules/js-yaml": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/puzrin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/nodeca"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"argparse": "^2.0.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"js-yaml": "bin/js-yaml.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
+2
-2
@@ -49,8 +49,8 @@
|
|||||||
"@actions/http-client": "^4.0.1",
|
"@actions/http-client": "^4.0.1",
|
||||||
"@actions/io": "^3.0.2",
|
"@actions/io": "^3.0.2",
|
||||||
"@actions/tool-cache": "^4.0.0",
|
"@actions/tool-cache": "^4.0.0",
|
||||||
"semver": "^7.8.5",
|
"fast-xml-parser": "^5.10.1",
|
||||||
"xmlbuilder2": "^4.0.3"
|
"semver": "^7.8.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
|
|||||||
+34
-40
@@ -4,11 +4,10 @@ import * as io from '@actions/io';
|
|||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
||||||
import {create as xmlCreate} from 'xmlbuilder2';
|
|
||||||
import * as constants from './constants.js';
|
import * as constants from './constants.js';
|
||||||
import * as gpg from './gpg.js';
|
import * as gpg from './gpg.js';
|
||||||
import {getBooleanInput} from './util.js';
|
import {getBooleanInput} from './util.js';
|
||||||
|
import {escapeXmlText} from './xml.js';
|
||||||
|
|
||||||
export async function configureAuthentication() {
|
export async function configureAuthentication() {
|
||||||
const id = core.getInput(constants.INPUT_SERVER_ID);
|
const id = core.getInput(constants.INPUT_SERVER_ID);
|
||||||
@@ -101,53 +100,48 @@ export function generate(
|
|||||||
passwordEnvVar: string,
|
passwordEnvVar: string,
|
||||||
gpgPassphraseEnvVar?: string | undefined
|
gpgPassphraseEnvVar?: string | undefined
|
||||||
) {
|
) {
|
||||||
const xmlObj: {[key: string]: any} = {
|
|
||||||
settings: {
|
|
||||||
'@xmlns': 'http://maven.apache.org/SETTINGS/1.0.0',
|
|
||||||
'@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
|
||||||
'@xsi:schemaLocation':
|
|
||||||
'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd',
|
|
||||||
interactiveMode: false,
|
|
||||||
servers: {
|
|
||||||
server: [
|
|
||||||
{
|
|
||||||
id: id,
|
|
||||||
username: `\${env.${usernameEnvVar}}`,
|
|
||||||
password: `\${env.${passwordEnvVar}}`
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The maven-gpg-plugin reads the passphrase from the environment variable
|
// The maven-gpg-plugin reads the passphrase from the environment variable
|
||||||
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
// named by the `gpg.passphraseEnvName` property (default MAVEN_GPG_PASSPHRASE).
|
||||||
// Only configure it when the requested env var name differs from that default;
|
// Only configure it when the requested env var name differs from that default;
|
||||||
// otherwise the plugin already reads the right variable and no extra settings
|
// otherwise the plugin already reads the right variable and no extra settings
|
||||||
// are needed. Writing `gpg.passphrase` to settings.xml is deprecated and fails
|
// are needed. Writing `gpg.passphrase` to settings.xml is deprecated and fails
|
||||||
// when the plugin's `bestPractices` mode is enabled.
|
// when the plugin's `bestPractices` mode is enabled.
|
||||||
if (
|
const includeGpgPassphraseProfile =
|
||||||
gpgPassphraseEnvVar &&
|
gpgPassphraseEnvVar &&
|
||||||
gpgPassphraseEnvVar !== constants.MAVEN_GPG_PASSPHRASE_DEFAULT_ENV
|
gpgPassphraseEnvVar !== constants.MAVEN_GPG_PASSPHRASE_DEFAULT_ENV;
|
||||||
) {
|
|
||||||
xmlObj.settings.profiles = {
|
const lines = [
|
||||||
profile: {
|
'<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"',
|
||||||
id: constants.GPG_PASSPHRASE_PROFILE_ID,
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
|
||||||
properties: {
|
' xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">',
|
||||||
'gpg.passphraseEnvName': gpgPassphraseEnvVar
|
' <interactiveMode>false</interactiveMode>',
|
||||||
}
|
' <servers>',
|
||||||
}
|
' <server>',
|
||||||
};
|
` <id>${escapeXmlText(id)}</id>`,
|
||||||
xmlObj.settings.activeProfiles = {
|
` <username>${escapeXmlText(`\${env.${usernameEnvVar}}`)}</username>`,
|
||||||
activeProfile: constants.GPG_PASSPHRASE_PROFILE_ID
|
` <password>${escapeXmlText(`\${env.${passwordEnvVar}}`)}</password>`,
|
||||||
};
|
' </server>',
|
||||||
|
' </servers>'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (includeGpgPassphraseProfile) {
|
||||||
|
lines.push(
|
||||||
|
' <profiles>',
|
||||||
|
' <profile>',
|
||||||
|
` <id>${constants.GPG_PASSPHRASE_PROFILE_ID}</id>`,
|
||||||
|
' <properties>',
|
||||||
|
` <gpg.passphraseEnvName>${escapeXmlText(gpgPassphraseEnvVar)}</gpg.passphraseEnvName>`,
|
||||||
|
' </properties>',
|
||||||
|
' </profile>',
|
||||||
|
' </profiles>',
|
||||||
|
' <activeProfiles>',
|
||||||
|
` <activeProfile>${constants.GPG_PASSPHRASE_PROFILE_ID}</activeProfile>`,
|
||||||
|
' </activeProfiles>'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmlCreate(xmlObj).end({
|
lines.push('</settings>');
|
||||||
headless: true,
|
return lines.join('\n');
|
||||||
prettyPrint: true,
|
|
||||||
width: 80
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function write(
|
async function write(
|
||||||
|
|||||||
+59
-17
@@ -1,15 +1,13 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as auth from './auth.js';
|
|
||||||
import {getBooleanInput, getVersionFromFileContent} from './util.js';
|
import {getBooleanInput, getVersionFromFileContent} from './util.js';
|
||||||
import * as toolchains from './toolchains.js';
|
|
||||||
import * as constants from './constants.js';
|
import * as constants from './constants.js';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {fileURLToPath} from 'url';
|
import {fileURLToPath} from 'url';
|
||||||
import {getJavaDistribution} from './distributions/distribution-factory.js';
|
import {getJavaDistribution} from './distributions/distribution-factory.js';
|
||||||
import {JavaInstallerOptions} from './distributions/base-models.js';
|
import {JavaInstallerOptions} from './distributions/base-models.js';
|
||||||
import {configureMavenArgs} from './maven-args.js';
|
|
||||||
import {configureProblemMatcher} from './problem-matcher.js';
|
import {configureProblemMatcher} from './problem-matcher.js';
|
||||||
|
import {validateToolchainIds} from './toolchain-ids.js';
|
||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION);
|
const versions = core.getMultilineInput(constants.INPUT_JAVA_VERSION);
|
||||||
@@ -33,9 +31,9 @@ export async function run() {
|
|||||||
const verifySignaturePublicKey =
|
const verifySignaturePublicKey =
|
||||||
core.getInput(constants.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY) || undefined;
|
core.getInput(constants.INPUT_VERIFY_SIGNATURE_PUBLIC_KEY) || undefined;
|
||||||
const toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID);
|
const toolchainIds = core.getMultilineInput(constants.INPUT_MVN_TOOLCHAIN_ID);
|
||||||
|
|
||||||
let actionError: Error | undefined;
|
let actionError: Error | undefined;
|
||||||
let cacheRestore: Promise<void> | undefined;
|
let cacheRestore: Promise<void> | undefined;
|
||||||
|
const toolchainConfigurations: ToolchainConfiguration[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core.startGroup('Installed distributions');
|
core.startGroup('Installed distributions');
|
||||||
@@ -44,7 +42,7 @@ export async function run() {
|
|||||||
throw new Error('java-version or java-version-file input expected');
|
throw new Error('java-version or java-version-file input expected');
|
||||||
}
|
}
|
||||||
|
|
||||||
toolchains.validateToolchainIds(versions, versionFile, toolchainIds);
|
validateToolchainIds(versions, versionFile, toolchainIds);
|
||||||
|
|
||||||
if (!versions.length) {
|
if (!versions.length) {
|
||||||
core.debug(
|
core.debug(
|
||||||
@@ -93,7 +91,9 @@ export async function run() {
|
|||||||
cacheRestore = cache
|
cacheRestore = cache
|
||||||
? startCacheRestore(cache, cacheDependencyPath, cachePath)
|
? startCacheRestore(cache, cacheDependencyPath, cachePath)
|
||||||
: undefined;
|
: undefined;
|
||||||
await installVersion(versionInfo.version, installerInputsOptions);
|
toolchainConfigurations.push(
|
||||||
|
await installVersion(versionInfo.version, installerInputsOptions)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// When using java-version input, distribution is still required
|
// When using java-version input, distribution is still required
|
||||||
if (!distributionName) {
|
if (!distributionName) {
|
||||||
@@ -117,7 +117,9 @@ export async function run() {
|
|||||||
? startCacheRestore(cache, cacheDependencyPath, cachePath)
|
? startCacheRestore(cache, cacheDependencyPath, cachePath)
|
||||||
: undefined;
|
: undefined;
|
||||||
for (const [index, version] of versions.entries()) {
|
for (const [index, version] of versions.entries()) {
|
||||||
await installVersion(version, installerInputsOptions, index);
|
toolchainConfigurations.push(
|
||||||
|
await installVersion(version, installerInputsOptions, index)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core.endGroup();
|
core.endGroup();
|
||||||
@@ -129,8 +131,7 @@ export async function run() {
|
|||||||
);
|
);
|
||||||
configureProblemMatcher(path.join(matchersPath, 'java.json'));
|
configureProblemMatcher(path.join(matchersPath, 'java.json'));
|
||||||
|
|
||||||
await auth.configureAuthentication();
|
await configureMaven(toolchainConfigurations);
|
||||||
configureMavenArgs();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
actionError = error as Error;
|
actionError = error as Error;
|
||||||
}
|
}
|
||||||
@@ -174,7 +175,7 @@ async function installVersion(
|
|||||||
version: string,
|
version: string,
|
||||||
options: installerInputsOptions,
|
options: installerInputsOptions,
|
||||||
toolchainId = 0
|
toolchainId = 0
|
||||||
) {
|
): Promise<ToolchainConfiguration> {
|
||||||
const {
|
const {
|
||||||
distributionName,
|
distributionName,
|
||||||
jdkFile,
|
jdkFile,
|
||||||
@@ -217,19 +218,19 @@ async function installVersion(
|
|||||||
const isLatest = version.trim().toLowerCase() === 'latest';
|
const isLatest = version.trim().toLowerCase() === 'latest';
|
||||||
const toolchainVersion = isLatest ? result.version : version;
|
const toolchainVersion = isLatest ? result.version : version;
|
||||||
|
|
||||||
await toolchains.configureToolchains(
|
|
||||||
toolchainVersion,
|
|
||||||
distributionName,
|
|
||||||
result.path,
|
|
||||||
toolchainIds[toolchainId]
|
|
||||||
);
|
|
||||||
|
|
||||||
core.info('');
|
core.info('');
|
||||||
core.info('Java configuration:');
|
core.info('Java configuration:');
|
||||||
core.info(` Distribution: ${distributionName}`);
|
core.info(` Distribution: ${distributionName}`);
|
||||||
core.info(` Version: ${result.version}`);
|
core.info(` Version: ${result.version}`);
|
||||||
core.info(` Path: ${result.path}`);
|
core.info(` Path: ${result.path}`);
|
||||||
core.info('');
|
core.info('');
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: toolchainVersion,
|
||||||
|
distributionName,
|
||||||
|
path: result.path,
|
||||||
|
toolchainId: toolchainIds[toolchainId]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface installerInputsOptions {
|
interface installerInputsOptions {
|
||||||
@@ -245,6 +246,47 @@ interface installerInputsOptions {
|
|||||||
toolchainIds: Array<string>;
|
toolchainIds: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ToolchainConfiguration {
|
||||||
|
version: string;
|
||||||
|
distributionName: string;
|
||||||
|
path: string;
|
||||||
|
toolchainId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function configureMaven(
|
||||||
|
toolchainConfigurations: ToolchainConfiguration[]
|
||||||
|
): Promise<void> {
|
||||||
|
const authentication = import('./auth.js').then(auth =>
|
||||||
|
auth.configureAuthentication()
|
||||||
|
);
|
||||||
|
const toolchains = configureInstalledToolchains(toolchainConfigurations);
|
||||||
|
|
||||||
|
const results = await Promise.allSettled([authentication, toolchains]);
|
||||||
|
const failure = results.find(
|
||||||
|
(result): result is PromiseRejectedResult => result.status === 'rejected'
|
||||||
|
);
|
||||||
|
if (failure) {
|
||||||
|
throw failure.reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {configureMavenArgs} = await import('./maven-args.js');
|
||||||
|
configureMavenArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function configureInstalledToolchains(
|
||||||
|
toolchainConfigurations: ToolchainConfiguration[]
|
||||||
|
): Promise<void> {
|
||||||
|
const toolchains = await import('./toolchains.js');
|
||||||
|
for (const configuration of toolchainConfigurations) {
|
||||||
|
await toolchains.configureToolchains(
|
||||||
|
configuration.version,
|
||||||
|
configuration.distributionName,
|
||||||
|
configuration.path,
|
||||||
|
configuration.toolchainId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function startCacheRestore(
|
async function startCacheRestore(
|
||||||
cache: string,
|
cache: string,
|
||||||
cacheDependencyPath: string,
|
cacheDependencyPath: string,
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export function validateToolchainIds(
|
||||||
|
versions: string[],
|
||||||
|
versionFile: string,
|
||||||
|
toolchainIds: string[]
|
||||||
|
) {
|
||||||
|
if (!toolchainIds.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionCount = versions.length || (versionFile ? 1 : 0);
|
||||||
|
if (versionCount !== toolchainIds.length) {
|
||||||
|
throw new Error(
|
||||||
|
`The number of Maven toolchain IDs (${toolchainIds.length}) must match the number of Java versions (${versionCount})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+213
-86
@@ -4,8 +4,8 @@ import * as path from 'path';
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import * as constants from './constants.js';
|
import * as constants from './constants.js';
|
||||||
|
export {validateToolchainIds} from './toolchain-ids.js';
|
||||||
import {create as xmlCreate} from 'xmlbuilder2';
|
import {escapeXmlAttribute, escapeXmlText} from './xml.js';
|
||||||
|
|
||||||
interface JdkInfo {
|
interface JdkInfo {
|
||||||
version: string;
|
version: string;
|
||||||
@@ -14,23 +14,6 @@ interface JdkInfo {
|
|||||||
jdkHome: string;
|
jdkHome: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateToolchainIds(
|
|
||||||
versions: string[],
|
|
||||||
versionFile: string,
|
|
||||||
toolchainIds: string[]
|
|
||||||
) {
|
|
||||||
if (!toolchainIds.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionCount = versions.length || (versionFile ? 1 : 0);
|
|
||||||
if (versionCount !== toolchainIds.length) {
|
|
||||||
throw new Error(
|
|
||||||
`The number of Maven toolchain IDs (${toolchainIds.length}) must match the number of Java versions (${versionCount})`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function configureToolchains(
|
export async function configureToolchains(
|
||||||
version: string,
|
version: string,
|
||||||
distributionName: string,
|
distributionName: string,
|
||||||
@@ -70,7 +53,7 @@ export async function createToolchainsSettings({
|
|||||||
await io.mkdirP(settingsDirectory);
|
await io.mkdirP(settingsDirectory);
|
||||||
const originalToolchains =
|
const originalToolchains =
|
||||||
await readExistingToolchainsFile(settingsDirectory);
|
await readExistingToolchainsFile(settingsDirectory);
|
||||||
const updatedToolchains = generateToolchainDefinition(
|
const updatedToolchains = await generateToolchainDefinition(
|
||||||
originalToolchains,
|
originalToolchains,
|
||||||
jdkInfo.version,
|
jdkInfo.version,
|
||||||
jdkInfo.vendor,
|
jdkInfo.vendor,
|
||||||
@@ -81,7 +64,27 @@ export async function createToolchainsSettings({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only exported for testing purposes
|
// only exported for testing purposes
|
||||||
export function generateToolchainDefinition(
|
export async function generateToolchainDefinition(
|
||||||
|
original: string,
|
||||||
|
version: string,
|
||||||
|
vendor: string,
|
||||||
|
id: string,
|
||||||
|
jdkHome: string
|
||||||
|
) {
|
||||||
|
if (!original?.length) {
|
||||||
|
return generateNewToolchainDefinition(version, vendor, id, jdkHome);
|
||||||
|
}
|
||||||
|
|
||||||
|
return generateMergedToolchainDefinition(
|
||||||
|
original,
|
||||||
|
version,
|
||||||
|
vendor,
|
||||||
|
id,
|
||||||
|
jdkHome
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateMergedToolchainDefinition(
|
||||||
original: string,
|
original: string,
|
||||||
version: string,
|
version: string,
|
||||||
vendor: string,
|
vendor: string,
|
||||||
@@ -108,62 +111,75 @@ export function generateToolchainDefinition(
|
|||||||
'@xsi:schemaLocation':
|
'@xsi:schemaLocation':
|
||||||
'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd'
|
'http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd'
|
||||||
};
|
};
|
||||||
if (original?.length) {
|
const {XMLParser} = await import('fast-xml-parser');
|
||||||
// convert existing toolchains into TS native objects for better handling
|
const parser = new XMLParser({
|
||||||
// xmlbuilder2 will convert the document into a `{toolchains: { toolchain: [] | {} }}` structure
|
ignoreAttributes: false,
|
||||||
// instead of the desired `toolchains: [{}]` one or simply `[{}]`
|
attributeNamePrefix: '@',
|
||||||
const jsObj = xmlCreate(original)
|
parseAttributeValue: false,
|
||||||
.root()
|
parseTagValue: false,
|
||||||
.toObject() as unknown as ExtractedToolchains;
|
trimValues: true,
|
||||||
if (jsObj.toolchains) {
|
isArray: tagName => tagName === 'toolchain'
|
||||||
// preserve the existing root attributes (xmlns, schemaLocation, …) so we don't
|
});
|
||||||
// silently rewrite user-managed metadata or change the effective XML namespace;
|
const jsObj = parser.parse(original) as ExtractedToolchains;
|
||||||
// xmlbuilder2 exposes attributes as `@`-prefixed keys on the element object
|
if (isToolchainsRoot(jsObj.toolchains)) {
|
||||||
const existingAttributes = Object.fromEntries(
|
// preserve the existing root attributes (xmlns, schemaLocation, …) so we don't
|
||||||
Object.entries(jsObj.toolchains).filter(([key]) => key.startsWith('@'))
|
// silently rewrite user-managed metadata or change the effective XML namespace;
|
||||||
) as Record<string, string>;
|
// fast-xml-parser exposes attributes as `@`-prefixed keys on the element object
|
||||||
// fall back to the defaults only for attributes the existing file is missing
|
const existingAttributes = Object.fromEntries(
|
||||||
rootAttributes = {...rootAttributes, ...existingAttributes};
|
Object.entries(jsObj.toolchains).filter(
|
||||||
|
([key, value]) => key.startsWith('@') && typeof value === 'string'
|
||||||
|
)
|
||||||
|
) as Record<string, string>;
|
||||||
|
// fall back to the defaults only for attributes the existing file is missing
|
||||||
|
rootAttributes = {...rootAttributes, ...existingAttributes};
|
||||||
|
|
||||||
if (jsObj.toolchains.toolchain) {
|
if (jsObj.toolchains.toolchain) {
|
||||||
// in case only a single child exists xmlbuilder2 will not create an array and using verbose = true equally doesn't work here
|
jsToolchains.push(...jsObj.toolchains.toolchain);
|
||||||
// See https://oozcitak.github.io/xmlbuilder2/serialization.html#js-object-and-map-serializers for details
|
|
||||||
if (Array.isArray(jsObj.toolchains.toolchain)) {
|
|
||||||
jsToolchains.push(...jsObj.toolchains.toolchain);
|
|
||||||
} else {
|
|
||||||
jsToolchains.push(jsObj.toolchains.toolchain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove potential duplicates based on type & id (which should be a unique combination);
|
|
||||||
// self.findIndex will only return the first occurrence, ensuring duplicates are skipped
|
|
||||||
jsToolchains = jsToolchains.filter(
|
|
||||||
(value, index, self) =>
|
|
||||||
// ensure non-jdk toolchains are kept in the results, we must not touch them because they belong to the user
|
|
||||||
value.type !== 'jdk' ||
|
|
||||||
// keep toolchains that lack a usable string id (e.g. partially-formed user files);
|
|
||||||
// we cannot safely deduplicate them and must not crash while reading them
|
|
||||||
typeof value.provides?.id !== 'string' ||
|
|
||||||
index ===
|
|
||||||
self.findIndex(
|
|
||||||
t => t.type === value.type && t.provides?.id === value.provides?.id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xmlCreate({
|
// remove potential duplicates based on type & id (which should be a unique combination);
|
||||||
toolchains: {
|
// self.findIndex will only return the first occurrence, ensuring duplicates are skipped
|
||||||
...rootAttributes,
|
jsToolchains = jsToolchains.filter(
|
||||||
toolchain: jsToolchains
|
(value, index, self) =>
|
||||||
}
|
// ensure non-jdk toolchains are kept in the results, we must not touch them because they belong to the user
|
||||||
}).end({
|
value.type !== 'jdk' ||
|
||||||
format: 'xml',
|
// keep toolchains that lack a usable string id (e.g. partially-formed user files);
|
||||||
wellFormed: false,
|
// we cannot safely deduplicate them and must not crash while reading them
|
||||||
headless: false,
|
typeof value.provides?.id !== 'string' ||
|
||||||
prettyPrint: true,
|
index ===
|
||||||
width: 80
|
self.findIndex(
|
||||||
});
|
t => t.type === value.type && t.provides?.id === value.provides?.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return serializeToolchains(rootAttributes, jsToolchains);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateNewToolchainDefinition(
|
||||||
|
version: string,
|
||||||
|
vendor: string,
|
||||||
|
id: string,
|
||||||
|
jdkHome: string
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
'<?xml version="1.0"?>',
|
||||||
|
'<toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0"',
|
||||||
|
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
|
||||||
|
' xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd">',
|
||||||
|
' <toolchain>',
|
||||||
|
' <type>jdk</type>',
|
||||||
|
' <provides>',
|
||||||
|
` <version>${escapeXmlText(version)}</version>`,
|
||||||
|
` <vendor>${escapeXmlText(vendor)}</vendor>`,
|
||||||
|
` <id>${escapeXmlText(id)}</id>`,
|
||||||
|
' </provides>',
|
||||||
|
' <configuration>',
|
||||||
|
` <jdkHome>${escapeXmlText(jdkHome)}</jdkHome>`,
|
||||||
|
' </configuration>',
|
||||||
|
' </toolchain>',
|
||||||
|
'</toolchains>'
|
||||||
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readExistingToolchainsFile(directory: string) {
|
async function readExistingToolchainsFile(directory: string) {
|
||||||
@@ -198,23 +214,134 @@ async function writeToolchainsFileToDisk(directory: string, settings: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function serializeToolchains(
|
||||||
|
rootAttributes: Record<string, string>,
|
||||||
|
toolchains: Toolchain[]
|
||||||
|
) {
|
||||||
|
return [
|
||||||
|
'<?xml version="1.0"?>',
|
||||||
|
serializeOpeningTag('toolchains', rootAttributes, 0),
|
||||||
|
...toolchains.flatMap(toolchain =>
|
||||||
|
serializeXmlElement('toolchain', toolchain, 1)
|
||||||
|
),
|
||||||
|
'</toolchains>'
|
||||||
|
].join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeOpeningTag(
|
||||||
|
name: string,
|
||||||
|
attributes: Record<string, string>,
|
||||||
|
depth: number
|
||||||
|
) {
|
||||||
|
const indent = ' '.repeat(depth);
|
||||||
|
const attributeEntries = Object.entries(attributes);
|
||||||
|
if (!attributeEntries.length) {
|
||||||
|
return `${indent}<${name}>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [firstAttribute, ...restAttributes] = attributeEntries;
|
||||||
|
const lines = [
|
||||||
|
`${indent}<${name} ${formatXmlAttribute(firstAttribute)}`,
|
||||||
|
...restAttributes.map(([attributeName, value]) => {
|
||||||
|
return `${indent} ${formatXmlAttribute([attributeName, value])}`;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
lines[lines.length - 1] += '>';
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeXmlElement(
|
||||||
|
name: string,
|
||||||
|
value: XmlElementValue,
|
||||||
|
depth: number
|
||||||
|
): string[] {
|
||||||
|
const indent = ' '.repeat(depth);
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.flatMap(item => serializeXmlElement(name, item, depth));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isXmlElementObject(value)) {
|
||||||
|
return [
|
||||||
|
`${indent}<${name}>${escapeXmlText(String(value ?? ''))}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const attributes = Object.fromEntries(
|
||||||
|
Object.entries(value)
|
||||||
|
.filter(([key, attributeValue]) => {
|
||||||
|
return key.startsWith('@') && typeof attributeValue === 'string';
|
||||||
|
})
|
||||||
|
.map(([key, attributeValue]) => [key, attributeValue as string])
|
||||||
|
);
|
||||||
|
const childEntries = Object.entries(value).filter(
|
||||||
|
([key]) => !key.startsWith('@') && key !== '#text'
|
||||||
|
);
|
||||||
|
const textValue = value['#text'];
|
||||||
|
|
||||||
|
if (!childEntries.length) {
|
||||||
|
if (textValue !== undefined) {
|
||||||
|
return [
|
||||||
|
`${serializeOpeningTag(name, attributes, depth)}${escapeXmlText(
|
||||||
|
String(textValue ?? '')
|
||||||
|
)}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [`${serializeOpeningTag(name, attributes, depth)}</${name}>`];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
serializeOpeningTag(name, attributes, depth),
|
||||||
|
...(textValue === undefined
|
||||||
|
? []
|
||||||
|
: [`${' '.repeat(depth + 1)}${escapeXmlText(String(textValue ?? ''))}`]),
|
||||||
|
...childEntries.flatMap(([childName, childValue]) =>
|
||||||
|
serializeXmlElement(childName, childValue, depth + 1)
|
||||||
|
),
|
||||||
|
`${indent}</${name}>`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatXmlAttribute([name, value]: [string, string]) {
|
||||||
|
return `${name.slice(1)}="${escapeXmlAttribute(value)}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isToolchainsRoot(value: ExtractedToolchains['toolchains']) {
|
||||||
|
return isXmlElementObject(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isXmlElementObject(
|
||||||
|
value: unknown
|
||||||
|
): value is Record<string, XmlElementValue> {
|
||||||
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
interface ExtractedToolchains {
|
interface ExtractedToolchains {
|
||||||
toolchains: {
|
toolchains: ToolchainsRoot | string;
|
||||||
// root attributes such as xmlns / schemaLocation are exposed as `@`-prefixed keys
|
}
|
||||||
[attribute: `@${string}`]: string;
|
|
||||||
toolchain?: Toolchain[] | Toolchain;
|
interface ToolchainsRoot extends XmlElementObject {
|
||||||
};
|
// root attributes such as xmlns / schemaLocation are exposed as `@`-prefixed keys
|
||||||
|
[attribute: `@${string}`]: string;
|
||||||
|
toolchain?: Toolchain[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toolchain type definition according to Maven Toolchains XSD 1.1.0
|
// Toolchain type definition according to Maven Toolchains XSD 1.1.0
|
||||||
interface Toolchain {
|
interface Toolchain {
|
||||||
type: string;
|
type: string;
|
||||||
provides:
|
provides?: XmlElementObject;
|
||||||
| {
|
configuration?: XmlElementObject;
|
||||||
version: string;
|
[customElement: string]: XmlElementValue;
|
||||||
vendor: string;
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
| any;
|
|
||||||
configuration: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface XmlElementObject {
|
||||||
|
[name: string]: XmlElementValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
type XmlElementValue =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
| XmlElementObject
|
||||||
|
| XmlElementValue[];
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
export function escapeXmlText(value: string): string {
|
||||||
|
return value
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use for user-controlled values written into XML attributes. Text nodes should
|
||||||
|
// use escapeXmlText so quotes remain byte-compatible with previous output.
|
||||||
|
export function escapeXmlAttribute(value: string): string {
|
||||||
|
return escapeXmlText(value).replace(/"/g, '"').replace(/'/g, ''');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user