@zohodesk/codestandard-validator 1.0.0-exp-3 → 1.0.0-exp-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/hooks/Precommit/lint.js +15 -13
- package/build/hooks/Precommit/pre-commit-default.js +369 -0
- package/build/hooks/hook.js +15 -10
- package/build/utils/General/SonarQubeUtil.js +108 -0
- package/build/utils/PluginsInstallation/installPlugins.js +3 -10
- package/index.js +52 -0
- package/package.json +3 -3
|
@@ -37,6 +37,9 @@ const {
|
|
|
37
37
|
const {
|
|
38
38
|
Logger
|
|
39
39
|
} = require('../../utils/Logger/Logger');
|
|
40
|
+
const {
|
|
41
|
+
default: fetchProjectIssuesViaCurl
|
|
42
|
+
} = require('../../utils/General/SonarQubeUtil');
|
|
40
43
|
const execAsync = promisify(exec);
|
|
41
44
|
async function lintFiles(filePath) {
|
|
42
45
|
const ext = path.extname(filePath);
|
|
@@ -84,7 +87,6 @@ async function runLintWorkflow(files, branch) {
|
|
|
84
87
|
const branchDiff = {
|
|
85
88
|
diffs: []
|
|
86
89
|
};
|
|
87
|
-
let shouldAbort = false;
|
|
88
90
|
var branchName = getBranchName();
|
|
89
91
|
for (const file of files) {
|
|
90
92
|
if (!getSupportedLanguage().includes(path.extname(file))) continue;
|
|
@@ -95,31 +97,31 @@ async function runLintWorkflow(files, branch) {
|
|
|
95
97
|
diff: changeset
|
|
96
98
|
};
|
|
97
99
|
branchDiff.diffs.push(diff);
|
|
98
|
-
// const filteredErrors = impactBasedPrecommit
|
|
99
|
-
// ? await filterErrorsByChangedLines(errors, branch, file)
|
|
100
|
-
// : filterFileLevelErrors(errors);
|
|
101
|
-
|
|
102
|
-
// if (filteredErrors.length > 0) {
|
|
103
|
-
// logErrors(file, filteredErrors);
|
|
104
|
-
// shouldAbort ||= shouldWarningsAbortCommit || !isOnlyWarnings(filteredErrors);
|
|
105
|
-
// }
|
|
106
100
|
}
|
|
107
101
|
const diffPath = path.resolve(getNodeModulesPath(), 'diffBranch.json');
|
|
108
102
|
fs.writeFileSync(diffPath, JSON.stringify(branchDiff));
|
|
109
103
|
const cliobj = {
|
|
110
104
|
env: 'ci',
|
|
111
|
-
cmdExecuted: '
|
|
105
|
+
cmdExecuted: 'precommit'
|
|
112
106
|
};
|
|
113
107
|
const execute = new Execution(EsLint, SonarQube, cliobj);
|
|
114
108
|
await execute.executeLintHandler().finally(async () => {
|
|
115
109
|
await execute.executeMetricHandler();
|
|
110
|
+
/**
|
|
111
|
+
* global.analytics.totalIssues = global.analytics.totalIssues + 1;
|
|
112
|
+
global.analytics.status = "FAILURE";
|
|
113
|
+
global.analytics.message = 'Issues are detected, please review and resolve the errors'
|
|
114
|
+
*/
|
|
115
|
+
const {
|
|
116
|
+
issues,
|
|
117
|
+
hasIssue,
|
|
118
|
+
totalIssues
|
|
119
|
+
} = fetchProjectIssuesViaCurl("projectName");
|
|
116
120
|
});
|
|
117
121
|
Logger.log(Logger.INFO_TYPE, global.analytics);
|
|
118
122
|
return global.analytics.status == 'FAILURE' ? true : false;
|
|
119
123
|
}
|
|
120
124
|
module.exports = {
|
|
121
125
|
runLintWorkflow,
|
|
122
|
-
lintFiles
|
|
123
|
-
findEslintErrors,
|
|
124
|
-
findStyleLintErrors
|
|
126
|
+
lintFiles
|
|
125
127
|
};
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
exec
|
|
5
|
+
} = require('child_process');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const {
|
|
9
|
+
getEslintExecutablePath
|
|
10
|
+
} = require('../../utils/ConfigFileUtils/getEslintExecutablePath');
|
|
11
|
+
const {
|
|
12
|
+
getNodeModulesPath
|
|
13
|
+
} = require('../../utils/General/getNodeModulesPath');
|
|
14
|
+
const {
|
|
15
|
+
filterFiles
|
|
16
|
+
} = require('../../utils/FileAndFolderOperations/filterFiles');
|
|
17
|
+
const {
|
|
18
|
+
Logger
|
|
19
|
+
} = require('../../utils/Logger/Logger');
|
|
20
|
+
const {
|
|
21
|
+
checkIfPluginsAreInstalled
|
|
22
|
+
} = require('../../utils/PluginsInstallation/checkIfPluginsAreInstalled');
|
|
23
|
+
const {
|
|
24
|
+
getBranchName
|
|
25
|
+
} = require('../../utils/GitActions/gitActions');
|
|
26
|
+
const {
|
|
27
|
+
getConfigurationPrecommit,
|
|
28
|
+
getSupportedLanguage
|
|
29
|
+
} = require('../../utils/General/getGeneralInfo');
|
|
30
|
+
const {
|
|
31
|
+
getRootDirectory
|
|
32
|
+
} = require('../../utils/General/RootDirectoryUtils/getRootDirectory');
|
|
33
|
+
const {
|
|
34
|
+
impactBasedPrecommit,
|
|
35
|
+
shouldWarningsAbortCommit
|
|
36
|
+
} = getConfigurationPrecommit();
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @function isMergeCommit - This method check whether it is merge or not
|
|
40
|
+
* @returns {Boolean} - return boolean based on latest merge changes
|
|
41
|
+
*/
|
|
42
|
+
async function isMergeCommit() {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
exec('git rev-parse -q --verify MERGE_HEAD', (error, stderr, stdout) => {
|
|
45
|
+
if (error) {
|
|
46
|
+
reject(error.toString().trim());
|
|
47
|
+
} else if (stderr) {
|
|
48
|
+
resolve(stderr.trim());
|
|
49
|
+
} else if (stdout) {
|
|
50
|
+
resolve(stdout.trim());
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @function {getStagedFiles} - methods return staged files
|
|
58
|
+
* @returns {Array<string>} - array of files
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
async function getStagedFiles() {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
exec("git diff --staged --name-only", (error, stderr, stdout) => {
|
|
64
|
+
if (error) {
|
|
65
|
+
if (error != null) reject("Couldn't fetch staged files");
|
|
66
|
+
} else if (stderr) {
|
|
67
|
+
resolve(filterDeltedFileFromStagedFiles(stderr.trim().split('\n')));
|
|
68
|
+
} else if (stdout.trim() === '') {
|
|
69
|
+
resolve(stdout.trim());
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @function {filterDeltedFileFromStagedFiles} - filter deleted staged files
|
|
77
|
+
* @param {Array<string>} files - staged files
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
80
|
+
function filterDeltedFileFromStagedFiles(files) {
|
|
81
|
+
return files.filter(file => {
|
|
82
|
+
const absolutePath = path.resolve(getRootDirectory(), file);
|
|
83
|
+
if (fs.existsSync(absolutePath)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async function lintFiles(filePath) {
|
|
90
|
+
switch (String(path.extname(filePath))) {
|
|
91
|
+
case '.js':
|
|
92
|
+
case '.ts':
|
|
93
|
+
case '.tsx':
|
|
94
|
+
case '.jsx':
|
|
95
|
+
case '.properties':
|
|
96
|
+
{
|
|
97
|
+
return await findEslintErrors(filePath);
|
|
98
|
+
}
|
|
99
|
+
case '.css':
|
|
100
|
+
case '.scss':
|
|
101
|
+
{
|
|
102
|
+
return await findStyleLintErrors(filePath);
|
|
103
|
+
}
|
|
104
|
+
default:
|
|
105
|
+
{
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @function findEslintErrors - method Lint given file based on given configuration
|
|
113
|
+
* @param {*} file - path of file to lint
|
|
114
|
+
* @returns {Array<string>} - array of command line report as a string
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
function findEslintErrors(file) {
|
|
118
|
+
let nodeModulesPathOfProject = `${getNodeModulesPath()}`;
|
|
119
|
+
let eslintExecutablePath = getEslintExecutablePath();
|
|
120
|
+
let eslintConfigurationFilePath = `${nodeModulesPathOfProject}/.eslintrc.js`;
|
|
121
|
+
let isEslintExecutablePresent = fs.existsSync(eslintExecutablePath) ? true : false;
|
|
122
|
+
let isNodeModulesPresent = fs.existsSync(nodeModulesPathOfProject);
|
|
123
|
+
if (isNodeModulesPresent) {
|
|
124
|
+
if (isEslintExecutablePresent) {
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
exec(`npx --ignore-existing "${eslintExecutablePath}" --config "${eslintConfigurationFilePath}" --no-inline-config --resolve-plugins-relative-to="${nodeModulesPathOfProject}/node_modules" ${file}`, (error, stderr, stdout) => {
|
|
127
|
+
if (stderr) {
|
|
128
|
+
resolve(stderr.trim().split('\n'));
|
|
129
|
+
} else if (error) {
|
|
130
|
+
Logger.log(Logger.FAILURE_TYPE, error);
|
|
131
|
+
reject("Error executing eslint command");
|
|
132
|
+
} else {
|
|
133
|
+
resolve([]);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
Logger.log(Logger.INFO_TYPE, 'Eslint executable not found. make sure eslint plugin is installed');
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
Logger.log(Logger.INFO_TYPE, 'node_modules not found');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @param {*} params
|
|
148
|
+
*/
|
|
149
|
+
function findStyleLintErrors(filePath) {
|
|
150
|
+
const configFilePath = path.resolve(getNodeModulesPath(), '.stylelintrc.js');
|
|
151
|
+
const absolutePath = path.join(getRootDirectory(), filePath);
|
|
152
|
+
try {
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
exec(`npx stylelint ${absolutePath} --config ${configFilePath}`, {
|
|
155
|
+
cwd: getNodeModulesPath()
|
|
156
|
+
}, (error, stderr, stdout) => {
|
|
157
|
+
if (stdout) {
|
|
158
|
+
resolve(stdout.trim().split('\n'));
|
|
159
|
+
}
|
|
160
|
+
// if(stderr){
|
|
161
|
+
// resolve(stderr.trim().split('\n'))
|
|
162
|
+
// }
|
|
163
|
+
else if (error) {
|
|
164
|
+
Logger.log(Logger.FAILURE_TYPE, error);
|
|
165
|
+
reject("Error executing stylelint command");
|
|
166
|
+
} else {
|
|
167
|
+
resolve([]);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
} catch (error) {
|
|
172
|
+
Logger.log(Logger.FAILURE_TYPE, `Issue is lint css files`);
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @function {calculateGitDiffForFile} - method calculate diff of file
|
|
179
|
+
* @param {*} branch_name - branch name
|
|
180
|
+
* @param {*} file - path of file
|
|
181
|
+
* @returns {Promise<Array<string>>} - array of command line report as a string
|
|
182
|
+
*/
|
|
183
|
+
async function calculateGitDiffForFile(branch_name, file) {
|
|
184
|
+
let gitDiffCommand = `git diff -U0 ${branch_name.trim()} ${file}`;
|
|
185
|
+
return new Promise((resolve, reject) => {
|
|
186
|
+
exec(gitDiffCommand, (error, stderr) => {
|
|
187
|
+
if (stderr) {
|
|
188
|
+
resolve(stderr.trim().split('\n'));
|
|
189
|
+
} else if (error) {
|
|
190
|
+
reject(error);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* @function {areAllPluginsInstalled} - method whether plugin is installed or not
|
|
197
|
+
* @returns {Boolean} - return boolean based on plugin installed or not
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
function areAllPluginsInstalled() {
|
|
201
|
+
let unInstalledPlugins = checkIfPluginsAreInstalled().uninstalledPlugins;
|
|
202
|
+
return unInstalledPlugins.length === 0 ? true : false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @function {isOnlyWarningsPresentInFile} - method that checks if only eslint warnings are present in a file
|
|
207
|
+
* @returns {Boolean} - returns boolean based on only warnings present or not in file
|
|
208
|
+
*/
|
|
209
|
+
function isOnlyWarningsPresentInFile(eslintErrorsPresent) {
|
|
210
|
+
let severityOfEachErrorInFile = [];
|
|
211
|
+
eslintErrorsPresent.map(error => {
|
|
212
|
+
let partsInString = error.split(" ");
|
|
213
|
+
let severityOfError = partsInString.find(word => word === 'error' || word === 'warning' || word === '✖');
|
|
214
|
+
severityOfEachErrorInFile.push(severityOfError);
|
|
215
|
+
});
|
|
216
|
+
return !(severityOfEachErrorInFile.includes('✖') || severityOfEachErrorInFile.includes('error'));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @function {preCommitHook} - method execute pre commit hook
|
|
221
|
+
* @returns {void}
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
async function preCommitHook_default() {
|
|
225
|
+
Logger.log(Logger.INFO_TYPE, 'Executing pre commit hook...');
|
|
226
|
+
Logger.log(Logger.INFO_TYPE, `working dir : ${process.cwd()}`);
|
|
227
|
+
try {
|
|
228
|
+
let isMerge = await isMergeCommit();
|
|
229
|
+
Logger.log(Logger.INFO_TYPE, 'Looks like you have merged. So skipping pre commit check');
|
|
230
|
+
process.exit(0);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (areAllPluginsInstalled()) {
|
|
233
|
+
let staged_files = [];
|
|
234
|
+
let eslintConfigFiles = ['.eslintrc.js'];
|
|
235
|
+
let exemptionFiles = [];
|
|
236
|
+
let current_branch = '';
|
|
237
|
+
let hasEslintErrorsInChangedLines = false;
|
|
238
|
+
let hasEslintErrorsInFiles = false;
|
|
239
|
+
let areFilesStaged = false;
|
|
240
|
+
let shouldAbortCommit = false;
|
|
241
|
+
try {
|
|
242
|
+
current_branch = await getBranchName();
|
|
243
|
+
} catch {
|
|
244
|
+
Logger.log(Logger.INFO_TYPE, "Error fetching current branch");
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
staged_files = await getStagedFiles();
|
|
248
|
+
if (!staged_files.length == 0) {
|
|
249
|
+
const {
|
|
250
|
+
JsFiles: staged_filesJS,
|
|
251
|
+
CssFiles
|
|
252
|
+
} = filterFiles(staged_files, eslintConfigFiles, true);
|
|
253
|
+
|
|
254
|
+
// staged_filesJS = filterFiles(staged_filesJS,exemptionFiles) //this is the code for giving exemption to a file during pre commit
|
|
255
|
+
// if(staged_filesJS.length === 0){
|
|
256
|
+
// Logger.log(Logger.SUCCESS_TYPE,`Commit Successful`)
|
|
257
|
+
// process.exit(0)
|
|
258
|
+
// }
|
|
259
|
+
|
|
260
|
+
// CssFiles not Enabled For while
|
|
261
|
+
areFilesStaged = true;
|
|
262
|
+
var stagedFiles = [...staged_filesJS];
|
|
263
|
+
for (let file in stagedFiles) {
|
|
264
|
+
let currentFileName = stagedFiles[file];
|
|
265
|
+
let changedLinesArray = [];
|
|
266
|
+
let eslintErrorsInChangedLines = [];
|
|
267
|
+
let isOnlyEslintWarningsPresentInFile = false;
|
|
268
|
+
if (getSupportedLanguage().includes(path.extname(stagedFiles[file]))) {
|
|
269
|
+
try {
|
|
270
|
+
var errorsInFile = await lintFiles(stagedFiles[file]);
|
|
271
|
+
// eslintErrorsInFile = impactBasedPrecommit == false ? filterWarningInFile(errorsInFile) : errorsInFile
|
|
272
|
+
if (stagedFiles[file] && typeof stagedFiles[file] == 'string') {
|
|
273
|
+
if (!errorsInFile.length == 0) {
|
|
274
|
+
//Calculating changed lines in a file and storing them in respective arrays
|
|
275
|
+
if (impactBasedPrecommit) {
|
|
276
|
+
//git diff is computed and stored in an array
|
|
277
|
+
let git_diff = await calculateGitDiffForFile(current_branch, stagedFiles[file]);
|
|
278
|
+
changedLinesArray = git_diff.filter(line => line.startsWith('@@'));
|
|
279
|
+
let changedLinesStartArray = [];
|
|
280
|
+
let changedLinesEndArray = [];
|
|
281
|
+
for (let number of changedLinesArray) {
|
|
282
|
+
let changesStartLine = parseInt(number.split(' ')[2].split(',')[0]);
|
|
283
|
+
changedLinesStartArray.push(changesStartLine);
|
|
284
|
+
let changesEndLine = number.split(' ')[2].split(',')[1];
|
|
285
|
+
if (changesEndLine === undefined) {
|
|
286
|
+
changedLinesEndArray.push(changesStartLine);
|
|
287
|
+
} else {
|
|
288
|
+
changedLinesEndArray.push(changesStartLine + parseInt(changesEndLine) - 1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (let error = 1; error < errorsInFile.length - 2; error++) {
|
|
292
|
+
//errorsInFile[error].trim() - 69:26 error => Do not hardcode content. Use I18N key instead no-hardcoding/no-hardcoding,
|
|
293
|
+
//errorsInFile[error].trim().split(' ')[0] => 69:26
|
|
294
|
+
//errorsInFile[error].trim().split(' ')[0].split(':')[0] => 69
|
|
295
|
+
|
|
296
|
+
let eslintErrorLineNumber = errorsInFile[error].trim().split(' ')[0].split(':')[0];
|
|
297
|
+
for (let lineNumber in changedLinesStartArray) {
|
|
298
|
+
if (eslintErrorLineNumber >= changedLinesStartArray[lineNumber] && eslintErrorLineNumber <= changedLinesEndArray[lineNumber]) {
|
|
299
|
+
eslintErrorsInChangedLines.push(errorsInFile[error]);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (eslintErrorsInChangedLines.length > 0) {
|
|
304
|
+
isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(eslintErrorsInChangedLines);
|
|
305
|
+
Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
|
|
306
|
+
for (let eslintError of eslintErrorsInChangedLines) {
|
|
307
|
+
Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
|
|
308
|
+
}
|
|
309
|
+
if (shouldWarningsAbortCommit) {
|
|
310
|
+
hasEslintErrorsInChangedLines = true;
|
|
311
|
+
shouldAbortCommit = true;
|
|
312
|
+
} else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
|
|
313
|
+
hasEslintErrorsInChangedLines = false;
|
|
314
|
+
} else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
|
|
315
|
+
hasEslintErrorsInChangedLines = true;
|
|
316
|
+
shouldAbortCommit = true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
if (errorsInFile.length > 0) {
|
|
321
|
+
let startIndex = 1;
|
|
322
|
+
let endIndex = errorsInFile.length - 2;
|
|
323
|
+
let listOsEslintErrors = errorsInFile.slice(startIndex, endIndex);
|
|
324
|
+
isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(listOsEslintErrors);
|
|
325
|
+
Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
|
|
326
|
+
for (let eslintError of listOsEslintErrors) {
|
|
327
|
+
Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
|
|
328
|
+
}
|
|
329
|
+
if (shouldWarningsAbortCommit) {
|
|
330
|
+
hasEslintErrorsInFiles = true;
|
|
331
|
+
shouldAbortCommit = true;
|
|
332
|
+
} else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
|
|
333
|
+
hasEslintErrorsInFiles = false;
|
|
334
|
+
} else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
|
|
335
|
+
hasEslintErrorsInFiles = true;
|
|
336
|
+
shouldAbortCommit = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
} catch (err) {
|
|
343
|
+
Logger.log(Logger.FAILURE_TYPE, err);
|
|
344
|
+
Logger.log(Logger.FAILURE_TYPE, "Error in executing lint command");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
} else if (staged_files.length === 0) {
|
|
349
|
+
Logger.log(Logger.INFO_TYPE, 'No files have been staged. Stage your files before committing');
|
|
350
|
+
}
|
|
351
|
+
} catch {
|
|
352
|
+
Logger.log(Logger.INFO_TYPE, 'Error executing pre commit hook');
|
|
353
|
+
}
|
|
354
|
+
if (shouldAbortCommit) {
|
|
355
|
+
Logger.log(Logger.FAILURE_TYPE, `There are linter errors/warnings present. So commit is aborted.`);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
} else if (shouldAbortCommit === false && staged_files.length !== 0) {
|
|
358
|
+
Logger.log(Logger.SUCCESS_TYPE, `Commit Successful`);
|
|
359
|
+
process.exit(0);
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
Logger.log(Logger.FAILURE_TYPE, 'Commit failed since some lint plugins are not installed');
|
|
363
|
+
Logger.log(Logger.INFO_TYPE, `Kindly execute the command \x1b[37mnpx ZDPrecommit setupPlugins \x1b[33mfrom the location where package.json is present to install the plugins`);
|
|
364
|
+
Logger.log(Logger.INFO_TYPE, 'Execute the command and kindly try committing again.');
|
|
365
|
+
process.exit(1);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
preCommitHook_default();
|
package/build/hooks/hook.js
CHANGED
|
@@ -4,23 +4,23 @@ const {
|
|
|
4
4
|
getLastCommitHash,
|
|
5
5
|
getStoredCommitHash,
|
|
6
6
|
updateJsonFile
|
|
7
|
-
} = require(
|
|
7
|
+
} = require('../utils/General/getGeneralInfo');
|
|
8
8
|
const {
|
|
9
9
|
executeMethodsThatReturnBooleanValue
|
|
10
|
-
} = require(
|
|
10
|
+
} = require('../utils/General/wrapperFunctionToExecuteAFunction');
|
|
11
11
|
const {
|
|
12
12
|
cloneViaCdt
|
|
13
|
-
} = require(
|
|
13
|
+
} = require('../utils/CloneCommonLinterRepo/cloneViaCdt');
|
|
14
14
|
const {
|
|
15
15
|
getPluginsToInstall
|
|
16
|
-
} = require(
|
|
16
|
+
} = require('../utils/PluginsInstallation/checkIfPluginsAreInstalled');
|
|
17
17
|
const {
|
|
18
18
|
installPlugins
|
|
19
|
-
} = require(
|
|
20
|
-
const path = require(
|
|
19
|
+
} = require('../utils/PluginsInstallation/installPlugins');
|
|
20
|
+
const path = require('path');
|
|
21
21
|
const {
|
|
22
22
|
Logger
|
|
23
|
-
} = require(
|
|
23
|
+
} = require('../utils/Logger/Logger');
|
|
24
24
|
async function hooks() {
|
|
25
25
|
var jsonFilePath = path.join(__dirname, '..', '..', 'jsonUtils', 'fsUtils.json');
|
|
26
26
|
if (!(getLastCommitHash() == getStoredCommitHash())) {
|
|
@@ -29,12 +29,17 @@ async function hooks() {
|
|
|
29
29
|
return data;
|
|
30
30
|
});
|
|
31
31
|
Logger.log(Logger.INFO_TYPE, `Some rules and plugins are being fetched from a remote source and installed...`);
|
|
32
|
-
await executeMethodsThatReturnBooleanValue(
|
|
32
|
+
await executeMethodsThatReturnBooleanValue('Make sure zgit.csez.zohocorpin.com is accessible', cloneViaCdt, null);
|
|
33
33
|
const {
|
|
34
34
|
uninstalledPlugins
|
|
35
35
|
} = getPluginsToInstall();
|
|
36
|
-
await executeMethodsThatReturnBooleanValue(
|
|
36
|
+
await executeMethodsThatReturnBooleanValue('Some issue occurred in installing plugins', installPlugins, uninstalledPlugins);
|
|
37
|
+
}
|
|
38
|
+
console.log(process.env);
|
|
39
|
+
if (process.env.defaultprecommit) {
|
|
40
|
+
require('./Precommit/pre-commit-default');
|
|
41
|
+
} else {
|
|
42
|
+
require('./Precommit/commit');
|
|
37
43
|
}
|
|
38
|
-
require('./Precommit/commit');
|
|
39
44
|
}
|
|
40
45
|
hooks();
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _Logger = require("../Logger/Logger");
|
|
8
|
+
var _getGeneralInfo = require("./getGeneralInfo");
|
|
9
|
+
var _child_process = require("child_process");
|
|
10
|
+
/**
|
|
11
|
+
* Constructs a URL for searching issues in SonarQube.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} componentKey - The key of the component to search issues for.
|
|
14
|
+
* @returns {string} The fully constructed URL for the SonarQube issues search API.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
function buildIssuesSearchUrl(componentKey) {
|
|
18
|
+
const {
|
|
19
|
+
metricServerHost
|
|
20
|
+
} = (0, _getGeneralInfo.getConfigurationPrecommit)();
|
|
21
|
+
const base = `${"https://client-linters.zdesk.csez.zohocorpin.com" || metricServerHost}/api/issues/search`;
|
|
22
|
+
const params = new URLSearchParams({
|
|
23
|
+
componentKeys: componentKey,
|
|
24
|
+
s: 'FILE_LINE',
|
|
25
|
+
resolved: 'false',
|
|
26
|
+
ps: '100',
|
|
27
|
+
facets: 'severities,types',
|
|
28
|
+
additionalFields: '_all',
|
|
29
|
+
timeZone: 'Asia/Calcutta'
|
|
30
|
+
});
|
|
31
|
+
return `${base}?${params.toString()}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extract minimal issue info from SonarQube issues JSON.
|
|
36
|
+
*/
|
|
37
|
+
function extractIssues(json) {
|
|
38
|
+
var hasIssue = false;
|
|
39
|
+
var totalIssues = json.issues.length;
|
|
40
|
+
if (!json || !Array.isArray(json.issues)) return [];
|
|
41
|
+
return {
|
|
42
|
+
issues: json.issues.map(i => {
|
|
43
|
+
if (i.severity == 'MAJOR') {
|
|
44
|
+
hasIssue = true;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
key: i.key,
|
|
48
|
+
component: i.component,
|
|
49
|
+
severity: i.severity,
|
|
50
|
+
type: i.type,
|
|
51
|
+
message: i.message,
|
|
52
|
+
line: i.line,
|
|
53
|
+
rule: i.rule,
|
|
54
|
+
status: i.status
|
|
55
|
+
};
|
|
56
|
+
}),
|
|
57
|
+
hasIssue,
|
|
58
|
+
totalIssues
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Fetches project issues for a given component key using a cURL command.
|
|
64
|
+
*
|
|
65
|
+
* This function constructs a URL to search for issues, decrypts an API token,
|
|
66
|
+
* and executes a cURL command to retrieve the issues in JSON format. It then
|
|
67
|
+
* extracts and returns the issues along with the raw JSON response.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} componentKey - The key of the component for which issues are to be fetched.
|
|
70
|
+
* @returns {Object} An object containing:
|
|
71
|
+
* - {Object|null} raw: The raw JSON response from the API, or null if an error occurred.
|
|
72
|
+
* - {Array} issues: An array of extracted issues, or an empty array if an error occurred.
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
function fetchProjectIssuesViaCurl(componentKey) {
|
|
76
|
+
_Logger.Logger.log(_Logger.Logger.INFO_TYPE, `\n Fetching issues (curl) for component: ${componentKey}`);
|
|
77
|
+
const url = buildIssuesSearchUrl(componentKey);
|
|
78
|
+
try {
|
|
79
|
+
const token = 'sqa_1f6675c05f63c4784dc741ce751efa0066d2693c' || decrypt(getAPIToken(), process.env.DECRYPT_TOKEN);
|
|
80
|
+
const command = `curl --tlsv1.2 -s -u "${token}:" "${url}"`;
|
|
81
|
+
console.log("command", command);
|
|
82
|
+
const output = (0, _child_process.execSync)(command).toString();
|
|
83
|
+
const json = JSON.parse(output);
|
|
84
|
+
const {
|
|
85
|
+
issues,
|
|
86
|
+
hasIssue,
|
|
87
|
+
totalIssues
|
|
88
|
+
} = extractIssues(json);
|
|
89
|
+
_Logger.Logger.log(_Logger.Logger.INFO_TYPE, `Retrieved ${issues.length} issues.`);
|
|
90
|
+
return {
|
|
91
|
+
raw: json,
|
|
92
|
+
issues,
|
|
93
|
+
hasIssue,
|
|
94
|
+
totalIssues
|
|
95
|
+
};
|
|
96
|
+
} catch (err) {
|
|
97
|
+
_Logger.Logger.log(_Logger.Logger.FAILURE_TYPE, 'Issue fetching project issues (curl)');
|
|
98
|
+
_Logger.Logger.log(_Logger.Logger.FAILURE_TYPE, err);
|
|
99
|
+
return {
|
|
100
|
+
raw: null,
|
|
101
|
+
issues: [],
|
|
102
|
+
hasIssue: true,
|
|
103
|
+
totalIssues: 0
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
console.log(fetchProjectIssuesViaCurl('zohogc_client_master_rajasekar.hm_Dev-report'));
|
|
108
|
+
var _default = exports.default = fetchProjectIssuesViaCurl;
|
|
@@ -15,6 +15,7 @@ const {
|
|
|
15
15
|
const {
|
|
16
16
|
getNodeModulesPath
|
|
17
17
|
} = require('../General/getNodeModulesPath');
|
|
18
|
+
const path = require('path');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* @function installPlugins - installs uninstalled plugins for the project
|
|
@@ -32,15 +33,7 @@ function installPlugins(pluginsToBeInstalled) {
|
|
|
32
33
|
}], '', 'Some issue occured while installing plugins', false, true);
|
|
33
34
|
if (arePluginsInstalledSuccessfully) {
|
|
34
35
|
Logger.log(Logger.SUCCESS_TYPE, 'Plugins installation successful');
|
|
35
|
-
|
|
36
|
-
// if(isPackageJsonRestored){
|
|
37
|
-
// createVersionControlFile(pluginsToBeInstalled)
|
|
38
|
-
// return true
|
|
39
|
-
// }
|
|
40
|
-
// else{
|
|
41
|
-
// Logger.log(Logger.FAILURE_TYPE,'Unable to restore package.json content')
|
|
42
|
-
// return false
|
|
43
|
-
// }
|
|
36
|
+
return restorePackageJsonContent(packageJsonBeforePluginsInstallation);
|
|
44
37
|
} else {
|
|
45
38
|
Logger.log(Logger.FAILURE_TYPE, "Unable to install plugins. Kindly retry the command");
|
|
46
39
|
return false;
|
|
@@ -66,7 +59,7 @@ function getPackageJsonContentBeforeInstallingPlugins() {
|
|
|
66
59
|
* @returns {Boolean} - indicating the success or failure of restoring package.json content
|
|
67
60
|
*/
|
|
68
61
|
function restorePackageJsonContent(packageJsonContentBeforePluginsInstallation) {
|
|
69
|
-
let packageJsonFilePath =
|
|
62
|
+
let packageJsonFilePath = path.join(getNodeModulesPath(), 'package.json');
|
|
70
63
|
let isPackageJsonRestored = executeSynchronizedCommands(writeFileSync, [packageJsonFilePath, JSON.stringify(packageJsonContentBeforePluginsInstallation, null, 2)], 'Package.json content restored successfully', 'Unable to restore package.json content', false, true);
|
|
71
64
|
return isPackageJsonRestored;
|
|
72
65
|
}
|
package/index.js
CHANGED
|
@@ -6,3 +6,55 @@ module.exports = {
|
|
|
6
6
|
plugins,
|
|
7
7
|
extendPlugins
|
|
8
8
|
};
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function config() {
|
|
13
|
+
return {
|
|
14
|
+
addConfig(conf){
|
|
15
|
+
return conf
|
|
16
|
+
},
|
|
17
|
+
addRule(){
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const rule = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: "problem",
|
|
28
|
+
docs: {
|
|
29
|
+
description: "Disallow the use of 'debugger' statements",
|
|
30
|
+
category: "Possible Errors",
|
|
31
|
+
recommended: true,
|
|
32
|
+
},
|
|
33
|
+
schema: [], // No options for this rule
|
|
34
|
+
messages: {
|
|
35
|
+
noDebugger: "Unexpected 'debugger' statement.",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
create(){
|
|
39
|
+
return {
|
|
40
|
+
DebuggerStatement(node) {
|
|
41
|
+
context.report({
|
|
42
|
+
node,
|
|
43
|
+
messageId: "noDebugger",
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
const { addConfig, addRule } = config()
|
|
52
|
+
|
|
53
|
+
addRule([{name:"dummyrule",conf:rule}])
|
|
54
|
+
|
|
55
|
+
addConfig([{
|
|
56
|
+
files: ["config/*.js"],
|
|
57
|
+
rules: {
|
|
58
|
+
"no-console": "off",
|
|
59
|
+
},
|
|
60
|
+
}])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/codestandard-validator",
|
|
3
|
-
"version": "1.0.0-exp-
|
|
3
|
+
"version": "1.0.0-exp-4",
|
|
4
4
|
"description": "library to enforce code standard using eslint",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
},
|
|
16
16
|
"type": "commonjs",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@zohodesk/codestandard-analytics":"1.0.2-exp-3",
|
|
18
|
+
"@zohodesk/codestandard-analytics": "1.0.2-exp-3",
|
|
19
19
|
"@zohodesk-private/client_deployment_tool": "0.0.5",
|
|
20
20
|
"eslint": "8.26.0",
|
|
21
|
-
"stylelint":"16.23.0"
|
|
21
|
+
"stylelint": "16.23.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@babel/core": "7.24.7",
|