Added support for GPG

This commit is contained in:
Jared Petersen 2020-05-02 04:33:15 -07:00
parent 5c87b70ffe
commit d94db22179
17 changed files with 37442 additions and 128 deletions

View File

@ -113,36 +113,55 @@ jobs:
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy server-username: MAVEN_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Publish to Apache Maven Central - name: Publish to Apache Maven Central
run: mvn deploy run: mvn deploy
env: env:
MAVEN_USERNAME: maven_username123 MAVEN_USERNAME: maven_username123
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }} MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
``` ```
The two `settings.xml` files created from the above example look like the following. The two `settings.xml` files created from the above example look like the following.
`settings.xml` file created for the first deploy to GitHub Packages `settings.xml` file created for the first deploy to GitHub Packages
```xml ```xml
<servers> <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>
<id>github</id> <id>github</id>
<username>${env.GITHUB_ACTOR}</username> <username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password> <password>${env.GITHUB_TOKEN}</password>
</server> </server>
</servers> <server>
<id>gpg.passphrase</id>
<passphrase>${env.GPG_PASSPHRASE}</passphrase>
</server>
</servers>
</settings>
``` ```
`settings.xml` file created for the second deploy to Apache Maven Central `settings.xml` file created for the second deploy to Apache Maven Central
```xml ```xml
<servers> <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>
<id>maven</id> <id>maven</id>
<username>${env.MAVEN_USERNAME}</username> <username>${env.MAVEN_USERNAME}</username>
<password>${env.MAVEN_CENTRAL_TOKEN}</password> <password>${env.MAVEN_CENTRAL_TOKEN}</password>
</server> </server>
</servers> <server>
<id>gpg.passphrase</id>
<passphrase>${env.MAVEN_GPG_PASSPHRASE}</passphrase>
</server>
</servers>
</settings>
``` ```
***NOTE: The `settings.xml` file is created in the Actions $HOME directory. If you have an existing `settings.xml` file at that location, it will be overwritten. See below for using the `settings-path` to change your `settings.xml` file location.*** ***NOTE: The `settings.xml` file is created in the Actions $HOME directory. If you have an existing `settings.xml` file at that location, it will be overwritten. See below for using the `settings-path` to change your `settings.xml` file location.***

View File

@ -53,7 +53,7 @@ describe('auth tests', () => {
await io.rmRF(altHome); await io.rmRF(altHome);
}, 100000); }, 100000);
it('creates settings.xml with username and password', async () => { it('creates settings.xml with minimal configuration', async () => {
const id = 'packages'; const id = 'packages';
const username = 'UNAME'; const username = 'UNAME';
const password = 'TOKEN'; const password = 'TOKEN';
@ -67,6 +67,21 @@ describe('auth tests', () => {
); );
}, 100000); }, 100000);
it('creates settings.xml with additional configuration', async () => {
const id = 'packages';
const username = 'UNAME';
const password = 'TOKEN';
const gpgPassphrase = 'GPG';
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)
);
}, 100000);
it('overwrites existing settings.xml files', async () => { it('overwrites existing settings.xml files', async () => {
const id = 'packages'; const id = 'packages';
const username = 'USERNAME'; const username = 'USERNAME';
@ -86,59 +101,50 @@ describe('auth tests', () => {
); );
}, 100000); }, 100000);
it('does not create settings.xml without required parameters', async () => { it('generates valid settings.xml with minimal configuration', () => {
await auth.configAuthentication('FOO');
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate('FOO', auth.DEFAULT_USERNAME, auth.DEFAULT_PASSWORD)
);
await auth.configAuthentication(undefined, 'BAR', undefined);
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(auth.DEFAULT_ID, 'BAR', auth.DEFAULT_PASSWORD)
);
await auth.configAuthentication(undefined, undefined, 'BAZ');
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(auth.DEFAULT_ID, auth.DEFAULT_USERNAME, 'BAZ')
);
await auth.configAuthentication();
expect(fs.existsSync(m2Dir)).toBe(true);
expect(fs.existsSync(settingsFile)).toBe(true);
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
auth.generate(
auth.DEFAULT_ID,
auth.DEFAULT_USERNAME,
auth.DEFAULT_PASSWORD
)
);
}, 100000);
it('escapes invalid XML inputs', () => {
const id = 'packages'; const id = 'packages';
const username = 'USER'; const username = 'USER';
const password = '&<>"\'\'"><&'; const password = '&<>"\'\'"><&';
expect(auth.generate(id, username, password)).toEqual(` const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
<settings> 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> <servers>
<server> <server>
<id>${id}</id> <id>${id}</id>
<username>\${env.${username}}</username> <username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;&quot;&apos;&apos;&quot;&gt;&lt;&amp;}</password> <password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
</server> </server>
</servers> </servers>
</settings> </settings>`;
`);
expect(auth.generate(id, username, password)).toEqual(expectedSettings);
});
it('generates valid settings.xml with additional configuration', () => {
const id = 'packages';
const username = 'USER';
const password = '&<>"\'\'"><&';
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>${id}</id>
<username>\${env.${username}}</username>
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
</server>
<server>
<id>gpg.passphrase</id>
<passphrase>\${env.${gpgPassphrase}}</passphrase>
</server>
</servers>
</settings>`;
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
expectedSettings
);
}); });
}); });

56
__tests__/gpg.test.ts Normal file
View File

@ -0,0 +1,56 @@
import path = require('path');
import io = require('@actions/io');
import exec = require('@actions/exec');
jest.mock('@actions/exec', () => {
return {
exec: jest.fn()
};
});
const tempDir = path.join(__dirname, 'runner', 'temp');
process.env['RUNNER_TEMP'] = tempDir;
import gpg = require('../src/gpg');
describe('gpg tests', () => {
beforeEach(async () => {
await io.mkdirP(tempDir);
}, 300000);
afterAll(async () => {
try {
await io.rmRF(tempDir);
} catch {
console.log('Failed to remove test directories');
}
}, 100000);
describe('importKey', () => {
it('attempts to import private key and returns null key id on failure', async () => {
const privateKey = 'KEY CONTENTS';
const keyId = await gpg.importKey(privateKey);
expect(keyId).toBeNull();
expect(exec.exec).toHaveBeenCalledWith(
'gpg',
expect.anything(),
expect.anything()
);
});
});
describe('deleteKey', () => {
it('deletes private key', async () => {
const keyId = 'asdfhjkl';
await gpg.deleteKey(keyId);
expect(exec.exec).toHaveBeenCalledWith(
'gpg',
expect.anything(),
expect.anything()
);
});
});
});

61
__tests__/util.test.ts Normal file
View File

@ -0,0 +1,61 @@
import path = require('path');
const env = process.env;
describe('util tests', () => {
beforeEach(() => {
const tempEnv = Object.assign({}, env);
delete tempEnv.RUNNER_TEMP;
delete tempEnv.USERPROFILE;
process.env = tempEnv;
Object.defineProperty(process, 'platform', {value: 'linux'});
});
describe('getTempDir', () => {
it('gets temp dir using env', () => {
process.env['RUNNER_TEMP'] = 'defaulttmp';
const util = require('../src/util');
const tempDir = util.getTempDir();
expect(tempDir).toEqual(process.env['RUNNER_TEMP']);
});
it('gets temp dir for windows using userprofile', () => {
Object.defineProperty(process, 'platform', {value: 'win32'});
process.env['USERPROFILE'] = 'winusertmp';
const util = require('../src/util');
const tempDir = util.getTempDir();
expect(tempDir).toEqual(
path.join(process.env['USERPROFILE'], 'actions', 'temp')
);
});
it('gets temp dir for windows using c drive', () => {
Object.defineProperty(process, 'platform', {value: 'win32'});
const util = require('../src/util');
const tempDir = util.getTempDir();
expect(tempDir).toEqual(path.join('C:\\', 'actions', 'temp'));
});
it('gets temp dir for mac', () => {
Object.defineProperty(process, 'platform', {value: 'darwin'});
const util = require('../src/util');
const tempDir = util.getTempDir();
expect(tempDir).toEqual(path.join('/Users', 'actions', 'temp'));
});
it('gets temp dir for linux', () => {
const util = require('../src/util');
const tempDir = util.getTempDir();
expect(tempDir).toEqual(path.join('/home', 'actions', 'temp'));
});
});
});

View File

@ -36,6 +36,14 @@ inputs:
settings-path: settings-path:
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.' description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
required: false required: false
gpg-private-key:
description: 'GPG private key to import. Default is empty string.'
required: false
gpg-passphrase:
description: 'Environment variable name for the GPG private key passphrase. Default is
$GPG_PASSPHRASE.'
required: false
runs: runs:
using: 'node12' using: 'node12'
main: 'dist/index.js' main: 'dist/setup/index.js'
post: 'dist/cleanup/index.js'

1682
dist/cleanup/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
dist/index.js generated vendored

Binary file not shown.

35284
dist/setup/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

78
package-lock.json generated
View File

@ -430,6 +430,74 @@
"@types/yargs": "^13.0.0" "@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": { "@types/babel__core": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz",
@ -4955,6 +5023,16 @@
"integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
"dev": true "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": { "y18n": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",

View File

@ -5,11 +5,11 @@
"description": "setup java action", "description": "setup java action",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"build": "ncc build src/setup-java.ts", "build": "ncc build -o dist/setup src/setup-java.ts && ncc build -o dist/cleanup src/cleanup-java.ts",
"format": "prettier --write **/*.ts", "format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts", "format-check": "prettier --check **/*.ts",
"prerelease": "npm run-script build", "prerelease": "npm run-script build",
"release": "git add -f dist/index.js", "release": "git add -f dist/setup/index.js dist/cleanup/index.js",
"test": "jest" "test": "jest"
}, },
"repository": { "repository": {
@ -29,7 +29,8 @@
"@actions/http-client": "^1.0.6", "@actions/http-client": "^1.0.6",
"@actions/io": "^1.0.0", "@actions/io": "^1.0.0",
"@actions/tool-cache": "^1.3.1", "@actions/tool-cache": "^1.3.1",
"semver": "^6.1.1" "semver": "^6.1.1",
"xmlbuilder2": "^2.1.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.13", "@types/jest": "^24.0.13",

View File

@ -3,60 +3,72 @@ import * as os from 'os';
import * as path from 'path'; 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 {create as xmlCreate} from 'xmlbuilder2';
export const M2_DIR = '.m2'; export const M2_DIR = '.m2';
export const SETTINGS_FILE = 'settings.xml'; export const SETTINGS_FILE = 'settings.xml';
export const DEFAULT_ID = 'github';
export const DEFAULT_USERNAME = 'GITHUB_ACTOR';
export const DEFAULT_PASSWORD = 'GITHUB_TOKEN';
export async function configAuthentication( export async function configAuthentication(
id = DEFAULT_ID, id: string,
username = DEFAULT_USERNAME, username: string,
password = DEFAULT_PASSWORD password: string,
gpgPassphrase: string | undefined = undefined
) { ) {
console.log( console.log(
`creating ${SETTINGS_FILE} with server-id: ${id};`, `creating ${SETTINGS_FILE} with server-id: ${id};`,
`environment variables: username=\$${username} and password=\$${password}` '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) // when an alternate m2 location is specified use only that location (no .m2 directory)
// otherwise use the home/.m2/ path // otherwise use the home/.m2/ path
const directory: string = path.join( const settingsDirectory: string = path.join(
core.getInput('settings-path') || os.homedir(), core.getInput('settings-path') || os.homedir(),
core.getInput('settings-path') ? '' : M2_DIR core.getInput('settings-path') ? '' : M2_DIR
); );
await io.mkdirP(directory); await io.mkdirP(settingsDirectory);
core.debug(`created directory ${directory}`); core.debug(`created directory ${settingsDirectory}`);
await write(directory, generate(id, username, password)); await write(
} settingsDirectory,
generate(id, username, password, gpgPassphrase)
function escapeXML(value: string) { );
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
} }
// only exported for testing purposes // only exported for testing purposes
export function generate( export function generate(
id = DEFAULT_ID, id: string,
username = DEFAULT_USERNAME, username: string,
password = DEFAULT_PASSWORD password: string,
gpgPassphrase: string | undefined = undefined
) { ) {
return ` const xmlObj: {[key: string]: any} = {
<settings> settings: {
<servers> '@xmlns': 'http://maven.apache.org/SETTINGS/1.0.0',
<server> '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
<id>${escapeXML(id)}</id> '@xsi:schemaLocation':
<username>\${env.${escapeXML(username)}}</username> 'http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd',
<password>\${env.${escapeXML(password)}}</password> servers: {
</server> server: [
</servers> {
</settings> id: id,
`; username: `\${env.${username}}`,
password: `\${env.${password}}`
}
]
}
}
};
if (gpgPassphrase) {
const gpgServer = {
id: 'gpg.passphrase',
passphrase: `\${env.${gpgPassphrase}}`
};
xmlObj.settings.servers.server.push(gpgServer);
}
return xmlCreate(xmlObj).end({headless: true, prettyPrint: true, width: 80});
} }
async function write(directory: string, settings: string) { async function write(directory: string, settings: string) {

16
src/cleanup-java.ts Normal file
View File

@ -0,0 +1,16 @@
import * as core from '@actions/core';
import * as gpg from './gpg';
async function run() {
if (core.getInput('gpg-private-key', {required: false})) {
console.log('removing private key from keychain');
try {
const keyFingerprint = core.getState('gpg-private-key-fingerprint');
await gpg.deleteKey(keyFingerprint);
} catch (error) {
core.setFailed(error.message);
}
}
}
run();

58
src/gpg.ts Normal file
View File

@ -0,0 +1,58 @@
import * as fs from 'fs';
import * as path from 'path';
import * as io from '@actions/io';
import * as exec from '@actions/exec';
import * as util from './util';
import {ExecOptions} from '@actions/exec/lib/interfaces';
export const PRIVATE_KEY_FILE = path.join(util.getTempDir(), 'private-key.asc');
const PRIVATE_KEY_FINGERPRINT_REGEX = /\w{40}/;
export async function importKey(privateKey: string) {
fs.writeFileSync(PRIVATE_KEY_FILE, privateKey, {
encoding: 'utf-8',
flag: 'w'
});
let output = '';
const options: ExecOptions = {
silent: true,
listeners: {
stdout: (data: Buffer) => {
output += data.toString();
}
}
};
await exec.exec(
'gpg',
[
'--batch',
'--import-options',
'import-show',
'--import',
PRIVATE_KEY_FILE
],
options
);
await io.rmRF(PRIVATE_KEY_FILE);
const match = output.match(PRIVATE_KEY_FINGERPRINT_REGEX);
return match && match[0];
}
export async function deleteKey(keyFingerprint: string) {
await exec.exec(
'gpg',
['--batch', '--yes', '--delete-secret-keys', keyFingerprint],
{silent: true}
);
await exec.exec(
'gpg',
['--batch', '--yes', '--delete-keys', keyFingerprint],
{silent: true}
);
}

View File

@ -1,5 +1,3 @@
let tempDirectory = process.env['RUNNER_TEMP'] || '';
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 exec from '@actions/exec'; import * as exec from '@actions/exec';
@ -8,23 +6,10 @@ import * as tc from '@actions/tool-cache';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import * as util from './util';
const IS_WINDOWS = process.platform === 'win32'; const tempDirectory = util.getTempDir();
const IS_WINDOWS = util.isWindows();
if (!tempDirectory) {
let baseLocation;
if (IS_WINDOWS) {
// On windows use the USERPROFILE env variable
baseLocation = process.env['USERPROFILE'] || 'C:\\';
} else {
if (process.platform === 'darwin') {
baseLocation = '/Users';
} else {
baseLocation = '/home';
}
}
tempDirectory = path.join(baseLocation, 'actions', 'temp');
}
export async function getJava( export async function getJava(
version: string, version: string,

View File

@ -1,10 +1,20 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as installer from './installer'; import * as installer from './installer';
import * as auth from './auth'; import * as auth from './auth';
import * as gpg from './gpg';
import * as path from 'path'; import * as path from 'path';
const DEFAULT_ID = 'github';
const DEFAULT_USERNAME = 'GITHUB_ACTOR';
const DEFAULT_PASSWORD = 'GITHUB_TOKEN';
const DEFAULT_GPG_PRIVATE_KEY = undefined;
const DEFAULT_GPG_PASSPHRASE = 'GPG_PASSPHRASE';
async function run() { async function run() {
try { try {
// Set secrets before use
core.setSecret('gpg-private-key');
let version = core.getInput('version'); let version = core.getInput('version');
if (!version) { if (!version) {
version = core.getInput('java-version', {required: true}); version = core.getInput('java-version', {required: true});
@ -15,16 +25,28 @@ async function run() {
await installer.getJava(version, arch, jdkFile, javaPackage); await installer.getJava(version, arch, jdkFile, javaPackage);
const matchersPath = path.join(__dirname, '..', '.github'); const matchersPath = path.join(__dirname, '..', '..', '.github');
console.log(`##[add-matcher]${path.join(matchersPath, 'java.json')}`); console.log(`##[add-matcher]${path.join(matchersPath, 'java.json')}`);
const id = core.getInput('server-id', {required: false}) || undefined; const id = core.getInput('server-id', {required: false}) || DEFAULT_ID;
const username = const username =
core.getInput('server-username', {required: false}) || undefined; core.getInput('server-username', {required: false}) || DEFAULT_USERNAME;
const password = const password =
core.getInput('server-password', {required: false}) || undefined; core.getInput('server-password', {required: false}) || DEFAULT_PASSWORD;
const gpgPrivateKey =
core.getInput('gpg-private-key', {required: false}) ||
DEFAULT_GPG_PRIVATE_KEY;
const gpgPassphrase =
core.getInput('gpg-passphrase', {required: false}) ||
(gpgPrivateKey ? DEFAULT_GPG_PASSPHRASE : undefined);
await auth.configAuthentication(id, username, password); await auth.configAuthentication(id, username, password, gpgPassphrase);
if (gpgPrivateKey) {
console.log('importing private key');
const keyFingerprint = (await gpg.importKey(gpgPrivateKey)) || '';
core.saveState('gpg-private-key-fingerprint', keyFingerprint);
}
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }

26
src/util.ts Normal file
View File

@ -0,0 +1,26 @@
import * as path from 'path';
export function getTempDir() {
let tempDirectory = process.env.RUNNER_TEMP;
if (tempDirectory === undefined) {
let baseLocation;
if (isWindows()) {
// On windows use the USERPROFILE env variable
baseLocation = process.env['USERPROFILE']
? process.env['USERPROFILE']
: 'C:\\';
} else {
if (process.platform === 'darwin') {
baseLocation = '/Users';
} else {
baseLocation = '/home';
}
}
tempDirectory = path.join(baseLocation, 'actions', 'temp');
}
return tempDirectory;
}
export function isWindows() {
return process.platform === 'win32';
}