Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ For information about the latest releases, recent updates, and newly supported d

- `server-password`: Environment variable name for password or token for authentication to the Apache Maven repository. Default is GITHUB_TOKEN.

- `mvn-server-credentials`: Optional multiline list of Maven server credentials in the format `server-id:USERNAME_ENV:PASSWORD_ENV`. When set, this input overrides `server-id`/`server-username`/`server-password` and generates multiple `<server>` entries in `settings.xml`.

- `settings-path`: Maven related setting to point to the directory where the settings.xml file will be written. Default is ~/.m2.

- `gpg-private-key`: GPG private key to import. Default is empty string.
Expand Down
104 changes: 83 additions & 21 deletions __tests__/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ describe('auth tests', () => {
await io.rmRF(altHome); // ensure it doesn't already exist

await auth.createAuthenticationSettings(
id,
username,
password,
[{id, username, password}],
altHome,
true
);
Expand All @@ -56,7 +54,7 @@ describe('auth tests', () => {
expect(fs.existsSync(altHome)).toBe(true);
expect(fs.existsSync(altSettingsFile)).toBe(true);
expect(fs.readFileSync(altSettingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
auth.generate([{id, username, password}])
);

await io.rmRF(altHome);
Expand All @@ -68,17 +66,15 @@ describe('auth tests', () => {
const password = 'TOKEN';

await auth.createAuthenticationSettings(
id,
username,
password,
[{id, username, password}],
m2Dir,
true
);

expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
auth.generate([{id, username, password}])
);
}, 100000);

Expand All @@ -89,9 +85,7 @@ describe('auth tests', () => {
const gpgPassphrase = 'GPG';

await auth.createAuthenticationSettings(
id,
username,
password,
[{id, username, password}],
m2Dir,
true,
gpgPassphrase
Expand All @@ -100,7 +94,7 @@ describe('auth tests', () => {
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password, gpgPassphrase)
auth.generate([{id, username, password}], gpgPassphrase)
);
}, 100000);

Expand All @@ -115,17 +109,15 @@ describe('auth tests', () => {
expect(fs.existsSync(settingsFile)).toBe(true);

await auth.createAuthenticationSettings(
id,
username,
password,
[{id, username, password}],
m2Dir,
true
);

expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(id, username, password)
auth.generate([{id, username, password}])
);
}, 100000);

Expand All @@ -140,9 +132,7 @@ describe('auth tests', () => {
expect(fs.existsSync(settingsFile)).toBe(true);

await auth.createAuthenticationSettings(
id,
username,
password,
[{id, username, password}],
m2Dir,
false
);
Expand All @@ -169,7 +159,7 @@ describe('auth tests', () => {
</servers>
</settings>`;

expect(auth.generate(id, username, password)).toEqual(expectedSettings);
expect(auth.generate([{id, username, password}])).toEqual(expectedSettings);
});

it('generates valid settings.xml with additional configuration', () => {
Expand All @@ -194,8 +184,80 @@ describe('auth tests', () => {
</servers>
</settings>`;

expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
expect(auth.generate([{id, username, password}], gpgPassphrase)).toEqual(
expectedSettings
);
});

it('generates valid settings.xml for multiple repositories', () => {
const id0 = 'packages0';
const username0 = 'USER0';
const password0 = '&<>"\'\'"><&0';
const id1 = 'packages1';
const username1 = 'USER1';
const password1 = '&<>"\'\'"><&1';
const gpgPassphrase = 'PASSPHRASE';

const expectedSettings = `<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">
<servers>
<server>
<id>${id0}</id>
<username>\${env.${username0}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;0}</password>
</server>
<server>
<id>${id1}</id>
<username>\${env.${username1}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;1}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${gpgPassphrase}}</passphrase>
</server>
</servers>
</settings>`;

expect(
auth.generate(
[
{id: id0, username: username0, password: password0},
{id: id1, username: username1, password: password1}
],
gpgPassphrase
)
).toEqual(expectedSettings);
});

it('parses mvn-server-credentials multiline entries', () => {
const parsed = auth.parseMavenServerCredentials([
'releases:RELEASE_USER:RELEASE_TOKEN',
'snapshots:SNAPSHOT_USER:SNAPSHOT_TOKEN'
]);

expect(parsed).toEqual([
{id: 'releases', username: 'RELEASE_USER', password: 'RELEASE_TOKEN'},
{
id: 'snapshots',
username: 'SNAPSHOT_USER',
password: 'SNAPSHOT_TOKEN'
}
]);
});

it('fails on invalid mvn-server-credentials format', () => {
expect(() =>
auth.parseMavenServerCredentials(['releases:RELEASE_USER'])
).toThrow('Expected format: server-id:USERNAME_ENV:PASSWORD_ENV');
});

it('fails on duplicate server ids in mvn-server-credentials', () => {
expect(() =>
auth.parseMavenServerCredentials([
'releases:RELEASE_USER:RELEASE_TOKEN',
'releases:OTHER_USER:OTHER_TOKEN'
])
).toThrow("Duplicate server-id 'releases'");
});
});
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ inputs:
authentication to the Apache Maven repository. Default is $GITHUB_TOKEN'
required: false
default: 'GITHUB_TOKEN'
mvn-server-credentials:
description: 'Optional multiline list of Maven server credentials in the format "server-id:USERNAME_ENV:PASSWORD_ENV". When provided, this overrides server-id/server-username/server-password and writes multiple <server> entries in settings.xml.'
required: false
settings-path:
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
required: false
Expand Down
3 changes: 2 additions & 1 deletion dist/cleanup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52046,7 +52046,7 @@ else {
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_MVN_SERVER_CREDENTIALS = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
exports.INPUT_JAVA_VERSION = 'java-version';
exports.INPUT_JAVA_VERSION_FILE = 'java-version-file';
Expand All @@ -52055,6 +52055,7 @@ exports.INPUT_JAVA_PACKAGE = 'java-package';
exports.INPUT_DISTRIBUTION = 'distribution';
exports.INPUT_JDK_FILE = 'jdkFile';
exports.INPUT_CHECK_LATEST = 'check-latest';
exports.INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
exports.INPUT_SERVER_ID = 'server-id';
exports.INPUT_SERVER_USERNAME = 'server-username';
exports.INPUT_SERVER_PASSWORD = 'server-password';
Expand Down
72 changes: 55 additions & 17 deletions dist/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77481,7 +77481,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.generate = exports.createAuthenticationSettings = exports.configureAuthentication = void 0;
exports.parseMavenServerCredentials = exports.generate = exports.createAuthenticationSettings = exports.configureAuthentication = void 0;
const path = __importStar(__nccwpck_require__(16928));
const core = __importStar(__nccwpck_require__(37484));
const io = __importStar(__nccwpck_require__(94994));
Expand All @@ -77493,9 +77493,7 @@ const gpg = __importStar(__nccwpck_require__(88343));
const util_1 = __nccwpck_require__(54527);
function configureAuthentication() {
return __awaiter(this, void 0, void 0, function* () {
const id = core.getInput(constants.INPUT_SERVER_ID);
const username = core.getInput(constants.INPUT_SERVER_USERNAME);
const password = core.getInput(constants.INPUT_SERVER_PASSWORD);
const mvnSettings = getMavenServerSettings();
const settingsDirectory = core.getInput(constants.INPUT_SETTINGS_PATH) ||
path.join(os.homedir(), constants.M2_DIR);
const overwriteSettings = (0, util_1.getBooleanInput)(constants.INPUT_OVERWRITE_SETTINGS, true);
Expand All @@ -77506,7 +77504,7 @@ function configureAuthentication() {
if (gpgPrivateKey) {
core.setSecret(gpgPrivateKey);
}
yield createAuthenticationSettings(id, username, password, settingsDirectory, overwriteSettings, gpgPassphrase);
yield createAuthenticationSettings(mvnSettings, settingsDirectory, overwriteSettings, gpgPassphrase);
if (gpgPrivateKey) {
core.info('Importing private gpg key');
const keyFingerprint = (yield gpg.importKey(gpgPrivateKey)) || '';
Expand All @@ -77515,34 +77513,37 @@ function configureAuthentication() {
});
}
exports.configureAuthentication = configureAuthentication;
function createAuthenticationSettings(id, username, password, settingsDirectory, overwriteSettings, gpgPassphrase = undefined) {
function createAuthenticationSettings(mvnSettings, settingsDirectory, overwriteSettings, gpgPassphrase = undefined) {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Creating ${constants.MVN_SETTINGS_FILE} with server-id: ${id}`);
core.info(`Creating ${constants.MVN_SETTINGS_FILE}`);
// when an alternate m2 location is specified use only that location (no .m2 directory)
// otherwise use the home/.m2/ path
yield io.mkdirP(settingsDirectory);
yield write(settingsDirectory, generate(id, username, password, gpgPassphrase), overwriteSettings);
yield write(settingsDirectory, generate(mvnSettings, gpgPassphrase), overwriteSettings);
});
}
exports.createAuthenticationSettings = createAuthenticationSettings;
// only exported for testing purposes
function generate(id, username, password, gpgPassphrase) {
function generate(mvnSettings, gpgPassphrase) {
const xmlObj = {
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',
servers: {
server: [
{
id: id,
username: `\${env.${username}}`,
password: `\${env.${password}}`
}
]
server: []
}
}
};
for (const mvnSetting of mvnSettings) {
if (mvnSetting.username && mvnSetting.password) {
xmlObj.settings.servers.server.push({
id: mvnSetting.id,
username: `\${env.${mvnSetting.username}}`,
password: `\${env.${mvnSetting.password}}`
});
}
}
if (gpgPassphrase) {
const gpgServer = {
id: 'gpg.passphrase',
Expand All @@ -77557,6 +77558,42 @@ function generate(id, username, password, gpgPassphrase) {
});
}
exports.generate = generate;
function getMavenServerSettings() {
const multilineEntries = core
.getMultilineInput(constants.INPUT_MVN_SERVER_CREDENTIALS)
.map(entry => entry.trim())
.filter(Boolean);
if (multilineEntries.length > 0) {
return parseMavenServerCredentials(multilineEntries);
}
const id = core.getInput(constants.INPUT_SERVER_ID);
const username = core.getInput(constants.INPUT_SERVER_USERNAME);
const password = core.getInput(constants.INPUT_SERVER_PASSWORD);
return [{ id, username, password }];
}
// only exported for testing purposes
function parseMavenServerCredentials(entries) {
const parsed = entries.map((entry, index) => {
const parts = entry.split(':');
if (parts.length !== 3) {
throw new Error(`Invalid mvn-server-credentials entry at line ${index + 1}. Expected format: server-id:USERNAME_ENV:PASSWORD_ENV`);
}
const [id, username, password] = parts.map(part => part.trim());
if (!id || !username || !password) {
throw new Error(`Invalid mvn-server-credentials entry at line ${index + 1}. server-id, username env, and password env are required`);
}
return { id, username, password };
});
const ids = new Set();
for (const setting of parsed) {
if (ids.has(setting.id)) {
throw new Error(`Duplicate server-id '${setting.id}' in mvn-server-credentials input`);
}
ids.add(setting.id);
}
return parsed;
}
exports.parseMavenServerCredentials = parseMavenServerCredentials;
function write(directory, settings, overwriteSettings) {
return __awaiter(this, void 0, void 0, function* () {
const location = path.join(directory, constants.MVN_SETTINGS_FILE);
Expand Down Expand Up @@ -77805,7 +77842,7 @@ function isProbablyGradleDaemonProblem(packageManager, error) {
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.DISTRIBUTIONS_ONLY_MAJOR_VERSION = exports.INPUT_MVN_TOOLCHAIN_VENDOR = exports.INPUT_MVN_TOOLCHAIN_ID = exports.MVN_TOOLCHAINS_FILE = exports.MVN_SETTINGS_FILE = exports.M2_DIR = exports.STATE_GPG_PRIVATE_KEY_FINGERPRINT = exports.INPUT_JOB_STATUS = exports.INPUT_CACHE_DEPENDENCY_PATH = exports.INPUT_CACHE = exports.INPUT_DEFAULT_GPG_PASSPHRASE = exports.INPUT_DEFAULT_GPG_PRIVATE_KEY = exports.INPUT_GPG_PASSPHRASE = exports.INPUT_GPG_PRIVATE_KEY = exports.INPUT_OVERWRITE_SETTINGS = exports.INPUT_SETTINGS_PATH = exports.INPUT_SERVER_PASSWORD = exports.INPUT_SERVER_USERNAME = exports.INPUT_SERVER_ID = exports.INPUT_MVN_SERVER_CREDENTIALS = exports.INPUT_CHECK_LATEST = exports.INPUT_JDK_FILE = exports.INPUT_DISTRIBUTION = exports.INPUT_JAVA_PACKAGE = exports.INPUT_ARCHITECTURE = exports.INPUT_JAVA_VERSION_FILE = exports.INPUT_JAVA_VERSION = exports.MACOS_JAVA_CONTENT_POSTFIX = void 0;
exports.MACOS_JAVA_CONTENT_POSTFIX = 'Contents/Home';
exports.INPUT_JAVA_VERSION = 'java-version';
exports.INPUT_JAVA_VERSION_FILE = 'java-version-file';
Expand All @@ -77814,6 +77851,7 @@ exports.INPUT_JAVA_PACKAGE = 'java-package';
exports.INPUT_DISTRIBUTION = 'distribution';
exports.INPUT_JDK_FILE = 'jdkFile';
exports.INPUT_CHECK_LATEST = 'check-latest';
exports.INPUT_MVN_SERVER_CREDENTIALS = 'mvn-server-credentials';
exports.INPUT_SERVER_ID = 'server-id';
exports.INPUT_SERVER_USERNAME = 'server-username';
exports.INPUT_SERVER_PASSWORD = 'server-password';
Expand Down
Loading
Loading