diff --git a/__tests__/auth.test.ts b/__tests__/auth.test.ts index b460e93..77e0cd6 100644 --- a/__tests__/auth.test.ts +++ b/__tests__/auth.test.ts @@ -38,7 +38,7 @@ describe('auth tests', () => { process.env[`INPUT_SETTINGS-PATH`] = altHome; await io.rmRF(altHome); // ensure it doesn't already exist - await auth.configAuthentication(id, username, password); + await auth.configAuthentication([id], username, password); expect(fs.existsSync(m2Dir)).toBe(false); expect(fs.existsSync(settingsFile)).toBe(false); @@ -46,7 +46,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) ); delete process.env[`INPUT_SETTINGS-PATH`]; @@ -58,12 +58,27 @@ describe('auth tests', () => { const username = 'UNAME'; const password = 'TOKEN'; - await auth.configAuthentication(id, username, password); + await auth.configAuthentication([id], username, password); 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); + + it('creates settings.xml with minimal configuration and multiple servers', async () => { + const id1 = 'packages-1'; + const id2 = 'packages-2'; + const username = 'UNAME'; + const password = 'TOKEN'; + + await auth.configAuthentication([id1, id2], username, password); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(settingsFile)).toBe(true); + expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual( + auth.generate([id1, id2], username, password) ); }, 100000); @@ -73,12 +88,33 @@ describe('auth tests', () => { const password = 'TOKEN'; const gpgPassphrase = 'GPG'; - await auth.configAuthentication(id, username, password, gpgPassphrase); + await auth.configAuthentication([id], username, password, gpgPassphrase); 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); + + it('creates settings.xml with additional configuration and multiple servers', async () => { + const id1 = 'packages-1'; + const id2 = 'packages-2'; + const username = 'UNAME'; + const password = 'TOKEN'; + const gpgPassphrase = 'GPG'; + + await auth.configAuthentication( + [id1, id2], + username, + password, + gpgPassphrase + ); + + expect(fs.existsSync(m2Dir)).toBe(true); + expect(fs.existsSync(settingsFile)).toBe(true); + expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual( + auth.generate([id1, id2], username, password, gpgPassphrase) ); }, 100000); @@ -92,12 +128,12 @@ describe('auth tests', () => { expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); - await auth.configAuthentication(id, username, password); + await auth.configAuthentication([id], username, password); 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); @@ -118,7 +154,35 @@ describe('auth tests', () => { `; - expect(auth.generate(id, username, password)).toEqual(expectedSettings); + expect(auth.generate([id], username, password)).toEqual(expectedSettings); + }); + + it('generates valid settings.xml with minimal configuration and multiple servers', () => { + const id1 = 'packages-1'; + const id2 = 'packages-2'; + const username = 'USER'; + const password = '&<>"\'\'"><&'; + + const expectedSettings = ` + + + ${id1} + \${env.${username}} + \${env.&<>"''"><&} + + + ${id2} + \${env.${username}} + \${env.&<>"''"><&} + + +`; + + expect(auth.generate([id1, id2], username, password)).toEqual( + expectedSettings + ); }); it('generates valid settings.xml with additional configuration', () => { @@ -143,8 +207,85 @@ describe('auth tests', () => { `; - expect(auth.generate(id, username, password, gpgPassphrase)).toEqual( + expect(auth.generate([id], username, password, gpgPassphrase)).toEqual( expectedSettings ); }); + + it('generates valid settings.xml with additional configuration and multiple servers', () => { + const id1 = 'packages-1'; + const id2 = 'packages-2'; + const username = 'USER'; + const password = '&<>"\'\'"><&'; + const gpgPassphrase = 'PASSPHRASE'; + + const expectedSettings = ` + + + ${id1} + \${env.${username}} + \${env.&<>"''"><&} + + + ${id2} + \${env.${username}} + \${env.&<>"''"><&} + + + gpg.passphrase + \${env.${gpgPassphrase}} + + +`; + + expect( + auth.generate([id1, id2], username, password, gpgPassphrase) + ).toEqual(expectedSettings); + }); + + it('generates valid settings.xml with additional configuration and multiple servers, sorting alphabetically and removing duplicates', () => { + const id1 = 'packages-1'; + const id2 = 'packages-2'; + const id3 = 'packages-3'; + const username = 'USER'; + const password = '&<>"\'\'"><&'; + const gpgPassphrase = 'PASSPHRASE'; + + const expectedSettings = ` + + + ${id1} + \${env.${username}} + \${env.&<>"''"><&} + + + ${id2} + \${env.${username}} + \${env.&<>"''"><&} + + + ${id3} + \${env.${username}} + \${env.&<>"''"><&} + + + gpg.passphrase + \${env.${gpgPassphrase}} + + +`; + + expect( + auth.generate( + [id3, id3, id1, id2, id1, id2, id3], + username, + password, + gpgPassphrase + ) + ).toEqual(expectedSettings); + }); }); diff --git a/action.yml b/action.yml index 7457268..e1daf5d 100644 --- a/action.yml +++ b/action.yml @@ -26,6 +26,10 @@ inputs: file. Default is `github`' required: false default: 'github' + server-id-list: + description: 'IDs of the repositories in the pom.xml file. Default is `github`' + required: false + default: 'github' server-username: description: 'Environment variable name for the username for authentication to the Apache Maven repository. Default is $GITHUB_ACTOR' diff --git a/dist/cleanup/index.js b/dist/cleanup/index.js index 6647ad5..888ba78 100644 --- a/dist/cleanup/index.js +++ b/dist/cleanup/index.js @@ -960,6 +960,7 @@ exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_JDK_FILE = 'jdkFile'; exports.INPUT_SERVER_ID = 'server-id'; +exports.INPUT_SERVER_ID_LIST = 'server-id-list'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; exports.INPUT_SETTINGS_PATH = 'settings-path'; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index d77e3be..0000000 Binary files a/dist/index.js and /dev/null differ diff --git a/dist/setup/index.js b/dist/setup/index.js index 3beeeec..2c36115 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -13207,33 +13207,38 @@ const xmlbuilder2_1 = __webpack_require__(255); const constants = __importStar(__webpack_require__(694)); exports.M2_DIR = '.m2'; exports.SETTINGS_FILE = 'settings.xml'; -function configAuthentication(id, username, password, gpgPassphrase = undefined) { +function configAuthentication(idArray, username, password, gpgPassphrase = undefined) { return __awaiter(this, void 0, void 0, function* () { - console.log(`creating ${exports.SETTINGS_FILE} with server-id: ${id};`, 'environment variables:', `username=\$${username},`, `password=\$${password},`, `and gpg-passphrase=${gpgPassphrase ? '$' + gpgPassphrase : null}`); + console.log(`creating ${exports.SETTINGS_FILE} with server-id: ${idArray.join(', ')};`, 'environment variables:', `username=\$${username},`, `password=\$${password},`, `and gpg-passphrase=${gpgPassphrase ? '$' + gpgPassphrase : null}`); // when an alternate m2 location is specified use only that location (no .m2 directory) // otherwise use the home/.m2/ path const settingsDirectory = path.join(core.getInput(constants.INPUT_SETTINGS_PATH) || os.homedir(), core.getInput(constants.INPUT_SETTINGS_PATH) ? '' : exports.M2_DIR); yield io.mkdirP(settingsDirectory); core.debug(`created directory ${settingsDirectory}`); - yield write(settingsDirectory, generate(id, username, password, gpgPassphrase)); + yield write(settingsDirectory, generate(idArray, username, password, gpgPassphrase)); }); } exports.configAuthentication = configAuthentication; // only exported for testing purposes -function generate(id, username, password, gpgPassphrase = undefined) { +function generate(idArray, username, password, gpgPassphrase = undefined) { + const idArrayUnique = idArray + .sort() + .reduce((idArray, id, index, idArrayInput) => { + return idArray[idArray.length - 1] === id ? idArray : idArray.concat(id); + }, new Array()); 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: [ - { + server: idArrayUnique.map((id, index, idArray) => { + return { id: id, username: `\${env.${username}}`, password: `\${env.${password}}` - } - ] + }; + }) } } }; @@ -25660,6 +25665,7 @@ exports.INPUT_ARCHITECTURE = 'architecture'; exports.INPUT_JAVA_PACKAGE = 'java-package'; exports.INPUT_JDK_FILE = 'jdkFile'; exports.INPUT_SERVER_ID = 'server-id'; +exports.INPUT_SERVER_ID_LIST = 'server-id-list'; exports.INPUT_SERVER_USERNAME = 'server-username'; exports.INPUT_SERVER_PASSWORD = 'server-password'; exports.INPUT_SETTINGS_PATH = 'settings-path'; @@ -28693,6 +28699,10 @@ function run() { const matchersPath = path.join(__dirname, '..', '..', '.github'); core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); const id = core.getInput(constants.INPUT_SERVER_ID, { required: false }); + const idList = core + .getInput(constants.INPUT_SERVER_ID_LIST, { required: false }) + .split(',') + .map(id => id.trim()); const username = core.getInput(constants.INPUT_SERVER_USERNAME, { required: false }); @@ -28706,7 +28716,7 @@ function run() { if (gpgPrivateKey) { core.setSecret(gpgPrivateKey); } - yield auth.configAuthentication(id, username, password, gpgPassphrase); + yield auth.configAuthentication(idList.concat(id), username, password, gpgPassphrase); if (gpgPrivateKey) { core.info('importing private key'); const keyFingerprint = (yield gpg.importKey(gpgPrivateKey)) || ''; diff --git a/dist/setup/unzip b/dist/setup/unzip deleted file mode 100644 index 4082418..0000000 Binary files a/dist/setup/unzip and /dev/null differ diff --git a/src/auth.ts b/src/auth.ts index 9681049..50d8694 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -10,13 +10,13 @@ export const M2_DIR = '.m2'; export const SETTINGS_FILE = 'settings.xml'; export async function configAuthentication( - id: string, + idArray: string[], username: string, password: string, gpgPassphrase: string | undefined = undefined ) { console.log( - `creating ${SETTINGS_FILE} with server-id: ${id};`, + `creating ${SETTINGS_FILE} with server-id: ${idArray.join(', ')};`, 'environment variables:', `username=\$${username},`, `password=\$${password},`, @@ -32,17 +32,23 @@ export async function configAuthentication( core.debug(`created directory ${settingsDirectory}`); await write( settingsDirectory, - generate(id, username, password, gpgPassphrase) + generate(idArray, username, password, gpgPassphrase) ); } // only exported for testing purposes export function generate( - id: string, + idArray: string[], username: string, password: string, gpgPassphrase: string | undefined = undefined ) { + const idArrayUnique = idArray + .sort() + .reduce((idArray, id, index, idArrayInput) => { + return idArray[idArray.length - 1] === id ? idArray : idArray.concat(id); + }, new Array()); + const xmlObj: {[key: string]: any} = { settings: { '@xmlns': 'http://maven.apache.org/SETTINGS/1.0.0', @@ -50,13 +56,13 @@ export function generate( '@xsi:schemaLocation': 'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd', servers: { - server: [ - { + server: idArrayUnique.map((id, index, idArray) => { + return { id: id, username: `\${env.${username}}`, password: `\${env.${password}}` - } - ] + }; + }) } } }; diff --git a/src/constants.ts b/src/constants.ts index 2e885cf..d403e1e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,6 +4,7 @@ export const INPUT_ARCHITECTURE = 'architecture'; export const INPUT_JAVA_PACKAGE = 'java-package'; export const INPUT_JDK_FILE = 'jdkFile'; export const INPUT_SERVER_ID = 'server-id'; +export const INPUT_SERVER_ID_LIST = 'server-id-list'; export const INPUT_SERVER_USERNAME = 'server-username'; export const INPUT_SERVER_PASSWORD = 'server-password'; export const INPUT_SETTINGS_PATH = 'settings-path'; diff --git a/src/setup-java.ts b/src/setup-java.ts index db169f2..7233924 100644 --- a/src/setup-java.ts +++ b/src/setup-java.ts @@ -23,6 +23,10 @@ async function run() { core.info(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); const id = core.getInput(constants.INPUT_SERVER_ID, {required: false}); + const idList = core + .getInput(constants.INPUT_SERVER_ID_LIST, {required: false}) + .split(',') + .map(id => id.trim()); const username = core.getInput(constants.INPUT_SERVER_USERNAME, { required: false }); @@ -40,7 +44,12 @@ async function run() { core.setSecret(gpgPrivateKey); } - await auth.configAuthentication(id, username, password, gpgPassphrase); + await auth.configAuthentication( + idList.concat(id), + username, + password, + gpgPassphrase + ); if (gpgPrivateKey) { core.info('importing private key');