npm-groovy-lint
Advanced tools
Comparing version 2.2.1-beta.1 to 2.2.1-beta.2
# Changelog | ||
## [3.0.0] 2020-03-23 | ||
### Added | ||
- Local microservice "CodeNarcServer" called via Http by npm-groovy-lint, to avoid loading all groovy/java classes at each lint request. This microservice autokills itself after one hour idle. | ||
## [2.2.0] 2020-02-28 | ||
@@ -4,0 +10,0 @@ |
@@ -5,8 +5,12 @@ #! /usr/bin/env node | ||
const c = require("ansi-colors"); | ||
const cliProgress = require("cli-progress"); | ||
const fse = require("fs-extra"); | ||
const os = require("os"); | ||
const path = require("path"); | ||
const cliProgress = require("cli-progress"); | ||
const { performance } = require("perf_hooks"); | ||
const request = require("request"); | ||
const rp = require("request-promise-native"); | ||
const util = require("util"); | ||
const xml2js = require("xml2js"); | ||
const exec = util.promisify(require("child_process").exec); | ||
const NpmGroovyLintFix = require("./groovy-lint-fix.js"); | ||
@@ -24,2 +28,3 @@ const { npmGroovyLintRules } = require("./groovy-lint-rules.js"); | ||
jdeployFile; | ||
jdeployFilePlanB; | ||
jdeployRootPath; | ||
@@ -37,2 +42,3 @@ parseOptions; | ||
// npm-groovy-lint | ||
serverStatus = "unknown"; | ||
outputType; | ||
@@ -55,2 +61,3 @@ output; | ||
this.jdeployFile = internalOpts.jdeployFile || process.env.JDEPLOY_FILE || "originaljdeploy.js"; | ||
this.jdeployFilePlanB = internalOpts.jdeployFilePlanB || process.env.JDEPLOY_FILE_PLAN_B || "originaljdeployPlanB.js"; | ||
this.jdeployRootPath = internalOpts.jdeployRootPath || process.env.JDEPLOY_ROOT_PATH || __dirname; | ||
@@ -105,3 +112,13 @@ this.parseOptions = internalOpts.parseOptions !== false; | ||
if (this.options.version) { | ||
console.info("v2.0.0"); | ||
let v = process.env.npm_package_version; | ||
if (!v) { | ||
try { | ||
v = require("package.json").version; | ||
} catch { | ||
v = "3.0.0-beta.1"; | ||
} | ||
} | ||
const vLabel = "npm-groovy-lint v" + v; | ||
console.info(vLabel); | ||
this.nglOutputString = vLabel; | ||
return false; | ||
@@ -121,2 +138,28 @@ } | ||
// Kill running CodeNarcServer | ||
if (this.options.killserver) { | ||
const serverUri = this.getCodeNarcServerUri() + "/kill"; | ||
try { | ||
const parsedBody = await rp({ | ||
method: "POST", | ||
uri: serverUri, | ||
timeout: 5000, | ||
json: true | ||
}); | ||
if (parsedBody.status === "killed") { | ||
this.nglOutputString = "CodeNarcServer terminated"; | ||
} else { | ||
this.nglOutputString = "Error killing CodeNarcServer"; | ||
} | ||
} catch (e) { | ||
if (e.message.includes("socket hang up")) { | ||
this.nglOutputString = "CodeNarcServer terminated"; | ||
} else { | ||
this.nglOutputString = "CodeNarcServer was not running"; | ||
} | ||
} | ||
console.info(this.nglOutputString); | ||
return false; | ||
} | ||
//////////////////////////// | ||
@@ -186,7 +229,7 @@ // Build codenarc options // | ||
: this.output | ||
.split(".") | ||
.pop() | ||
.endsWith("xml") | ||
? "xml" | ||
: ""; | ||
.split(".") | ||
.pop() | ||
.endsWith("xml") | ||
? "xml" | ||
: ""; | ||
const ext = this.output.split(".").pop(); | ||
@@ -207,11 +250,67 @@ this.codenarcArgs.push('-report="' + ext + ":" + this.output + '"'); | ||
// Call either CodeNarc local server (better perfs), or java class if server not running | ||
async callCodeNarc() { | ||
let serverSuccess = false; | ||
if (!this.options.noserver) { | ||
serverSuccess = await this.callCodeNarcServer(); | ||
} | ||
if (!serverSuccess) { | ||
await this.callCodeNarcJava(); | ||
} | ||
} | ||
// Call local CodeNarc server if running | ||
async callCodeNarcServer() { | ||
// If use of --codenarcargs, get default values for CodeNarcServer host & port | ||
const serverUri = this.getCodeNarcServerUri(); | ||
// Remove "" around values because they won't get thru system command line parser | ||
const codeNarcArgsForServer = this.codenarcArgs.map(codeNarcArg => { | ||
if (codeNarcArg.includes('="') || codeNarcArg.includes(':"')) { | ||
codeNarcArg = codeNarcArg.replace('="', "=").replace(':"', ":"); | ||
codeNarcArg = codeNarcArg.substring(0, codeNarcArg.length - 1); | ||
} | ||
return codeNarcArg; | ||
}); | ||
// Call CodeNarc server | ||
const codeNarcArgsString = codeNarcArgsForServer.join(" "); | ||
const rqstOptions = { | ||
method: "POST", | ||
uri: serverUri, | ||
body: { | ||
codeNarcArgs: codeNarcArgsString | ||
}, | ||
json: true | ||
}; | ||
let parsedBody = null; | ||
try { | ||
parsedBody = await rp(rqstOptions); | ||
this.serverStatus = "running"; | ||
} catch (e) { | ||
// If server not started , start it and try again | ||
if ( | ||
e.message && | ||
e.message.includes("ECONNREFUSED") && | ||
["unknown", "running"].includes(this.serverStatus) && | ||
(await this.startCodeNarcServer()) | ||
) { | ||
return await this.callCodeNarcServer(); | ||
} | ||
this.serverStatus = "error"; | ||
return false; | ||
} | ||
this.codeNarcStdOut = parsedBody.stdout; | ||
this.codeNarcStdErr = parsedBody.stderr; | ||
return parsedBody.status === "success"; | ||
} | ||
// Call CodeNard java class from renamed jdeploy.js | ||
async callCodeNarc() { | ||
// Build jdeploy codenarc command , filter non-codenarc arguments | ||
async callCodeNarcJava(secondAttempt = false) { | ||
// Build jdeploy codenarc command (request to launch server for next call except if --noserver is sent) | ||
const nodeExe = this.args[0] && this.args[0].includes("node") ? this.args[0] : "node"; | ||
const jDeployCommand = '"' + nodeExe + '" "' + this.jdeployRootPath.trim() + "/" + this.jdeployFile + '" ' + this.codenarcArgs.join(" "); | ||
const jdeployFileToUse = secondAttempt ? this.jdeployFilePlanB : this.jdeployFile; | ||
const jDeployCommand = '"' + nodeExe + '" "' + this.jdeployRootPath.trim() + "/" + jdeployFileToUse + '" ' + this.codenarcArgs.join(" "); | ||
// Start progress bar | ||
if (this.options.verbose) { | ||
console.log("NGL: running CodeNarc with " + this.codenarcArgs.join(" ")); | ||
console.log("NGL: running CodeNarc using " + jDeployCommand); | ||
} | ||
@@ -235,3 +334,2 @@ this.bar = new cliProgress.SingleBar( | ||
// originalJDeploy.js Execution using child process | ||
const exec = util.promisify(require("child_process").exec); | ||
let execRes; | ||
@@ -243,3 +341,9 @@ try { | ||
this.bar.stop(); | ||
throw new Error("NGL: CodeNarc crash: \n" + e.message); | ||
// If failure (missing class com.nvuillam.CodeNarcServer for example, it can happen on Linux, let's try the original org.codenarc.CodeNarc class) | ||
if (!secondAttempt) { | ||
return await this.callCodeNarcJava(true); | ||
} else { | ||
this.codeNarcStdErr = e.stderr; | ||
return; | ||
} | ||
} | ||
@@ -255,2 +359,62 @@ | ||
// Start CodeNarc server so it can be called via Http just after | ||
async startCodeNarcServer() { | ||
this.serverStatus = "unknown"; | ||
const maxAttemptTimeMs = 1000; | ||
let attempts = 1; | ||
const nodeExe = this.args[0] && this.args[0].includes("node") ? this.args[0] : "node"; | ||
const jDeployCommand = '"' + nodeExe + '" "' + this.jdeployRootPath.trim() + "/" + this.jdeployFile + '" --server'; | ||
const serverPingUri = this.getCodeNarcServerUri() + "/ping"; | ||
try { | ||
// Start server using java | ||
exec(jDeployCommand); | ||
// Poll it until it is ready | ||
const start = performance.now(); | ||
await new Promise((resolve, reject) => { | ||
const interval = setInterval(() => { | ||
request | ||
.get(serverPingUri) | ||
.on("response", response => { | ||
if (response.statusCode === 200) { | ||
this.serverStatus = "running"; | ||
clearInterval(interval); | ||
resolve(); | ||
} else if (this.serverStatus === "unknown" && performance.now() - start > maxAttemptTimeMs) { | ||
this.printServerError({ | ||
message: "Timeout after " + maxAttemptTimeMs + "\nResponse: " + JSON.stringify(response.toJSON()) | ||
}); | ||
clearInterval(interval); | ||
reject(); | ||
} | ||
}) | ||
.on("error", e => { | ||
if (this.serverStatus === "unknown" && performance.now() - start > maxAttemptTimeMs) { | ||
this.printServerError(e); | ||
reject(); | ||
} | ||
}); | ||
}, 1000); | ||
}); | ||
} catch (e) { | ||
this.printServerError(e); | ||
return false; | ||
} | ||
console.log(`NGL: Started CodeNarc Server after ${attempts} attempts`); | ||
return true; | ||
} | ||
printServerError(e) { | ||
console.log("NGL: Unable to start CodeNarc Server. Use --noserver if you do not even want to try"); | ||
if (this.verbose && e) { | ||
console.error(e.message); | ||
} | ||
} | ||
// Return CodeNarc server URI | ||
getCodeNarcServerUri() { | ||
// If use of --codenarcargs, get default values for CodeNarcServer host & port | ||
const serverOptions = optionsDefinition.parse({}); | ||
return (this.options.serverhost || serverOptions.serverhost) + ":" + (this.options.serverport || serverOptions.serverport); | ||
} | ||
// After CodeNarc call | ||
@@ -342,6 +506,6 @@ async postProcess() { | ||
: violation["$"].priority === "2" | ||
? "warning" | ||
: violation["$"].priority === "3" | ||
? "info" | ||
: "unknown", | ||
? "warning" | ||
: violation["$"].priority === "3" | ||
? "info" | ||
: "unknown", | ||
msg: violation.Message ? violation.Message[0] : "" | ||
@@ -348,0 +512,0 @@ }; |
@@ -78,3 +78,2 @@ /** | ||
option: "verbose", | ||
alias: "v", | ||
type: "Boolean", | ||
@@ -136,2 +135,25 @@ description: "More outputs in console, including performed fixes" | ||
{ | ||
option: "noserver", | ||
type: "Boolean", | ||
description: | ||
"For better perfs, npm-groovy-lint runs a local server to eep CodeNarc alive instead of loading java/groovy at each call. If you don't want that, send this argument" | ||
}, | ||
{ | ||
option: "serverhost", | ||
type: "String", | ||
default: "http://" + require("ip").address(), //Usually localhost, but not always on CIs (Circle, Jenkins ...) | ||
description: "If use of CodeNarc server, host where is the CodeNarc server (default: localhost)" | ||
}, | ||
{ | ||
option: "serverport", | ||
type: "String", | ||
default: "7484", | ||
description: "If use of CodeNarc server, port of the CodeNarc server (default: 7484)" | ||
}, | ||
{ | ||
option: "killserver", | ||
type: "Boolean", | ||
description: "Terminate the CodeNarcServer if running" | ||
}, | ||
{ | ||
option: "help", | ||
@@ -141,2 +163,8 @@ alias: "h", | ||
description: "Show help (npm-groovy-lint -help OPTIONNAME to see option detail)" | ||
}, | ||
{ | ||
option: "version", | ||
alias: "v", | ||
type: "Boolean", | ||
description: "Show version" | ||
} | ||
@@ -143,0 +171,0 @@ ], |
@@ -69,4 +69,4 @@ #! /usr/bin/env node | ||
var jarName = "{{JAR_NAME}}"; | ||
var mainClass = "org.codenarc.CodeNarc"; | ||
var classPath = "lib/CodeNarc-1.5.jar:lib/groovy-3.0.1/lib/groovy-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-templates-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-xml-3.0.1.jar:lib/slf4j-api-1.7.9.jar:lib/log4j-slf4j-impl-2.13.0.jar:lib/log4j-api-2.13.0.jar:lib/log4j-core-2.13.0.jar:lib/GMetrics-0.7.jar:lib"; | ||
var mainClass = "com.nvuillam.CodeNarcServer"; | ||
var classPath = "lib/CodeNarcServer.jar:lib/CodeNarc-1.5.jar:lib/groovy-3.0.1/lib/groovy-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-templates-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-xml-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-json-3.0.1.jar:lib/slf4j-api-1.7.9.jar:lib/log4j-slf4j-impl-2.13.0.jar:lib/log4j-api-2.13.0.jar:lib/log4j-core-2.13.0.jar:lib/GMetrics-0.7.jar:lib"; | ||
var port = "0"; | ||
@@ -73,0 +73,0 @@ var warPath = ""; |
{ | ||
"name": "npm-groovy-lint", | ||
"version": "2.2.1-beta.1", | ||
"version": "2.2.1-beta.2", | ||
"description": "NPM CodeNarc wrapper to easily lint Groovy files", | ||
@@ -12,2 +12,4 @@ "main": "index.js", | ||
"postbuild": "node patch-jdeploy-after.js", | ||
"groovy:run-server-from-source": "groovy -cp \"lib/CodeNarc-1.5.jar;lib/groovy-3.0.1/lib/groovy-3.0.1.jar;lib/groovy-3.0.1/lib/groovy-templates-3.0.1.jar;lib/groovy-3.0.1/lib/groovy-xml-3.0.1.jar;lib/groovy-3.0.1/lib/groovy-json-3.0.1.jar;lib/slf4j-api-1.7.9.jar;lib/log4j-slf4j-impl-2.13.0.jar;lib/log4j-api-2.13.0.jar;lib/log4j-core-2.13.0.jar;lib/GMetrics-0.7.jar\" groovy/src/main/com/nvuillam/CodeNarcServer.groovy --server", | ||
"groovy:build": "groovyc -cp \"./lib/*\" --encoding utf-8 ./groovy/src/main/com/nvuillam/CodeNarcServer.groovy -d lib && jar -cvfm ./lib/CodeNarcServer.jar MANIFEST.txt lib/com/nvuillam/*.class ", | ||
"test": "mocha \"test/**/*.test.js\"", | ||
@@ -17,3 +19,4 @@ "test:coverage": "nyc npm run test", | ||
"publish:release": "npm run build && npm publish", | ||
"publish:beta": "npm run build && npm publish --tag beta" | ||
"publish:beta": "npm run build && npm publish --tag beta", | ||
"lint-build-all": "npm run lint:fix && npm run groovy:build && npm run build" | ||
}, | ||
@@ -49,3 +52,6 @@ "repository": { | ||
"glob": "^7.1.6", | ||
"ip": "^1.1.5", | ||
"optionator": "^0.8.3", | ||
"request": "^2.88.2", | ||
"request-promise-native": "^1.0.8", | ||
"shelljs": "^0.7.5", | ||
@@ -72,5 +78,6 @@ "xml2js": "^0.4.23" | ||
"jdeploy": { | ||
"jar": "dist/lib/CodeNarc-1.5.jar", | ||
"mainClass": "org.codenarc.CodeNarc", | ||
"classPath": "lib/groovy-3.0.1/lib/groovy-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-templates-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-xml-3.0.1.jar:lib/slf4j-api-1.7.9.jar:lib/log4j-slf4j-impl-2.13.0.jar:lib/log4j-api-2.13.0.jar:lib/log4j-core-2.13.0.jar:lib/GMetrics-0.7.jar:lib", | ||
"jar": "dist/lib/CodeNarcServer.jar", | ||
"mainClass": "com.nvuillam.CodeNarcServer", | ||
"mainClassPlanB": "org.codenarc.CodeNarc", | ||
"classPath": "lib/CodeNarc-1.5.jar:lib/groovy-3.0.1/lib/groovy-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-templates-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-xml-3.0.1.jar:lib/groovy-3.0.1/lib/groovy-json-3.0.1.jar:lib/slf4j-api-1.7.9.jar:lib/log4j-slf4j-impl-2.13.0.jar:lib/log4j-api-2.13.0.jar:lib/log4j-core-2.13.0.jar:lib/GMetrics-0.7.jar:lib", | ||
"files": [ | ||
@@ -77,0 +84,0 @@ { |
@@ -49,4 +49,5 @@ # NPM GROOVY LINT (and FIX !) | ||
| --failonwarning | Boolean | Fails if at least one warning is found | | ||
| --noserver | Boolean | npm-groovy-lint launches a microservice to avoid performance issues caused by loading jaja/groovy everytime,that auto kills itself after 1h idle. Use this argument if you do not want to use this feature | | ||
| --failoninfo | Boolean | Fails if at least one error is found | | ||
| --codenarcargs | Boolean | Use core CodeNarc arguments (all npm-groovy-lint arguments will be ignored)<br/> Doc: http://codenarc.github.io/CodeNarc/codenarc-command-line.html<br/> Example: `npm-groovy-lint --codenarcargs -basedir="jdeploy-bundle/lib/example" -rulesetfiles="file:jdeploy-bundle/lib/example/RuleSet-Groovy.groovy" -maxPriority1Violations=0 -report="xml:ReportTestCodenarc.xml` | | ||
| --codenarcargs | Boolean | Use core CodeNarc arguments (all npm-groovy-lint arguments will be ignored)<br/> Doc: http://codenarc.github.io/CodeNarc/codenarc-command-line.html<br/> Example: `npm-groovy-lint --codenarcargs -basedir="jdeploy-bundle/lib/example" -rulesetfiles="file:jdeploy-bundle/lib/example/RuleSet-Groovy.groovy" -maxPriority1Violations=0 -report="xml:ReportTestCodenarc.xml` | | ||
| -h<br/> --help | Boolean | Show help (npm-groovy-lint -h OPTIONNAME to see option detail with examples) | ||
@@ -53,0 +54,0 @@ # EXAMPLES |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
16176558
60
2194
153
11
11
+ Addedip@^1.1.5
+ Addedrequest@^2.88.2
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedip@1.1.9(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedrequest-promise-core@1.1.4(transitive)
+ Addedrequest-promise-native@1.0.9(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedstealthy-require@1.1.1(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)