diff --git a/nodejs-wrapper/README.md b/nodejs-wrapper/README.md index 3e71397d..6651443d 100644 --- a/nodejs-wrapper/README.md +++ b/nodejs-wrapper/README.md @@ -5,13 +5,13 @@ This npm package makes it easy to integrate [dash-licenses](https://github.com/e ## Runtime requirements - called using `bash` -- `node.js` (`node`) is available from the path +- `node.js` is installed and `node` executable is in the path - on Linux, mac or Windows using Windows Subsystem for Linux (WSL) -- JDK or JRE is installed (`java` executable is in the path), to run `dash-licenses` -- to run in [automatic review mode](https://github.com/eclipse/dash-licenses#automatic-ip-team-review-requests) : - - an Eclipse Foundation Gitlab Personal Access Token (PAT), generated by an Eclipse project committer, is necessary +- to run `dash-licenses`: JDK or JRE 11 or later is installed and the `java` executable is in the path +- to run `dash-licenses` in [automatic review mode](https://github.com/eclipse/dash-licenses#automatic-ip-team-review-requests): + - a PAT (Personal Access Token) generated on the Eclipse Foundation Gitlab by an Eclipse project committer - local run: the PAT needs to be set in environment variable `DASH_TOKEN`. e.g. `export DASH_TOKEN=` - - GitHub workflow run: the PAT needs to be set as a GitHub Secret, and used in the workflow to define environment variable `DASH_TOKEN`. Note: GitHub [secrets are not be available for PRs that originate from a fork](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#using-secrets-in-a-workflow), which means that "automatic review mode" can't be used for PRs from non-committers (that must open the PR from their fork vs from the main repo) or for PR from committers that open the PR from their fork. + - GitHub workflow run: the PAT needs to be set as a GitHub Secret, and used in the workflow to define environment variable `DASH_TOKEN`. Note: GitHub [secrets are not available for PRs that originate from a fork](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#using-secrets-in-a-workflow). This means that "automatic review mode" can't be used for PRs from non-committers or PRs from committers that open the PR from a branch in their fork. ## How to install and use @@ -133,4 +133,4 @@ It can be very efficient to run `dash-licenses` in `review` mode during CI, to a ## Acknowledgements -This work is based on work contributed to the [Eclipse Theia main git repository](https://github.com/eclipse-theia/theia), by Ericsson and others. Mainly script [check_3pp_licenses](https://github.com/eclipse-theia/theia/blob/master/scripts/check_3pp_licenses.js). +This work is based on work contributed to the [Eclipse Theia main git repository](https://github.com/eclipse-theia/theia), by Ericsson and others. Mainly script [check_3pp_licenses.js](https://github.com/eclipse-theia/theia/blob/master/scripts/check_3pp_licenses.js). diff --git a/nodejs-wrapper/src/dash-licenses-wrapper.js b/nodejs-wrapper/src/dash-licenses-wrapper.js index 316b6302..2277cfad 100755 --- a/nodejs-wrapper/src/dash-licenses-wrapper.js +++ b/nodejs-wrapper/src/dash-licenses-wrapper.js @@ -31,7 +31,7 @@ const regExpReplacer = (key, value) => { } return value; }; -const dashLicensesJar = path.resolve(__dirname, 'download/dash-licenses.jar'); +const dashLicensesJar = path.resolve(__dirname, '..', 'download/dash-licenses.jar'); const dashLicensesDownloadUrl = 'https://repo.eclipse.org/service/local/artifact/maven/redirect?r=dash-licenses&g=org.eclipse.dash&a=org.eclipse.dash.licenses&v=LATEST'; const dashLicensesInternalError = 127; @@ -178,6 +178,21 @@ async function main() { process.exit(1); } } + // sanity check on downloaded dash-licenses .jar file - it can occasionally happen that the + // download was not a valid jar file, without curl reporting a problem. e.g. the content might + // be an error message in plain text, rather than the expected content. ATM the legit .jar is + // expected to be ~12MB in size - if we download something much smaller, it's likely not what + // we want. + if (fs.statSync(dashLicensesJar).size < 1000000) { + const invalidJar = dashLicensesJar + '.invalid'; + error(`Downloaded dash-licenses jar file appears to be invalid or corrupted: ${dashLicensesJar}`); + error (`Renaming it to ${path.basename(invalidJar)} and exiting... `); + error("Perhaps it will work next time?"); + + // rename likely faulty jar so it will be downloaded again next run + fs.renameSync(dashLicensesJar, invalidJar); + process.exit(1); + } if (fs.existsSync(summaryFile)) { info('Backing up previous summary...'); fs.renameSync(summaryFile, `${summaryFile}.old`); @@ -216,16 +231,20 @@ async function main() { // filter-out restricted dependencies that are in the exclusion file if (restricted.length > 0) { if (fs.existsSync(exclusionsFile)) { - info('Checking results against the exclusions...'); + info('Checking dash-licenses "restricted" results against configured exclusions...'); const exclusions = readExclusions(exclusionsFile); const unmatched = new Set(exclusions.keys()); const unhandled = restricted.filter(entry => { unmatched.delete(entry.dependency); - return !exclusions.has(entry.dependency); + const dependencyIsExcluded = exclusions.has(entry.dependency); + if (dependencyIsExcluded) { + debug(`Restricted dependency from dash-licenses results is in exclusion file - filtering it out: ${entry.dependency}`); + } + return !dependencyIsExcluded; }); if (unmatched.size > 0) { - warn('Some entries in the exclusions did not match anything from dash-licenses output:'); - warn("(perhaps these entries are no longer required?)"); + warn('Some entries in the exclusions file did not match any restricted dependencies from dash-licenses output:'); + warn("(perhaps the following entries are no longer required?)"); for (const dependency of unmatched) { console.log(magenta(`> ${dependency}`)); const data = exclusions.get(dependency); @@ -233,18 +252,22 @@ async function main() { console.warn(`${dependency}:`, data); } } + console.log(``) } if (unhandled.length > 0) { - error(`Found results that aren't part of the exclusions!`); + error(`Found restricted dash-licenses results that are not filtered by configuration!`); logRestrictedDashSummaryEntries(unhandled); - process.exit(1); + process.exit(unhandled.length); + } else { + info("Some restricted dependencies were found in dash-licenses results, but all were excluded by configuration!"); } } else { - error(`Found unhandled restricted dependencies!`); + error(`Found restricted dependencies in dash-licenses results!`); logRestrictedDashSummaryEntries(restricted); - process.exit(1); + process.exit(restricted.length); } } + info("Found no dependency that requires further investigation. Good job!"); info('Done.'); process.exit(0); } @@ -424,6 +447,7 @@ async function getRestrictedDependenciesFromSummary(summary) { const restricted = []; for await (const entry of readSummaryLines(summary)) { if (entry.status.toLocaleLowerCase() === 'restricted') { + debug(`dash-licenses found a restricted dependency: ${entry.dependency}`); restricted.push(entry); } }