Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -56,6 +56,8 @@ For more details, see the full release notes on the [releases page](https://git

- `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 @@ -52241,7 +52241,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 @@ -52250,6 +52250,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 @@ -77676,7 +77676,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 @@ -77688,9 +77688,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 @@ -77701,7 +77699,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 @@ -77710,34 +77708,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 @@ -77752,6 +77753,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 @@ -78000,7 +78037,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 @@ -78009,6 +78046,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