diff --git a/__tests__/auth.test.ts b/__tests__/auth.test.ts index 58b1134b..2bfdd99a 100644 --- a/__tests__/auth.test.ts +++ b/__tests__/auth.test.ts @@ -66,7 +66,21 @@ describe('auth tests', () => { await io.rmRF(altHome); }, 100000); - it('creates settings.xml with all data', async () => { + it('creates settings.xml with minimal configuration', async () => { + const id = 'packages'; + const username = 'UNAME'; + const password = 'TOKEN'; + + 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) + ); + }, 100000); + + it('creates settings.xml with gpg data', async () => { const id = 'packages'; const username = 'UNAME'; const password = 'TOKEN'; @@ -145,27 +159,41 @@ describe('auth tests', () => { ); }, 100000); - it('escapes invalid XML inputs', () => { + it('generates valid settings.xml', () => { const id = 'packages'; const username = 'USER'; const password = '&<>"\'\'"><&'; const gpgPassphrase = 'PASSPHRASE'; - expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(` - - - - ${id} - \${env.${username}} - \${env.&<>"''"><&} - - - gpg.passphrase - \${env.${gpgPassphrase}} - - - - `); + const expectedSettings = ` + + + ${id} + \${env.${username}} + \${env.&<>"''"><&} + + + gpg.passphrase + \${env.${gpgPassphrase}} + + + + + + true + + + ${tempDir} + + + +`; + + expect(auth.generate(id, username, password, gpgPassphrase)).toEqual( + expectedSettings + ); }); it('imports gpg private key', async () => { diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index d7809b51..f93c4f48 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -10,7 +10,7 @@ describe('util tests', () => { describe('getTempDir', () => { it('gets temp dir using env', () => { - process.env['RUNNER_TEMP'] = 'defaulttmp' + process.env['RUNNER_TEMP'] = 'defaulttmp'; const util = require('../src/util'); const tempDir = util.getTempDir(); @@ -25,7 +25,9 @@ describe('util tests', () => { const tempDir = util.getTempDir(); - expect(tempDir).toEqual(path.join(process.env['USERPROFILE'], 'actions', 'temp')); + expect(tempDir).toEqual( + path.join(process.env['USERPROFILE'], 'actions', 'temp') + ); }); it('gets temp dir for windows using c drive', () => { diff --git a/dist/index.js b/dist/index.js index c879345f..a6afd712 100644 Binary files a/dist/index.js and b/dist/index.js differ diff --git a/package-lock.json b/package-lock.json index 66e0b6d4..b534287b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -430,6 +430,74 @@ "@types/yargs": "^13.0.0" } }, + "@oozcitak/dom": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.5.tgz", + "integrity": "sha512-L6v3Mwb0TaYBYgeYlIeBaHnc+2ZEaDSbFiRm5KmqZQSoBlbPlf+l6aIH/sD5GUf2MYwULw00LT7+dOnEuAEC0A==", + "requires": { + "@oozcitak/infra": "1.0.5", + "@oozcitak/url": "1.0.0", + "@oozcitak/util": "8.0.0" + }, + "dependencies": { + "@oozcitak/util": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz", + "integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw==" + } + } + }, + "@oozcitak/infra": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.5.tgz", + "integrity": "sha512-o+zZH7M6l5e3FaAWy3ojaPIVN5eusaYPrKm6MZQt0DKNdgXa2wDYExjpP0t/zx+GoQgQKzLu7cfD8rHCLt8JrQ==", + "requires": { + "@oozcitak/util": "8.0.0" + }, + "dependencies": { + "@oozcitak/util": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.0.0.tgz", + "integrity": "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw==" + } + } + }, + "@oozcitak/url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.0.tgz", + "integrity": "sha512-LGrMeSxeLzsdaitxq3ZmBRVOrlRRQIgNNci6L0VRnOKlJFuRIkNm4B+BObXPCJA6JT5bEJtrrwjn30jueHJYZQ==", + "requires": { + "@oozcitak/infra": "1.0.3", + "@oozcitak/util": "1.0.2" + }, + "dependencies": { + "@oozcitak/infra": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.3.tgz", + "integrity": "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag==", + "requires": { + "@oozcitak/util": "1.0.1" + }, + "dependencies": { + "@oozcitak/util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.1.tgz", + "integrity": "sha512-dFwFqcKrQnJ2SapOmRD1nQWEZUtbtIy9Y6TyJquzsalWNJsKIPxmTI0KG6Ypyl8j7v89L2wixH9fQDNrF78hKg==" + } + } + }, + "@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + } + } + }, + "@oozcitak/util": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.3.tgz", + "integrity": "sha512-Ufpab7G5PfnEhQyy5kDg9C8ltWJjsVT1P/IYqacjstaqydG4Q21HAT2HUZQYBrC/a1ZLKCz87pfydlDvv8y97w==" + }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -4955,6 +5023,16 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xmlbuilder2": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.1.2.tgz", + "integrity": "sha512-PI710tmtVlQ5VmwzbRTuhmVhKnj9pM8Si+iOZCV2g2SNo3gCrpzR2Ka9wNzZtqfD+mnP+xkrqoNy0sjKZqP4Dg==", + "requires": { + "@oozcitak/dom": "1.15.5", + "@oozcitak/infra": "1.0.5", + "@oozcitak/util": "8.3.3" + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index 57a69f5e..09b0f556 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "@actions/http-client": "^1.0.6", "@actions/io": "^1.0.0", "@actions/tool-cache": "^1.3.1", - "semver": "^6.1.1" + "semver": "^6.1.1", + "xmlbuilder2": "^2.1.2" }, "devDependencies": { "@types/jest": "^24.0.13", diff --git a/src/auth.ts b/src/auth.ts index e7978d55..e0dd6534 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -5,6 +5,7 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; import * as exec from '@actions/exec'; import * as util from './util'; +import {create as xmlCreate} from 'xmlbuilder2'; export const M2_DIR = '.m2'; export const TEMP_DIR = util.getTempDir(); @@ -39,10 +40,11 @@ export async function configAuthentication( ); await io.mkdirP(settingsDirectory); core.debug(`created directory ${settingsDirectory}`); + const isGpgEnabled = gpgPrivateKey !== DEFAULT_GPG_PRIVATE_KEY; await write( settingsDirectory, SETTINGS_FILE, - generate(id, username, password, gpgPassphrase) + generate(id, username, password, isGpgEnabled ? gpgPassphrase : null) ); if (gpgPrivateKey !== DEFAULT_GPG_PRIVATE_KEY) { @@ -51,37 +53,53 @@ export async function configAuthentication( } } -function escapeXML(value: string) { - return value - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - // only exported for testing purposes export function generate( - id = DEFAULT_ID, - username = DEFAULT_USERNAME, - password = DEFAULT_PASSWORD, - gpgPassphrase = DEFAULT_GPG_PASSPHRASE + id: string, + username: string, + password: string, + gpgPassphrase: string | null = null ) { - return ` - - - - ${escapeXML(id)} - \${env.${escapeXML(username)}} - \${env.${escapeXML(password)}} - - - gpg.passphrase - \${env.${escapeXML(gpgPassphrase)}} - - - - `; + const xmlObj: 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', + servers: { + server: [ + { + id: id, + username: `\${env.${username}}`, + password: `\${env.${password}}` + } + ] + } + } + }; + + if (gpgPassphrase !== null) { + const gpgServer = { + id: 'gpg.passphrase', + passphrase: `\${env.${gpgPassphrase}}` + }; + xmlObj.settings.servers.server.push(gpgServer); + + xmlObj.settings.profiles = { + profile: [ + { + activation: { + activeByDefault: true + }, + properties: { + 'gpg.homedir': TEMP_DIR + } + } + ] + }; + } + + return xmlCreate(xmlObj).end({headless: true, prettyPrint: true, width: 80}); } async function write(directory: string, file: string, contents: string) { diff --git a/src/util.ts b/src/util.ts index a061593b..671727c4 100644 --- a/src/util.ts +++ b/src/util.ts @@ -6,7 +6,9 @@ export function getTempDir() { let baseLocation; if (isWindows()) { // On windows use the USERPROFILE env variable - baseLocation = (process.env['USERPROFILE']) ? process.env['USERPROFILE'] : 'C:\\'; + baseLocation = process.env['USERPROFILE'] + ? process.env['USERPROFILE'] + : 'C:\\'; } else { if (process.platform === 'darwin') { baseLocation = '/Users'; @@ -20,5 +22,5 @@ export function getTempDir() { } export function isWindows() { - return (process.platform === 'win32'); -} \ No newline at end of file + return process.platform === 'win32'; +}