@zohodesk/codestandard-validator 0.0.2 → 0.0.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.
@@ -12,7 +12,8 @@ const {
12
12
  getNodeModulesPath
13
13
  } = require('../../utils/General/getNodeModulesPath');
14
14
  const {
15
- filterFiles
15
+ filterFiles,
16
+ filterWarningInFile
16
17
  } = require('../../utils/FileAndFolderOperations/filterFiles');
17
18
  const {
18
19
  Logger
@@ -23,6 +24,17 @@ const {
23
24
  const {
24
25
  getBranchName
25
26
  } = require('../../utils/GitActions/gitActions');
27
+ const {
28
+ getConfigurationPrecommit,
29
+ getSupportedLanguage
30
+ } = require('../../utils/General/getGeneralInfo');
31
+ const {
32
+ getRootDirectory
33
+ } = require('../../utils/General/RootDirectoryUtils/getRootDirectory');
34
+ const {
35
+ impactBasedPrecommit,
36
+ shouldWarningsAbortCommit
37
+ } = getConfigurationPrecommit();
26
38
 
27
39
  /**
28
40
  * @function isMergeCommit - This method check whether it is merge or not
@@ -53,7 +65,7 @@ async function getStagedFiles() {
53
65
  if (error) {
54
66
  if (error != null) reject("Couldn't fetch staged files");
55
67
  } else if (stderr) {
56
- resolve(stderr.trim().split('\n'));
68
+ resolve(filterDeltedFileFromStagedFiles(stderr.trim().split('\n')));
57
69
  } else if (stdout.trim() === '') {
58
70
  resolve(stdout.trim());
59
71
  }
@@ -61,6 +73,21 @@ async function getStagedFiles() {
61
73
  });
62
74
  }
63
75
 
76
+ /**
77
+ * @function {filterDeltedFileFromStagedFiles} - filter deleted staged files
78
+ * @param {Array<string>} files - staged files
79
+ * @returns
80
+ */
81
+ function filterDeltedFileFromStagedFiles(files) {
82
+ return files.filter(file => {
83
+ const absolutePath = path.resolve(getRootDirectory(), file);
84
+ if (fs.existsSync(absolutePath)) {
85
+ return true;
86
+ }
87
+ return false;
88
+ });
89
+ }
90
+
64
91
  /**
65
92
  * @function findEslintErrors - method Lint given file based on given configuration
66
93
  * @param {*} file - path of file to lint
@@ -122,6 +149,20 @@ function areAllPluginsInstalled() {
122
149
  return unInstalledPlugins.length === 0 ? true : false;
123
150
  }
124
151
 
152
+ /**
153
+ * @function {isOnlyWarningsPresentInFile} - method that checks if only eslint warnings are present in a file
154
+ * @returns {Boolean} - returns boolean based on only warnings present or not in file
155
+ */
156
+ function isOnlyWarningsPresentInFile(eslintErrorsPresent) {
157
+ let severityOfEachErrorInFile = [];
158
+ eslintErrorsPresent.map(error => {
159
+ let partsInString = error.split(" ");
160
+ let severityOfError = partsInString.find(word => word === 'error' || word === 'warning');
161
+ severityOfEachErrorInFile.push(severityOfError);
162
+ });
163
+ return !severityOfEachErrorInFile.includes('error');
164
+ }
165
+
125
166
  /**
126
167
  * @function {preCommitHook} - method execute pre commit hook
127
168
  * @returns {void}
@@ -141,7 +182,9 @@ async function preCommitHook() {
141
182
  let exemptionFiles = [];
142
183
  let current_branch = '';
143
184
  let hasEslintErrorsInChangedLines = false;
185
+ let hasEslintErrorsInFiles = false;
144
186
  let areFilesStaged = false;
187
+ let shouldAbortCommit = false;
145
188
  try {
146
189
  current_branch = await getBranchName();
147
190
  } catch {
@@ -162,46 +205,78 @@ async function preCommitHook() {
162
205
  let currentFileName = staged_files[file];
163
206
  let changedLinesArray = [];
164
207
  let eslintErrorsInChangedLines = [];
165
- if (path.extname(staged_files[file]) === '.js') {
208
+ let isOnlyEslintWarningsPresentInFile = false;
209
+ if (getSupportedLanguage().includes(path.extname(staged_files[file]))) {
166
210
  try {
167
- let eslintErrorsInFile = await findEslintErrors(staged_files[file]);
211
+ var eslintErrorsInFile = await findEslintErrors(staged_files[file]);
212
+ // eslintErrorsInFile = impactBasedPrecommit == false ? filterWarningInFile(eslintErrorsInFile) : eslintErrorsInFile
168
213
  if (staged_files[file] && typeof staged_files[file] == 'string') {
169
214
  if (!eslintErrorsInFile.length == 0) {
170
- //git diff is computed and stored in an array
171
- let git_diff = await calculateGitDiffForFile(current_branch, staged_files[file]);
172
- changedLinesArray = git_diff.filter(line => line.startsWith('@@'));
173
- let changedLinesStartArray = [];
174
- let changedLinesEndArray = [];
175
-
176
215
  //Calculating changed lines in a file and storing them in respective arrays
177
- for (let number of changedLinesArray) {
178
- let changesStartLine = parseInt(number.split(' ')[2].split(',')[0]);
179
- changedLinesStartArray.push(changesStartLine);
180
- let changesEndLine = number.split(' ')[2].split(',')[1];
181
- if (changesEndLine === undefined) {
182
- changedLinesEndArray.push(changesStartLine);
183
- } else {
184
- changedLinesEndArray.push(changesStartLine + parseInt(changesEndLine) - 1);
216
+ if (impactBasedPrecommit) {
217
+ //git diff is computed and stored in an array
218
+ let git_diff = await calculateGitDiffForFile(current_branch, staged_files[file]);
219
+ changedLinesArray = git_diff.filter(line => line.startsWith('@@'));
220
+ let changedLinesStartArray = [];
221
+ let changedLinesEndArray = [];
222
+ for (let number of changedLinesArray) {
223
+ let changesStartLine = parseInt(number.split(' ')[2].split(',')[0]);
224
+ changedLinesStartArray.push(changesStartLine);
225
+ let changesEndLine = number.split(' ')[2].split(',')[1];
226
+ if (changesEndLine === undefined) {
227
+ changedLinesEndArray.push(changesStartLine);
228
+ } else {
229
+ changedLinesEndArray.push(changesStartLine + parseInt(changesEndLine) - 1);
230
+ }
185
231
  }
186
- }
187
- for (let error = 1; error < eslintErrorsInFile.length - 2; error++) {
188
- //eslintErrorsInFile[error].trim() - 69:26 error => Do not hardcode content. Use I18N key instead no-hardcoding/no-hardcoding,
189
- //eslintErrorsInFile[error].trim().split(' ')[0] => 69:26
190
- //eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0] => 69
232
+ for (let error = 1; error < eslintErrorsInFile.length - 2; error++) {
233
+ //eslintErrorsInFile[error].trim() - 69:26 error => Do not hardcode content. Use I18N key instead no-hardcoding/no-hardcoding,
234
+ //eslintErrorsInFile[error].trim().split(' ')[0] => 69:26
235
+ //eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0] => 69
191
236
 
192
- let eslintErrorLineNumber = eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0];
193
- for (let lineNumber in changedLinesStartArray) {
194
- if (eslintErrorLineNumber >= changedLinesStartArray[lineNumber] && eslintErrorLineNumber <= changedLinesEndArray[lineNumber]) {
195
- eslintErrorsInChangedLines.push(eslintErrorsInFile[error]);
237
+ let eslintErrorLineNumber = eslintErrorsInFile[error].trim().split(' ')[0].split(':')[0];
238
+ for (let lineNumber in changedLinesStartArray) {
239
+ if (eslintErrorLineNumber >= changedLinesStartArray[lineNumber] && eslintErrorLineNumber <= changedLinesEndArray[lineNumber]) {
240
+ eslintErrorsInChangedLines.push(eslintErrorsInFile[error]);
241
+ }
196
242
  }
197
243
  }
198
- }
199
- if (eslintErrorsInChangedLines.length > 0) {
200
- Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
201
- for (let eslintError of eslintErrorsInChangedLines) {
202
- Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
244
+ if (eslintErrorsInChangedLines.length > 0) {
245
+ isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(eslintErrorsInChangedLines);
246
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
247
+ for (let eslintError of eslintErrorsInChangedLines) {
248
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
249
+ }
250
+ if (shouldWarningsAbortCommit) {
251
+ hasEslintErrorsInChangedLines = true;
252
+ shouldAbortCommit = true;
253
+ } else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
254
+ hasEslintErrorsInChangedLines = false;
255
+ } else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
256
+ hasEslintErrorsInChangedLines = true;
257
+ shouldAbortCommit = true;
258
+ }
259
+ }
260
+ } else {
261
+ if (eslintErrorsInFile.length > 0) {
262
+ let startIndex = 1;
263
+ let endIndex = eslintErrorsInFile.length - 2;
264
+ let listOsEslintErrors = eslintErrorsInFile.slice(startIndex, endIndex);
265
+ isOnlyEslintWarningsPresentInFile = isOnlyWarningsPresentInFile(listOsEslintErrors);
266
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[1m${currentFileName}\x1b[0m`);
267
+ for (let eslintError of listOsEslintErrors) {
268
+ Logger.log(Logger.FAILURE_TYPE, `\x1b[37m${eslintError.trimEnd()}\x1b[0m`);
269
+ }
270
+ if (shouldWarningsAbortCommit) {
271
+ hasEslintErrorsInFiles = true;
272
+ shouldAbortCommit = true;
273
+ } else if (!shouldWarningsAbortCommit && isOnlyEslintWarningsPresentInFile) {
274
+ hasEslintErrorsInFiles = false;
275
+ } else if (!shouldWarningsAbortCommit && !isOnlyEslintWarningsPresentInFile) {
276
+ hasEslintErrorsInFiles = true;
277
+ shouldAbortCommit = true;
278
+ }
203
279
  }
204
- hasEslintErrorsInChangedLines = true;
205
280
  }
206
281
  }
207
282
  }
@@ -217,10 +292,10 @@ async function preCommitHook() {
217
292
  } catch {
218
293
  Logger.log(Logger.INFO_TYPE, 'Error executing pre commit hook');
219
294
  }
220
- if (hasEslintErrorsInChangedLines) {
221
- Logger.log(Logger.FAILURE_TYPE, `There are eslint errors present. So commit is aborted`);
295
+ if (shouldAbortCommit) {
296
+ Logger.log(Logger.FAILURE_TYPE, `There are eslint errors/warnings present. So commit is aborted.`);
222
297
  process.exit(1);
223
- } else if (!hasEslintErrorsInChangedLines && areFilesStaged) {
298
+ } else if (shouldAbortCommit === false && staged_files.length !== 0) {
224
299
  Logger.log(Logger.SUCCESS_TYPE, `Commit Successful`);
225
300
  process.exit(0);
226
301
  }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ const path = require("path");
4
+
5
+ /**
6
+ * Configuration object for linting and reporting.
7
+ * @property {string} ruleConfigurationPath - The path to the ESLint configuration file.
8
+ * @property {boolean} impactBased - Indicates if the linting is impact-based.
9
+ * @property {string} lintReportPath - The path to the lint report JSON file.
10
+ * @property {string} metricServerHost - The URL of the SonarQube server.
11
+ * @property {string} exemptionInstanceHost - This is Exemption running host URL
12
+ * @property {string} metric_token - The token for authentication with the SonarQube server.
13
+ * @property {string} gitEndPoint - API EndPoint for Git Actions
14
+ * @property {string} tsConfigurationPath - The path of the ts configuration Path
15
+ * @property {number} projectId - project id of repository
16
+ * @property {boolean} impactBasedPrecommit - Indicates if the linting is impact-based in pre commit
17
+ * @property {boolean} shouldWarningsAbortCommit - Indicates if eslint warnings should abort the commit
18
+ * @property {string} token - Encrypted Authentication Token
19
+ * @property {string} compareBranch - Branch to compare diff
20
+ */
21
+
22
+ module.exports = {
23
+ ruleConfigurationPath: path.resolve(process.cwd(), ".eslintrc.js"),
24
+ impactBased: true,
25
+ lintReportPath: path.resolve(process.cwd(), "lint-report", "lintReport.json"),
26
+ metricServerHost: "https://client-linters.zohodesk.csez.zohocorpin.com",
27
+ exemptionInstanceHost: "",
28
+ metric_token: "zxh_9737850jh2l53ml17223929ihii73072j54j2260",
29
+ branchDiffPath: path.resolve(process.cwd(), "diffBranch.json"),
30
+ gitEndPoint: "https://zgit.csez.zohocorpin.com",
31
+ tsConfigurationPath: path.resolve(process.cwd(), 'tsconfig.json'),
32
+ projectId: `project-id`,
33
+ impactBasedPrecommit: true,
34
+ shouldWarningsAbortCommit: false,
35
+ token: "w-OkG3f5OOM1Rkly8phZ",
36
+ compareBranch: 'release'
37
+ };
@@ -16,21 +16,41 @@ const {
16
16
  const {
17
17
  executeSynchronizedCommands
18
18
  } = require('../General/executeSyncCommands');
19
- const {
19
+ var {
20
20
  type,
21
21
  endPoint,
22
22
  branch,
23
23
  cacheDirectory,
24
- commonLinterRepoName
24
+ commonLinterRepoName,
25
+ user
25
26
  } = require('../../../jsonUtils/commonLinterRepoDetails');
27
+ const {
28
+ getConfigurationPrecommit,
29
+ getRunningEnv
30
+ } = require("../General/getGeneralInfo");
31
+ const {
32
+ decrypt
33
+ } = require("../General/Hash");
34
+ const {
35
+ Logger
36
+ } = require("../Logger/Logger");
26
37
  /**
27
38
  * @function cloneViaCdt - Using the "clint development tool" clones the common linter_configuration repo into precommit library
28
39
  * @returns {boolean} - indicating the success or failure of the cloning process
29
40
  */
30
41
 
31
42
  function cloneViaCdt() {
43
+ const {
44
+ token
45
+ } = getConfigurationPrecommit();
32
46
  removeFolder(getDeleteDirPath());
33
- const commandToCloneCommonConfigRepo = `npx cdt clone --clone:type=${type} --clone:url=${endPoint} --clone:branch=${branch} --clone:cacheDir=${cacheDirectory} --clone:proj:name=${commonLinterRepoName}`;
47
+ const userName = user;
48
+ var absoluteEndPoint = `https://${endPoint}`;
49
+ if (getRunningEnv() === "CI") {
50
+ Logger.log(Logger.INFO_TYPE, `Running in CI`);
51
+ absoluteEndPoint = `https://${userName}:${decrypt(token, 12)}@${endPoint}`;
52
+ }
53
+ var commandToCloneCommonConfigRepo = `npx cdt clone --clone:type=${type} --clone:url=${absoluteEndPoint} --clone:branch=${branch} --clone:cacheDir=${cacheDirectory} --clone:proj:name=${commonLinterRepoName}`;
34
54
  let isCommonConfigurationClonedSuccessfully = executeSynchronizedCommands(execSync, [commandToCloneCommonConfigRepo, {
35
55
  cwd: getClonedDirPath()
36
56
  }], `Lint Configuration Cloned Successfully - ${getRepoName() || 'common'}`, 'Could not clone the linters common repo', false, true);
@@ -36,6 +36,15 @@ function filterFiles(arrayOfFilesToBeFiltered, filesToBeRemoved, isConfigFileNee
36
36
  return arrayOfFilesToBeFiltered;
37
37
  }
38
38
  }
39
+
40
+ /**
41
+ * @function filterWarningInFile - filter warning in files
42
+ * @returns {Array<string>}
43
+ */
44
+ function filterWarningInFile(array) {
45
+ // handle error in file
46
+ }
39
47
  module.exports = {
40
- filterFiles
48
+ filterFiles,
49
+ filterWarningInFile
41
50
  };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.encrypt = exports.decrypt = void 0;
7
+ const caesarCipher = (str, shift) => {
8
+ return str.split("").map(char => {
9
+ let code = char.charCodeAt();
10
+ if (code >= 65 && code <= 90) {
11
+ return String.fromCharCode((code - 65 + shift) % 26 + 65);
12
+ } else if (code >= 97 && code <= 122) {
13
+ return String.fromCharCode((code - 97 + shift) % 26 + 97);
14
+ }
15
+ return char;
16
+ }).join("");
17
+ };
18
+ const encrypt = (plaintext, shift) => caesarCipher(plaintext, shift);
19
+ exports.encrypt = encrypt;
20
+ const decrypt = (ciphertext, shift) => caesarCipher(ciphertext, 26 - shift);
21
+ exports.decrypt = decrypt;
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
 
3
3
  const os = require('os');
4
+ const path = require('path');
5
+ const fs = require("fs");
6
+ const {
7
+ execSync
8
+ } = require('child_process');
4
9
 
5
10
  /**
6
11
  * @function getTimeStampInfo - to fetch various timestamp details
@@ -25,7 +30,47 @@ function getTimeStampInfo() {
25
30
  function getEnv() {
26
31
  return os.type();
27
32
  }
33
+
34
+ /**
35
+ * @function getConfigPath - get a path of lint configuration path
36
+ * @returns {string}
37
+ */
38
+ function getConfigPath() {
39
+ const configPath = path.resolve(process.cwd(), 'lint.config.js');
40
+ const defaultConfigPath = path.resolve(__dirname, '..', '..', 'setup', 'sample.config.js');
41
+ return fs.existsSync(configPath) ? configPath : defaultConfigPath;
42
+ }
43
+
44
+ /**
45
+ * @function getConfiguration - get configuration object of lint configuration
46
+ * @returns
47
+ */
48
+ function getConfigurationPrecommit() {
49
+ return require(getConfigPath());
50
+ }
51
+
52
+ /**
53
+ * @function getSupportedLanguage - get support language
54
+ * @returns {Array<string>}
55
+ */
56
+ function getSupportedLanguage() {
57
+ const _language = [];
58
+ _language.push('.js');
59
+ _language.push('.jsx');
60
+ _language.push('.ts');
61
+ _language.push('.tsx');
62
+ return _language;
63
+ }
64
+ function getRunningEnv() {
65
+ const command = "npm config get lint_env";
66
+ return execSync(command, {
67
+ shell: true
68
+ }).toString().trim();
69
+ }
28
70
  module.exports = {
71
+ getSupportedLanguage,
29
72
  getTimeStampInfo,
30
- getEnv
73
+ getEnv,
74
+ getConfigurationPrecommit,
75
+ getRunningEnv
31
76
  };
package/changeLog.md CHANGED
@@ -10,4 +10,13 @@
10
10
  1. Sets up a custom precommit hook using husky
11
11
  2. clones the common linter configuration repository in developer branch
12
12
  3. Based on the cloned configuration folder creates a eslint config file
13
- 4. Checks for eslint rule violations in the staged files(Impact based) and aborts/allows commit accordingly
13
+ 4. Checks for eslint rule violations in the staged files(Impact based) and aborts/allows commit accordingly
14
+
15
+ # 0.0.3 - minor issue fix
16
+
17
+ # 0.0.4 - configuration based Execution
18
+
19
+ 1. Avoid linting deleted files that have been staged.
20
+ 2. Added configuration for linting based on impacted lines or the entire file.
21
+ 3. Added configuration to abort commits if there are warnings or issues.
22
+ 4. Environment-specific clone configuration added.
@@ -9,9 +9,10 @@
9
9
  */
10
10
 
11
11
  module.exports = {
12
- endPoint: "https://zgit.csez.zohocorpin.com/code_standard/client_linter/linter_configuration.git",
12
+ endPoint: "zgit.csez.zohocorpin.com/code_standard/client_linter/linter_configuration.git",
13
13
  branch: "master",
14
14
  cacheDirectory: "./",
15
15
  commonLinterRepoName: "configuration",
16
- type: "git"
16
+ type: "git",
17
+ user:"rajasekar.hm"
17
18
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/codestandard-validator",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "library to enforce code standard using eslint",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,12 +16,12 @@
16
16
  "type": "commonjs",
17
17
  "dependencies": {
18
18
  "@zohodesk-private/client_deployment_tool": "0.0.5",
19
- "eslint": "^8.26.0"
19
+ "eslint": "8.26.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@babel/core": "^7.24.7",
23
- "@babel/plugin-transform-runtime": "^7.24.7",
24
- "@babel/preset-env": "^7.24.7",
25
- "husky": "^7.0.4"
22
+ "@babel/core": "7.24.7",
23
+ "@babel/plugin-transform-runtime": "7.24.7",
24
+ "@babel/preset-env": "7.24.7",
25
+ "husky": "7.0.4"
26
26
  }
27
27
  }