E571 Added support for GPG · actions/setup-java@d94db22 · GitHub
[go: up one dir, main page]

Skip to content

Commit d94db22

Browse files
committed
Added support for GPG
1 parent 5c87b70 commit d94db22

File tree

17 files changed

+37441
-5141
lines changed

17 files changed

+37441
-5141
lines changed

README.md

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,27 @@ Examples of version specifications that the java-version parameter will accept:
2929
- A major Java version
3030
3131
e.g. ```6, 7, 8, 9, 10, 11, 12, 13, ...```
32-
32+
3333
- A semver Java version specification
3434

3535
e.g. ```8.0.232, 7.0.181, 11.0.4```
36-
36+
3737
e.g. ```8.0.x, >11.0.3, >=13.0.1, <8.0.212```
38-
38+
3939
- An early access (EA) Java version
4040

4141
e.g. ```14-ea, 15-ea```
42-
42+
4343
e.g. ```14.0.0-ea, 15.0.0-ea```
44-
44+
4545
e.g. ```14.0.0-ea.28, 15.0.0-ea.2``` (syntax for specifying an EA build number)
46-
46+
4747
Note that, per semver rules, EA builds will be matched by explicit EA version specifications.
48-
48+
4949
- 1.x syntax
5050

5151
e.g. ```1.8``` (same as ```8```)
52-
52+
5353
e.g. ```1.8.0.212``` (same as ```8.0.212```)
5454

5555

@@ -113,39 +113,58 @@ jobs:
113113
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
114114
server-username: MAVEN_USERNAME # env variable for username in deploy
115115
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
116+
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
117+
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
116118
117119
- name: Publish to Apache Maven Central
118-
run: mvn deploy
120+
run: mvn deploy
119121
env:
120122
MAVEN_USERNAME: maven_username123
121123
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
124+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
122125
```
123126

124127
The two `settings.xml` files created from the above example look like the following.
125128

126129
`settings.xml` file created for the first deploy to GitHub Packages
127130
```xml
128-
<servers>
131+
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
132+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
133+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
134+
<servers>
129135
<server>
130136
<id>github</id>
131137
<username>${env.GITHUB_ACTOR}</username>
132138
<password>${env.GITHUB_TOKEN}</password>
133139
</server>
134-
</servers>
140+
<server>
141+
<id>gpg.passphrase</id>
142+
<passphrase>${env.GPG_PASSPHRASE}</passphrase>
143+
</server>
144+
</servers>
145+
</settings>
135146
```
136147

137148
`settings.xml` file created for the second deploy to Apache Maven Central
138149
```xml
139-
<servers>
150+
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
151+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
152+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
153+
<servers>
140154
<server>
141155
<id>maven</id>
142156
<username>${env.MAVEN_USERNAME}</username>
143157
<password>${env.MAVEN_CENTRAL_TOKEN}</password>
144158
</server>
145-
</servers>
159+
<server>
160+
<id>gpg.passphrase</id>
161+
<passphrase>${env.MAVEN_GPG_PASSPHRASE}</passphrase>
162+
</server>
163+
</servers>
164+
</settings>
146165
```
147166

148-
***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.***
167+
***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.***
149168

150169
See the help docs on [Publishing a Package](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-apache-maven-for-use-with-github-packages#publishing-a-package) for more information on the `pom.xml` file.
151170

@@ -172,7 +191,7 @@ jobs:
172191
PASSWORD: ${{ secrets.GITHUB_TOKEN }}
173192
```
174193

175-
***NOTE: The `USERNAME` and `PASSWORD` need to correspond to the credentials environment variables used in the publishing section of your `build.gradle`.***
194+
***NOTE: The `USERNAME` and `PASSWORD` need to correspond to the credentials environment variables used in the publishing section of your `build.gradle`.***
176195

177196
See the help docs on [Publishing a Package with Gradle](https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages#example-using-gradle-groovy-for-a-single-package-in-a-repository) for more information on the `build.gradle` configuration file.
178197

__tests__/auth.test.ts

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('auth tests', () => {
5353
await io.rmRF(altHome);
5454
}, 100000);
5555

56-
it('creates settings.xml with username and password', async () => {
56+
it('creates settings.xml with minimal configuration', async () => {
5757
const id = 'packages';
5858
const username = 'UNAME';
5959
const password = 'TOKEN';
@@ -67,78 +67,84 @@ describe('auth tests', () => {
6767
);
6868
}, 100000);
6969

70-
it('overwrites existing settings.xml files', async () => {
70+
it('creates settings.xml with additional configuration', async () => {
7171
const id = 'packages';
72-
const username = 'USERNAME';
73-
const password = 'PASSWORD';
74-
75-
fs.mkdirSync(m2Dir, {recursive: true});
76-
fs.writeFileSync(settingsFile, 'FAKE FILE');
77-
expect(fs.existsSync(m2Dir)).toBe(true);
78-
expect(fs.existsSync(settingsFile)).toBe(true);
72+
const username = 'UNAME';
73+
const password = 'TOKEN';
74+
const gpgPassphrase = 'GPG';
7975

80-
await auth.configAuthentication(id, username, password);
76+
await auth.configAuthentication(id, username, password, gpgPassphrase);
8177

8278
expect(fs.existsSync(m2Dir)).toBe(true);
8379
expect(fs.existsSync(settingsFile)).toBe(true);
8480
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
85-
auth.generate(id, username, password)
81+
auth.generate(id, username, password, gpgPassphrase)
8682
);
8783
}, 100000);
8884

89-
it('does not create settings.xml without required parameters', async () => {
90-
await auth.configAuthentication('FOO');
91-
92-
expect(fs.existsSync(m2Dir)).toBe(true);
93-
expect(fs.existsSync(settingsFile)).toBe(true);
94-
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
95-
auth.generate('FOO', auth.DEFAULT_USERNAME, auth.DEFAULT_PASSWORD)
96-
);
97-
98-
await auth.configAuthentication(undefined, 'BAR', undefined);
99-
100-
expect(fs.existsSync(m2Dir)).toBe(true);
101-
expect(fs.existsSync(settingsFile)).toBe(true);
102-
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
103-
auth.generate(auth.DEFAULT_ID, 'BAR', auth.DEFAULT_PASSWORD)
104-
);
105-
106-
await auth.configAuthentication(undefined, undefined, 'BAZ');
85+
it('overwrites existing settings.xml files', async () => {
86+
const id = 'packages';
87+
const username = 'USERNAME';
88+
const password = 'PASSWORD';
10789

90+
fs.mkdirSync(m2Dir, {recursive: true});
91+
fs.writeFileSync(settingsFile, 'FAKE FILE');
10892
expect(fs.existsSync(m2Dir)).toBe(true);
10993
expect(fs.existsSync(settingsFile)).toBe(true);
110-
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
111-
auth.generate(auth.DEFAULT_ID, auth.DEFAULT_USERNAME, 'BAZ')
112-
);
11394

114-
await auth.configAuthentication();
95+
await auth.configAuthentication(id, username, password);
11596

11697
expect(fs.existsSync(m2Dir)).toBe(true);
11798
expect(fs.existsSync(settingsFile)).toBe(true);
11899
expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual(
119-
auth.generate(
120-
auth.DEFAULT_ID,
121-
auth.DEFAULT_USERNAME,
122-
auth.DEFAULT_PASSWORD
123-
)
100+
auth.generate(id, username, password)
124101
);
125102
}, 100000);
126103

127-
it('escapes invalid XML inputs', () => {
104+
it('generates valid settings.xml with minimal configuration', () => {
128105
const id = 'packages';
129106
const username = 'USER';
130107
const password = '&<>"\'\'"><&';
131108

132-
expect(auth.generate(id, username, password)).toEqual(`
133-
<settings>
134-
<servers>
135-
<server>
136-
<id>${id}</id>
137-
<username>\${env.${username}}</username>
138-
<password>\${env.&amp;&lt;&gt;&quot;&apos;&apos;&quot;&gt;&lt;&amp;}</password>
139-
</server>
140-
</servers>
141-
</settings>
142-
`);
109+
const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
110+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
111+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
112+
<servers>
113+
<server>
114+
<id>${id}</id>
115+
<username>\${env.${username}}</username>
116+
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
117+
</server>
118+
</servers>
119+
</settings>`;
120+
121+
expect(auth.generate(id, username, password)).toEqual(expectedSettings);
122+
});
123+
124+
it('generates valid settings.xml with additional configuration', () => {
125+
const id = 'packages';
126+
const username = 'USER';
127+
const password = '&<>"\'\'"><&';
128+
const gpgPassphrase = 'PASSPHRASE';
129+
130+
const expectedSettings = `<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
131+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
132+
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
133+
<servers>
134+
<server>
135+
<id>${id}</id>
136+
<username>\${env.${username}}</username>
137+
<password>\${env.&amp;&lt;&gt;"''"&gt;&lt;&amp;}</password>
138+
</server>
139+
<server>
140+
<id>gpg.passphrase</id>
141+
<passphrase>\${env.${gpgPassphrase}}</passphrase>
142+
</server>
143+
</servers>
144+
</settings>`;
145+
146+
expect(auth.generate(id, username, password, gpgPassphrase)).toEqual(
147+
expectedSettings
148+
);
143149
});
144150
});

__tests__/gpg.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import path = require('path');
2+
import io = require('@actions/io');
3+
import exec = require('@actions/exec');
4+
5+
jest.mock('@actions/exec', () => {
6+
return {
7+
exec: jest.fn()
8+
};
9+
});
10+
11+
const tempDir = path.join(__dirname, 'runner', 'temp');
12+
process.env['RUNNER_TEMP'] = tempDir;
13+
14+
import gpg = require('../src/gpg');
15+
16+
describe('gpg tests', () => {
17+
beforeEach(async () => {
18+
await io.mkdirP(tempDir);
19+
}, 300000);
20+
21+
afterAll(async () => {
22+
try {
23+
await io.rmRF(tempDir);
24+
} catch {
25+
console.log('Failed to remove test directories');
26+
}
27+
}, 100000);
28+
29+
describe('importKey', () => {
30+
it('attempts to import private key and returns null key id on failure', async () => {
31+
const privateKey = 'KEY CONTENTS';
32+
const keyId = await gpg.importKey(privateKey);
33+
34+
expect(keyId).toBeNull();
35+
36+
expect(exec.exec).toHaveBeenCalledWith(
37+
'gpg',
38+
expect.anything(),
39+
expect.anything()
40+
);
41+
});
42+
});
43+
44+
describe('deleteKey', () => {
45+
it('deletes private key', async () => {
46+
const keyId = 'asdfhjkl';
47+
await gpg.deleteKey(keyId);
48+
49+
expect(exec.exec).toHaveBeenCalledWith(
50+
'gpg',
51+
expect.anything(),
52+
expect.anything()
53+
);
54+
});
55+
});
56+
});

__tests__/util.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import path = require('path');
2+
3+
const env = process.env;
4+
5+
describe('util tests', () => {
6+
beforeEach(() => {
7+
const tempEnv = Object.assign({}, env);
8+
delete tempEnv.RUNNER_TEMP;
9+
delete tempEnv.USERPROFILE;
10+
process.env = tempEnv;
11+
Object.defineProperty(process, 'platform', {value: 'linux'});
12+
});
13+
14+
describe('getTempDir', () => {
15+
it('gets temp dir using env', () => {
16+
process.env['RUNNER_TEMP'] = 'defaulttmp';
17+
const util = require('../src/util');
18+
19+
const tempDir = util.getTempDir();
20+
21+
expect(tempDir).toEqual(process.env['RUNNER_TEMP']);
22+
});
23+
24+
it('gets temp dir for windows using userprofile', () => {
25+
Object.defineProperty(process, 'platform', {value: 'win32'});
26+
process.env['USERPROFILE'] = 'winusertmp';
27+
const util = require('../src/util');
28+
29+
const tempDir = util.getTempDir();
30+
31+
expect(tempDir).toEqual(
32+
path.join(process.env['USERPROFILE'], 'actions', 'temp')
33+
);
34+
});
35+
36+
it('gets temp dir for windows using c drive', () => {
37+
Object.defineProperty(process, 'platform', {value: 'win32'});
38+
const util = require('../src/util');
39+
40+
const tempDir = util.getTempDir();
41+
42+
expect(tempDir).toEqual(path.join('C:\\', 'actions', 'temp'));
43+
});
44+
45+
it('gets temp dir for mac', () => {
46+
Object.defineProperty(process, 'platform', {value: 'darwin'});
47+
const util = require('../src/util');
48+
49+
const tempDir = util.getTempDir();
50+
51+
expect(tempDir).toEqual(path.join('/Users', 'actions', 'temp'));
52+
});
53+
54+
it('gets temp dir for linux', () => {
55+
const util = require('../src/util');
56+
const tempDir = util.getTempDir();
57+
58+
expect(tempDir).toEqual(path.join('/home', 'actions', 'temp'));
59+
});
60+
});
61+
});

action.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ inputs:
3636
settings-path:
3737
description: 'Path to where the settings.xml file will be written. Default is ~/.m2.'
3838
required: false
39+
gpg-private-key:
40+
description: 'GPG private key to import. Default is empty string.'
41+
required: false
42+
gpg-passphrase:
43+
description: 'Environment variable name for the GPG private key passphrase. Default is
44+
$GPG_PASSPHRASE.'
45+
required: false
3946
runs:
4047
using: 'node12'
41-
main: 'dist/index.js'
48+
main: 'dist/setup/index.js'
49+
post: 'dist/cleanup/index.js'

0 commit comments

Comments
 (0)
0