eslint-formatter-gitlab 2.2.0 → 3.0.0

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.
Files changed (4) hide show
  1. package/README.md +7 -1
  2. package/index.js +117 -27
  3. package/package.json +20 -19
  4. package/CHANGELOG.md +0 -56
package/README.md CHANGED
@@ -44,7 +44,13 @@ configuration, options are passed using environment variables.
44
44
  | Environment Variable | Description |
45
45
  | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
46
46
  | `ESLINT_CODE_QUALITY_REPORT` | The location to store the code quality report. By default it will detect the location of the codequality artifact defined in the GitLab CI configuration file. |
47
- | `ESLINT_FORMATTER` | The ESLint formatter to use for the console output. This defaults to stylish, the default ESLint formatter. |
47
+
48
+ ## Upgrading
49
+
50
+ ### to v3
51
+
52
+ - Support for the environment variable `ESLINT_FORMATTER` has been removed, console output now
53
+ always uses a builtin formatter.
48
54
 
49
55
  [gitlab code quality]: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html
50
56
  [merge request !1]: https://gitlab.com/remcohaszing/eslint-formatter-gitlab/merge_requests/1
package/index.js CHANGED
@@ -1,16 +1,21 @@
1
1
  const { createHash } = require('crypto');
2
2
  const { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } = require('fs');
3
+ const { EOL } = require('os');
3
4
  const { dirname, join, relative, resolve } = require('path');
4
5
 
5
- const { CLIEngine } = require('eslint');
6
+ // eslint-disable-next-line unicorn/import-style
7
+ const chalk = require('chalk');
6
8
  const yaml = require('js-yaml');
7
9
 
8
10
  const {
9
11
  CI_CONFIG_PATH = '.gitlab-ci.yml',
10
12
  CI_JOB_NAME,
11
13
  CI_PROJECT_DIR = process.cwd(),
14
+ CI_PROJECT_URL,
15
+ CI_COMMIT_SHORT_SHA,
12
16
  ESLINT_CODE_QUALITY_REPORT,
13
- ESLINT_FORMATTER,
17
+ GITLAB_CI,
18
+ NODE_ENV,
14
19
  } = process.env;
15
20
 
16
21
  /**
@@ -60,30 +65,118 @@ function createFingerprint(filePath, message) {
60
65
  * @returns {object[]} The ESLint messages in the form of a GitLab code quality report.
61
66
  */
62
67
  function convert(results) {
63
- return results.reduce(
64
- (acc, result) => [
65
- ...acc,
66
- ...result.messages.map((message) => {
67
- const relativePath = relative(CI_PROJECT_DIR, result.filePath);
68
- // https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types
69
- return {
70
- description: message.message,
71
- severity: message.severity === 2 ? 'major' : 'minor',
72
- fingerprint: createFingerprint(relativePath, message),
73
- location: {
74
- path: relativePath,
75
- lines: {
76
- begin: message.line,
77
- },
68
+ const messages = [];
69
+ for (const result of results) {
70
+ for (const message of result.messages) {
71
+ const relativePath = relative(CI_PROJECT_DIR, result.filePath);
72
+ // https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types
73
+ messages.push({
74
+ description: message.message,
75
+ severity: message.severity === 2 ? 'major' : 'minor',
76
+ fingerprint: createFingerprint(relativePath, message),
77
+ location: {
78
+ path: relativePath,
79
+ lines: {
80
+ begin: message.line,
78
81
  },
79
- };
80
- }),
81
- ],
82
- [],
83
- );
82
+ },
83
+ });
84
+ }
85
+ }
86
+ return messages;
87
+ }
88
+
89
+ /**
90
+ * @param {object} message - The ESLint report message.
91
+ * @returns {boolean} `true` if the message is at error level, `false` if it represents a warning
92
+ */
93
+ function messageIsLevelError(message) {
94
+ return message.fatal || message.severity === 2;
95
+ }
96
+
97
+ /**
98
+ * @param {object[]} results - The ESLint report results.
99
+ * @returns {object} Statistics about the number of problems at various levels
100
+ * and length of contained description strings.
101
+ */
102
+ function calculateResultsStats(results) {
103
+ const stats = { total: 0, errors: 0, warnings: 0, maxRuleIdLength: 0, maxMsgLength: 0 };
104
+
105
+ for (const result of results) {
106
+ for (const message of result.messages) {
107
+ const isError = messageIsLevelError(message);
108
+ stats.errors += isError ? 1 : 0;
109
+ stats.warnings += isError ? 0 : 1;
110
+ stats.maxRuleIdLength = message.ruleId
111
+ ? Math.max(stats.maxRuleIdLength, message.ruleId.length)
112
+ : stats.maxRuleIdLength;
113
+ stats.maxMsgLength = Math.max(stats.maxMsgLength, message.message.length);
114
+ }
115
+ }
116
+
117
+ stats.total = stats.warnings + stats.errors;
118
+
119
+ return stats;
120
+ }
121
+
122
+ const plural = (count, text) => `${count} ${text}${count === 1 ? '' : 's'}`;
123
+
124
+ /**
125
+ * @param {object[]} results - The ESLint report results.
126
+ * @returns {string} The ESLint messages converted to a format
127
+ * suitable as output in GitLab CI job logs.
128
+ */
129
+ function gitlabConsoleFormatter(results) {
130
+ // Severity labels manually padded to have equal lengths and end with spaces
131
+ const labelError = `${chalk.red('error')} `;
132
+ const labelWarn = `${chalk.yellow('warn')} `;
133
+
134
+ const lines = [''];
135
+
136
+ let gitLabBaseURL;
137
+ if (CI_PROJECT_URL && CI_COMMIT_SHORT_SHA) {
138
+ gitLabBaseURL = `${CI_PROJECT_URL}/-/blob/${CI_COMMIT_SHORT_SHA}/`;
139
+ }
140
+
141
+ const stats = calculateResultsStats(results);
142
+
143
+ for (const result of results) {
144
+ const { filePath, messages } = result;
145
+ const repoFilePath = relative(CI_PROJECT_DIR, filePath);
146
+
147
+ for (const message of messages) {
148
+ let line;
149
+ line = messageIsLevelError(message) ? labelError : labelWarn;
150
+ line += String(message.ruleId ? message.ruleId : '').padEnd(stats.maxRuleIdLength + 2);
151
+ line += message.message.padEnd(stats.maxMsgLength + 2);
152
+
153
+ if (gitLabBaseURL) {
154
+ // Create link to referenced file in GitLab
155
+ const anchor = message.line === undefined ? '' : `#L${message.line}`;
156
+ line += chalk.blue(`${gitLabBaseURL}${repoFilePath}${anchor}`);
157
+ } else {
158
+ line += `${filePath}:${message.line || 0}:${message.column || 0}`;
159
+ }
160
+
161
+ lines.push(line);
162
+ }
163
+ }
164
+
165
+ if (stats.total > 0) {
166
+ const details = `(${plural(stats.errors, 'error')}, ${plural(stats.warnings, 'warning')})`;
167
+ lines.push('', `${chalk.red('✖')} ${plural(stats.total, 'problem')} ${details}`);
168
+ } else {
169
+ lines.push(`${chalk.green('✔')} No problems found`);
170
+ }
171
+
172
+ lines.push('');
173
+ return lines.join(EOL);
84
174
  }
85
175
 
86
176
  module.exports = (results) => {
177
+ if (GITLAB_CI === 'true' && NODE_ENV !== 'test') {
178
+ chalk.level = 1;
179
+ }
87
180
  if (CI_JOB_NAME || ESLINT_CODE_QUALITY_REPORT) {
88
181
  const data = convert(results);
89
182
  const outputPath = ESLINT_CODE_QUALITY_REPORT || getOutputPath();
@@ -91,9 +184,6 @@ module.exports = (results) => {
91
184
  mkdirSync(dir, { recursive: true });
92
185
  writeFileSync(outputPath, JSON.stringify(data, null, 2));
93
186
  }
94
- let formatter = CLIEngine.getFormatter(ESLINT_FORMATTER);
95
- if (formatter === module.exports) {
96
- formatter = CLIEngine.getFormatter();
97
- }
98
- return formatter(results);
187
+
188
+ return gitlabConsoleFormatter(results);
99
189
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-formatter-gitlab",
3
- "version": "2.2.0",
3
+ "version": "3.0.0",
4
4
  "description": "Show ESLint results directly in the GitLab code quality results",
5
5
  "author": "Remco Haszing <remcohaszing@gmail.com>",
6
6
  "license": "MIT",
@@ -26,28 +26,29 @@
26
26
  "gitlab-ci"
27
27
  ],
28
28
  "dependencies": {
29
+ "chalk": "^4.0.0",
29
30
  "js-yaml": "^4.0.0"
30
31
  },
31
32
  "peerDependencies": {
32
- "eslint": "^5 || ^6 || ^7"
33
+ "eslint": "^5 || ^6 || ^7 || ^8"
33
34
  },
34
35
  "devDependencies": {
35
- "codecov": "^3.8.1",
36
- "eslint": "^7.18.0",
37
- "eslint-config-remcohaszing": "^3.1.0",
38
- "eslint-plugin-eslint-comments": "^3.2.0",
39
- "eslint-plugin-import": "^2.22.1",
40
- "eslint-plugin-jest": "^24.1.3",
41
- "eslint-plugin-jest-formatting": "^2.0.1",
42
- "eslint-plugin-jsdoc": "^31.4.0",
43
- "eslint-plugin-markdown": "^2.0.0-rc.1",
44
- "eslint-plugin-node": "^11.1.0",
45
- "eslint-plugin-prettier": "^3.3.1",
46
- "eslint-plugin-sort-destructure-keys": "^1.3.5",
47
- "eslint-plugin-unicorn": "^27.0.0",
48
- "jest": "^26.6.3",
49
- "jest-junit": "^12.0.0",
50
- "memfs": "^3.2.0",
51
- "prettier": "^2.2.1"
36
+ "codecov": "^3.0.0",
37
+ "eslint": "^7.0.0",
38
+ "eslint-config-remcohaszing": "^3.0.0",
39
+ "eslint-plugin-eslint-comments": "^3.0.0",
40
+ "eslint-plugin-import": "^2.0.0",
41
+ "eslint-plugin-jest": "^24.0.0",
42
+ "eslint-plugin-jest-formatting": "^3.0.0",
43
+ "eslint-plugin-jsdoc": "^36.0.0",
44
+ "eslint-plugin-markdown": "^2.0.0",
45
+ "eslint-plugin-node": "^11.0.0",
46
+ "eslint-plugin-prettier": "^4.0.0",
47
+ "eslint-plugin-sort-destructure-keys": "^1.0.0",
48
+ "eslint-plugin-unicorn": "^36.0.0",
49
+ "jest": "^27.0.0",
50
+ "jest-junit": "^13.0.0",
51
+ "memfs": "^3.0.0",
52
+ "prettier": "^2.0.0"
52
53
  }
53
54
  }
package/CHANGELOG.md DELETED
@@ -1,56 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
6
- adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ## [2.2.0] - 2021-01-27
11
-
12
- ### Changed
13
-
14
- - Updated `ja-yaml`.
15
-
16
- ## [2.2.0] - 2020-12-12
17
-
18
- ### Added
19
-
20
- - Added severity to output.
21
-
22
- ## [2.0.0] - 2020-04-14
23
-
24
- ### Changed
25
-
26
- - Support ESLint 7.
27
-
28
- ### Fixed
29
-
30
- - Fix infinite recursion when `ESLINT_CODE_QUALITY_REPORT` refers to `eslint-formatter-gitlab`
31
- itself.
32
-
33
- ## [1.1.0] - 2019-08-08
34
-
35
- ### Changed
36
-
37
- - Support ESLint 6.
38
-
39
- ## [1.0.2] - 2018-12-13
40
-
41
- ### Fixes
42
-
43
- - Fix automated release process.
44
-
45
- ## [1.0.1] - 2018-12-13
46
-
47
- ### Added
48
-
49
- - Tests.
50
- - Link to example merge request.
51
-
52
- ## [1.0.0] - 2018-11-29
53
-
54
- ### Added
55
-
56
- - Initial release.