Skip to content

Commit ea15b9a

Browse files
committed
Add optional token parameter
The token is used for querying GitHub Releases API to determine the latest PMD version and the download URL for PMD. This allows to use `@actions/github` to get a octokit. Error handling is improved as well - util doesn't catch the errors anymore, so any exceptions bubble up to the main function.
1 parent 946ac27 commit ea15b9a

File tree

9 files changed

+131
-93
lines changed

9 files changed

+131
-93
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ See also [Uploading a SARIF file to GitHub](https://docs.github.com/en/code-secu
7070
7171
|input |required|default|description|
7272
|------------|---|--------|---------------|
73-
|`version` |no |"latest"|PMD version to use. Using "latest" automatically downloads the latest version. Available versions: https://github.com/pmd/pmd/releases|
73+
|`token` |no |"github.token"|Personal access token (PAT) used to query the latest PMD release and the download URL for PMD.<br>By default the automatic token for GitHub Actions is used.<br>[Learn more about automatic token authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication)<br>[Learn more about creating and using encrypted secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)|
74+
|`version` |no |"latest"|PMD version to use. Using "latest" automatically downloads the latest version.<br>Available versions: https://github.com/pmd/pmd/releases|
7475
|`sourcePath`|no |"." |Root directory for sources. Uses by default the current directory|
7576
|`rulesets` |yes| |Comma separated list of ruleset names to use.|
7677

action.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
name: PMD
22
description: Execute PMD static code analysis.
33
inputs:
4+
token:
5+
description: >-
6+
Personal access token (PAT) used to query the latest PMD release and the
7+
download URL for PMD.
8+
9+
By default the automatic token for GitHub Actions is used. [Learn more
10+
about automatic token
11+
authentication](https://docs.github.com/en/actions/security-guides/automatic-token-authentication)
12+
13+
[Learn more about creating and using encrypted
14+
secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
15+
required: false
16+
default: '${{ github.token }}'
417
version:
518
description: >-
619
PMD version to use. Using "latest" automatically downloads the latest
7-
version. Available versions: https://github.com/pmd/pmd/releases
20+
version.
21+
22+
Available versions: https://github.com/pmd/pmd/releases
823
required: false
924
default: latest
1025
sourcePath:

dist/index.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/licenses.txt

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ The above copyright notice and this permission notice shall be included in all c
3434

3535
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3636

37+
@actions/github
38+
MIT
39+
The MIT License (MIT)
40+
41+
Copyright 2019 GitHub
42+
43+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
44+
45+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
46+
47+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48+
3749
@actions/http-client
3850
MIT
3951
Actions Http Client for Node.js
@@ -194,17 +206,6 @@ The above copyright notice and this permission notice (including the next paragr
194206
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
195207

196208

197-
@octokit/plugin-request-log
198-
MIT
199-
MIT License Copyright (c) 2020 Octokit contributors
200-
201-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
202-
203-
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
204-
205-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
206-
207-
208209
@octokit/plugin-rest-endpoint-methods
209210
MIT
210211
MIT License Copyright (c) 2019 Octokit contributors
@@ -266,32 +267,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
266267
THE SOFTWARE.
267268

268269

269-
@octokit/rest
270-
MIT
271-
The MIT License
272-
273-
Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer)
274-
Copyright (c) 2017-2018 Octokit contributors
275-
276-
Permission is hereby granted, free of charge, to any person obtaining a copy
277-
of this software and associated documentation files (the "Software"), to deal
278-
in the Software without restriction, including without limitation the rights
279-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
280-
copies of the Software, and to permit persons to whom the Software is
281-
furnished to do so, subject to the following conditions:
282-
283-
The above copyright notice and this permission notice shall be included in
284-
all copies or substantial portions of the Software.
285-
286-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
287-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
288-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
289-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
290-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
291-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
292-
THE SOFTWARE.
293-
294-
295270
@vercel/ncc
296271
MIT
297272
Copyright 2018 ZEIT, Inc.

lib/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ const reportFile = 'pmd-report.sarif'
99

1010
let pmdPath, exitCode, violations;
1111

12-
async function run() {
12+
async function main() {
1313
try {
14-
pmdPath = await util.downloadPmd(validator.validateVersion(core.getInput('version'), { required: true }));
14+
pmdPath = await util.downloadPmd(
15+
validator.validateVersion(core.getInput('version', { required: true })),
16+
core.getInput('token', { required: true })
17+
);
1518
exitCode = await util.executePmd(pmdPath,
1619
validator.validateSourcePath(core.getInput('sourcePath', { required: true })),
1720
validator.validateRulesets(core.getInput('rulesets', { required: true })),
@@ -32,4 +35,4 @@ async function run() {
3235
}
3336
}
3437

35-
run();
38+
main();

lib/util.js

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,46 @@
11
const core = require('@actions/core');
2-
const { Octokit } = require("@octokit/rest");
2+
const github = require('@actions/github');
33
const tc = require('@actions/tool-cache');
44
const exec = require('@actions/exec');
55

6-
const downloadPmd = async function(version) {
7-
try {
8-
let pmdVersion = version;
9-
let cachedPmdPath = tc.find('pmd', version);
10-
core.debug(`cached path result: ${cachedPmdPath}`);
11-
if (cachedPmdPath === '') {
12-
const pmdRelease = await determinePmdRelease(version);
13-
pmdVersion = getPmdVersionFromRelease(pmdRelease);
14-
const pathToZipDistribution = await tc.downloadTool(await getDownloadURL(pmdRelease));
15-
const pmdExtractedFolder = await tc.extractZip(pathToZipDistribution);
16-
cachedPmdPath = await tc.cacheDir(pmdExtractedFolder, 'pmd', pmdVersion);
17-
}
18-
19-
core.info(`Using PMD ${pmdVersion} from cached path ${cachedPmdPath}`);
20-
return `${cachedPmdPath}/pmd-bin-${pmdVersion}`;
21-
} catch (error) {
22-
core.setFailed(error.message || error);
6+
const downloadPmd = async function(version, token) {
7+
let pmdVersion = version;
8+
let cachedPmdPath = tc.find('pmd', version);
9+
core.debug(`cached path result: ${cachedPmdPath}`);
10+
if (cachedPmdPath === '') {
11+
const pmdRelease = await determinePmdRelease(version, token);
12+
pmdVersion = getPmdVersionFromRelease(pmdRelease);
13+
const pathToZipDistribution = await tc.downloadTool(await getDownloadURL(pmdRelease));
14+
const pmdExtractedFolder = await tc.extractZip(pathToZipDistribution);
15+
cachedPmdPath = await tc.cacheDir(pmdExtractedFolder, 'pmd', pmdVersion);
2316
}
17+
18+
core.info(`Using PMD ${pmdVersion} from cached path ${cachedPmdPath}`);
19+
return `${cachedPmdPath}/pmd-bin-${pmdVersion}`;
2420
}
2521

2622
const executePmd = async function(pmdPath, sourcePath, ruleset, reportFormat, reportFile) {
27-
try {
28-
const { exitCode, stdout, stderr } = await exec.getExecOutput(`${pmdPath}/bin/run.sh`,
29-
[
30-
'pmd',
31-
'-no-cache',
32-
'-d', sourcePath,
33-
'-f', reportFormat,
34-
'-R', ruleset,
35-
'-r', reportFile,
36-
],
37-
{
38-
ignoreReturnCode: true
39-
});
40-
core.debug(`stdout: ${stdout}`);
41-
core.debug(`stderr: ${stderr}`);
42-
core.debug(`exitCode: ${exitCode}`);
43-
return exitCode;
44-
} catch (error) {
45-
core.setFailed(error.message || error);
46-
}
23+
const { exitCode, stdout, stderr } = await exec.getExecOutput(`${pmdPath}/bin/run.sh`,
24+
[
25+
'pmd',
26+
'-no-cache',
27+
'-d', sourcePath,
28+
'-f', reportFormat,
29+
'-R', ruleset,
30+
'-r', reportFile,
31+
],
32+
{
33+
ignoreReturnCode: true
34+
});
35+
core.debug(`stdout: ${stdout}`);
36+
core.debug(`stderr: ${stderr}`);
37+
core.debug(`exitCode: ${exitCode}`);
38+
return exitCode;
4739
}
4840

49-
async function determinePmdRelease(pmdVersion) {
50-
core.debug(`determine release info for ${pmdVersion}`);
51-
const octokit = new Octokit({baseUrl: getGithubBaseUrl()});
41+
async function determinePmdRelease(pmdVersion, token) {
42+
core.debug(`Determine release info for ${pmdVersion}`);
43+
const octokit = github.getOctokit(token);
5244
let release;
5345
if (pmdVersion === 'latest') {
5446
release = await octokit.rest.repos.getLatestRelease({
@@ -76,9 +68,5 @@ async function getDownloadURL(release) {
7668
return asset.browser_download_url;
7769
}
7870

79-
function getGithubBaseUrl() {
80-
return process.env['GITHUB_API_URL'] || 'https://api.github.com';
81-
}
82-
8371
module.exports.downloadPmd = downloadPmd;
8472
module.exports.executePmd = executePmd;

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@actions/artifact": "^0.5.2",
2828
"@actions/core": "^1.6.0",
2929
"@actions/exec": "^1.1.0",
30+
"@actions/github": "^5.0.0",
3031
"@actions/tool-cache": "^1.7.1",
3132
"@octokit/rest": "^18.12.0"
3233
},

tests/util.test.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('pmd-github-action-util', function() {
4545
.get('/pmd/pmd/releases/download/pmd_releases/6.40.0/pmd-bin-6.40.0.zip')
4646
.replyWithFile(200, __dirname + '/data/pmd-bin-6.40.0.zip')
4747

48-
const cachedPmdPath = await util.downloadPmd('latest');
48+
const cachedPmdPath = await util.downloadPmd('latest', 'my_test_token');
4949

5050
const toolCache = path.join(cachePath, 'pmd', '6.40.0', os.arch(), 'pmd-bin-6.40.0');
5151
expect(cachedPmdPath).toBe(toolCache);
@@ -61,13 +61,33 @@ describe('pmd-github-action-util', function() {
6161
nock('https://github.com')
6262
.get('/pmd/pmd/releases/download/pmd_releases/6.39.0/pmd-bin-6.39.0.zip')
6363
.replyWithFile(200, __dirname + '/data/pmd-bin-6.39.0.zip');
64-
const cachedPmdPath = await util.downloadPmd('6.39.0');
64+
const cachedPmdPath = await util.downloadPmd('6.39.0', 'my_test_token');
6565

6666
const toolCache = path.join(cachePath, 'pmd', '6.39.0', os.arch(), 'pmd-bin-6.39.0');
6767
expect(cachedPmdPath).toBe(toolCache);
6868
expect(fs.existsSync(toolCache)).toBeTruthy();
6969
})
7070

71+
it('use cached PMD version', async () => {
72+
nock('https://api.github.com')
73+
.get('/repos/pmd/pmd/releases/tags/pmd_releases%2F6.39.0')
74+
.once()
75+
.replyWithFile(200, __dirname + '/data/releases-6.39.0.json', {
76+
'Content-Type': 'application/json',
77+
})
78+
nock('https://github.com')
79+
.get('/pmd/pmd/releases/download/pmd_releases/6.39.0/pmd-bin-6.39.0.zip')
80+
.once()
81+
.replyWithFile(200, __dirname + '/data/pmd-bin-6.39.0.zip');
82+
const cachedPmdPath = await util.downloadPmd('6.39.0', 'my_test_token');
83+
const cachedPmdPath2 = await util.downloadPmd('6.39.0', 'my_test_token');
84+
85+
const toolCache = path.join(cachePath, 'pmd', '6.39.0', os.arch(), 'pmd-bin-6.39.0');
86+
expect(cachedPmdPath).toBe(toolCache);
87+
expect(cachedPmdPath2).toBe(cachedPmdPath);
88+
expect(fs.existsSync(toolCache)).toBeTruthy();
89+
})
90+
7191
it('can execute PMD', async () => {
7292
nock('https://api.github.com')
7393
.get('/repos/pmd/pmd/releases/latest')
@@ -78,14 +98,26 @@ describe('pmd-github-action-util', function() {
7898
.get('/pmd/pmd/releases/download/pmd_releases/6.40.0/pmd-bin-6.40.0.zip')
7999
.replyWithFile(200, __dirname + '/data/pmd-bin-6.40.0.zip')
80100

81-
const cachedPmdPath = await util.downloadPmd('latest');
101+
const cachedPmdPath = await util.downloadPmd('latest', 'my_test_token');
82102
await util.executePmd(cachedPmdPath, '.', 'ruleset.xml', 'sarif', 'pmd-report.sarif');
83103
const reportFile = path.join('.', 'pmd-report.sarif');
84104
expect(fs.existsSync(reportFile)).toBeTruthy();
85105
const report = JSON.parse(fs.readFileSync(reportFile));
86106
expect(report.runs[0].tool.driver.version).toBe('6.40.0');
87107
await io.rmRF(reportFile)
88108
})
109+
110+
it('failure while downloading PMD', async () => {
111+
nock('https://api.github.com')
112+
.get('/repos/pmd/pmd/releases/latest')
113+
.reply(503, 'Test Internal Server Error');
114+
115+
expect(() => util.downloadPmd('latest', 'my_test_token')).rejects.toThrow();
116+
});
117+
118+
it('failure while executing PMD', async () => {
119+
expect(() => util.executePmd('non-existing-pmd-path', '.', 'ruleset.xml', 'sarif', 'pmd-report.sarif')).rejects.toThrow();
120+
});
89121
});
90122

91123
function setGlobal(key, value) {

0 commit comments

Comments
 (0)