eslint-formatter-gitlab 3.0.0 → 5.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.
- package/LICENSE.md +2 -2
- package/README.md +28 -21
- package/index.js +179 -110
- package/package.json +18 -27
package/LICENSE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Copyright © 2018 Remco Haszing
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
6
|
-
associated documentation files (the
|
|
6
|
+
associated documentation files (the “Software”), to deal in the Software without restriction,
|
|
7
7
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
8
8
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
9
9
|
furnished to do so, subject to the following conditions:
|
|
@@ -11,7 +11,7 @@ furnished to do so, subject to the following conditions:
|
|
|
11
11
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
12
12
|
portions of the Software.
|
|
13
13
|
|
|
14
|
-
THE SOFTWARE IS PROVIDED
|
|
14
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
15
15
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
16
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
|
17
17
|
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
package/README.md
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
# ESLint Formatter for GitLab
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Show ESLint results directly in the
|
|
4
|
+
[GitLab code quality](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html)
|
|
5
|
+
results.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Requirements](#requirements)
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Usage](#usage)
|
|
12
|
+
- [Example](#example)
|
|
13
|
+
- [Configuration](#configuration)
|
|
14
|
+
- [License](#license)
|
|
4
15
|
|
|
5
16
|
## Requirements
|
|
6
17
|
|
|
7
|
-
This requires at least
|
|
18
|
+
This package requires at least Node.js 18 and ESLint 5.
|
|
8
19
|
|
|
9
20
|
## Installation
|
|
10
21
|
|
|
@@ -14,13 +25,15 @@ Install `eslint` and `eslint-formatter-gitlab` using your package manager.
|
|
|
14
25
|
npm install --save-dev eslint eslint-formatter-gitlab
|
|
15
26
|
```
|
|
16
27
|
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
17
30
|
Define a GitLab job to run `eslint`.
|
|
18
31
|
|
|
19
32
|
_.gitlab-ci.yml_:
|
|
20
33
|
|
|
21
34
|
```yaml
|
|
22
35
|
eslint:
|
|
23
|
-
image: node:
|
|
36
|
+
image: node:20-alpine
|
|
24
37
|
script:
|
|
25
38
|
- npm ci
|
|
26
39
|
- npx eslint --format gitlab .
|
|
@@ -29,28 +42,22 @@ eslint:
|
|
|
29
42
|
codequality: gl-codequality.json
|
|
30
43
|
```
|
|
31
44
|
|
|
32
|
-
The formatter
|
|
33
|
-
|
|
45
|
+
The formatter automatically detects a GitLab CI environment. It detects where to output the code
|
|
46
|
+
quality report based on the GitLab configuration file.
|
|
34
47
|
|
|
35
48
|
## Example
|
|
36
49
|
|
|
37
|
-
An example of the results can be seen in
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
ESLint formatters don’t take any configuration options. In order to still allow some way of
|
|
42
|
-
configuration, options are passed using environment variables.
|
|
43
|
-
|
|
44
|
-
| Environment Variable | Description |
|
|
45
|
-
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
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. |
|
|
50
|
+
An example of the results can be seen in
|
|
51
|
+
[Merge Request !1](https://gitlab.com/remcohaszing/eslint-formatter-gitlab/merge_requests/1) of
|
|
52
|
+
`eslint-formatter-gitlab` itself.
|
|
47
53
|
|
|
48
|
-
##
|
|
54
|
+
## Configuration
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
ESLint formatters don’t take any configuration options. `eslint-formatter-gitlab` uses GitLab’s
|
|
57
|
+
[predefined environment variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
|
|
58
|
+
to configure the output. In addition, the environment variable `ESLINT_CODE_QUALITY_REPORT` is used
|
|
59
|
+
to override the location to store the code quality report.
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
always uses a builtin formatter.
|
|
61
|
+
## License
|
|
54
62
|
|
|
55
|
-
[
|
|
56
|
-
[merge request !1]: https://gitlab.com/remcohaszing/eslint-formatter-gitlab/merge_requests/1
|
|
63
|
+
[MIT](LICENSE.md) © [Remco Haszing](https://gitlab.com/remcohaszing)
|
package/index.js
CHANGED
|
@@ -1,189 +1,258 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('eslint').ESLint.LintResult} LintResult
|
|
3
|
+
* @typedef {import('eslint').ESLint.LintResultData} LintResultData
|
|
4
|
+
* @typedef {import('eslint').Linter.LintMessage} LintMessage
|
|
5
|
+
* @typedef {import('codeclimate-types').Issue} Issue
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { createHash } = require('node:crypto')
|
|
9
|
+
const { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } = require('node:fs')
|
|
10
|
+
const { EOL } = require('node:os')
|
|
11
|
+
const { dirname, join, relative, resolve } = require('node:path')
|
|
5
12
|
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const yaml = require('js-yaml');
|
|
13
|
+
const chalk = require('chalk')
|
|
14
|
+
const yaml = require('yaml')
|
|
9
15
|
|
|
10
16
|
const {
|
|
17
|
+
CI_COMMIT_SHORT_SHA,
|
|
11
18
|
CI_CONFIG_PATH = '.gitlab-ci.yml',
|
|
12
19
|
CI_JOB_NAME,
|
|
13
20
|
CI_PROJECT_DIR = process.cwd(),
|
|
14
21
|
CI_PROJECT_URL,
|
|
15
|
-
CI_COMMIT_SHORT_SHA,
|
|
16
22
|
ESLINT_CODE_QUALITY_REPORT,
|
|
17
|
-
GITLAB_CI
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
GITLAB_CI
|
|
24
|
+
} = process.env
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @type {yaml.CollectionTag}
|
|
28
|
+
*/
|
|
29
|
+
const reference = {
|
|
30
|
+
tag: '!reference',
|
|
31
|
+
collection: 'seq',
|
|
32
|
+
default: false,
|
|
33
|
+
resolve() {
|
|
34
|
+
// We only allow the syntax. We don’t actually resolve the reference.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
20
37
|
|
|
21
38
|
/**
|
|
22
39
|
* @returns {string} The output path of the code quality artifact.
|
|
23
40
|
*/
|
|
24
41
|
function getOutputPath() {
|
|
25
|
-
const configPath = join(CI_PROJECT_DIR, CI_CONFIG_PATH)
|
|
42
|
+
const configPath = join(CI_PROJECT_DIR, CI_CONFIG_PATH)
|
|
26
43
|
// GitlabCI allows a custom configuration path which can be a URL or a path relative to another
|
|
27
44
|
// project. In these cases CI_CONFIG_PATH is empty and we'll have to require the user provide
|
|
28
45
|
// ESLINT_CODE_QUALITY_REPORT.
|
|
29
46
|
if (!existsSync(configPath) || !lstatSync(configPath).isFile()) {
|
|
30
47
|
throw new Error(
|
|
31
48
|
'Could not resolve .gitlab-ci.yml to automatically detect report artifact path.' +
|
|
32
|
-
' Please manually provide a path via the ESLINT_CODE_QUALITY_REPORT variable.'
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
const jobs = yaml.load(readFileSync(configPath, 'utf-8'));
|
|
36
|
-
const { artifacts } = jobs[CI_JOB_NAME];
|
|
37
|
-
const location = artifacts && artifacts.reports && artifacts.reports.codequality;
|
|
38
|
-
const msg = `Expected ${CI_JOB_NAME}.artifacts.reports.codequality to be one exact path`;
|
|
39
|
-
if (!location) {
|
|
40
|
-
throw new Error(`${msg}, but no value was found.`);
|
|
49
|
+
' Please manually provide a path via the ESLINT_CODE_QUALITY_REPORT variable.'
|
|
50
|
+
)
|
|
41
51
|
}
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
const doc = yaml.parseDocument(readFileSync(configPath, 'utf8'), {
|
|
53
|
+
version: '1.1',
|
|
54
|
+
customTags: [reference]
|
|
55
|
+
})
|
|
56
|
+
const path = [CI_JOB_NAME, 'artifacts', 'reports', 'codequality']
|
|
57
|
+
const location = doc.getIn(path)
|
|
58
|
+
if (typeof location !== 'string' || !location) {
|
|
59
|
+
throw new TypeError(
|
|
60
|
+
`Expected ${path.join('.')} to be one exact path, got: ${JSON.stringify(location)}`
|
|
61
|
+
)
|
|
44
62
|
}
|
|
45
|
-
return resolve(CI_PROJECT_DIR, location)
|
|
63
|
+
return resolve(CI_PROJECT_DIR, location)
|
|
46
64
|
}
|
|
47
65
|
|
|
48
66
|
/**
|
|
49
|
-
* @param {string} filePath
|
|
50
|
-
* @param {
|
|
67
|
+
* @param {string} filePath The path to the linted file.
|
|
68
|
+
* @param {LintMessage} message The ESLint report message.
|
|
69
|
+
* @param {Set<string>} hashes Hashes already encountered. Used to avoid duplicate hashes
|
|
51
70
|
* @returns {string} The fingerprint for the ESLint report message.
|
|
52
71
|
*/
|
|
53
|
-
function createFingerprint(filePath, message) {
|
|
54
|
-
const md5 = createHash('md5')
|
|
55
|
-
md5.update(filePath)
|
|
72
|
+
function createFingerprint(filePath, message, hashes) {
|
|
73
|
+
const md5 = createHash('md5')
|
|
74
|
+
md5.update(filePath)
|
|
56
75
|
if (message.ruleId) {
|
|
57
|
-
md5.update(message.ruleId)
|
|
76
|
+
md5.update(message.ruleId)
|
|
58
77
|
}
|
|
59
|
-
md5.update(message.message)
|
|
60
|
-
|
|
78
|
+
md5.update(message.message)
|
|
79
|
+
|
|
80
|
+
// Create copy of hash since md5.digest() will finalize it, not allowing us to .update() again
|
|
81
|
+
let md5Tmp = md5.copy()
|
|
82
|
+
let hash = md5Tmp.digest('hex')
|
|
83
|
+
|
|
84
|
+
while (hashes.has(hash)) {
|
|
85
|
+
// Hash collision. This happens if we encounter the same ESLint message in one file
|
|
86
|
+
// multiple times. Keep generating new hashes until we get a unique one.
|
|
87
|
+
md5.update(hash)
|
|
88
|
+
|
|
89
|
+
md5Tmp = md5.copy()
|
|
90
|
+
hash = md5Tmp.digest('hex')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
hashes.add(hash)
|
|
94
|
+
return hash
|
|
61
95
|
}
|
|
62
96
|
|
|
63
97
|
/**
|
|
64
|
-
* @param {
|
|
65
|
-
* @
|
|
98
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
99
|
+
* @param {LintResultData} data The ESLint report result data.
|
|
100
|
+
* @returns {Issue[]} The ESLint messages in the form of a GitLab code quality report.
|
|
66
101
|
*/
|
|
67
|
-
function convert(results) {
|
|
68
|
-
|
|
102
|
+
function convert(results, data) {
|
|
103
|
+
/** @type {Issue[]} */
|
|
104
|
+
const messages = []
|
|
105
|
+
|
|
106
|
+
/** @type {Set<string>} */
|
|
107
|
+
const hashes = new Set()
|
|
108
|
+
|
|
69
109
|
for (const result of results) {
|
|
110
|
+
const relativePath = relative(CI_PROJECT_DIR, result.filePath)
|
|
111
|
+
|
|
70
112
|
for (const message of result.messages) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
113
|
+
/** @type {Issue} */
|
|
114
|
+
const issue = {
|
|
115
|
+
type: 'issue',
|
|
116
|
+
categories: ['Style'],
|
|
117
|
+
check_name: message.ruleId ?? '',
|
|
74
118
|
description: message.message,
|
|
75
|
-
severity: message.severity === 2 ? 'major' : 'minor',
|
|
76
|
-
fingerprint: createFingerprint(relativePath, message),
|
|
119
|
+
severity: message.fatal ? 'critical' : message.severity === 2 ? 'major' : 'minor',
|
|
120
|
+
fingerprint: createFingerprint(relativePath, message, hashes),
|
|
77
121
|
location: {
|
|
78
122
|
path: relativePath,
|
|
79
123
|
lines: {
|
|
80
124
|
begin: message.line,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
125
|
+
end: message.endLine ?? message.line
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (message.ruleId && message.ruleId in data.rulesMeta) {
|
|
130
|
+
const { docs, type } = data.rulesMeta[message.ruleId]
|
|
131
|
+
if (type === 'problem') {
|
|
132
|
+
issue.categories.unshift('Bug Risk')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (docs) {
|
|
136
|
+
let body = docs.description || ''
|
|
137
|
+
if (docs.url) {
|
|
138
|
+
if (body) {
|
|
139
|
+
body += '\n\n'
|
|
140
|
+
}
|
|
141
|
+
body += `[${message.ruleId}](${docs.url})`
|
|
142
|
+
}
|
|
143
|
+
if (body) {
|
|
144
|
+
issue.content = { body }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
messages.push(issue)
|
|
84
149
|
}
|
|
85
150
|
}
|
|
86
|
-
return messages
|
|
151
|
+
return messages
|
|
87
152
|
}
|
|
88
153
|
|
|
89
154
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
155
|
+
* Make a text singular or plural based on the count.
|
|
156
|
+
*
|
|
157
|
+
* @param {number} count The count of the data.
|
|
158
|
+
* @param {string} text The text to make singular or plural.
|
|
159
|
+
* @returns {string} The formatted text.
|
|
92
160
|
*/
|
|
93
|
-
function
|
|
94
|
-
return
|
|
161
|
+
function plural(count, text) {
|
|
162
|
+
return `${count} ${text}${count === 1 ? '' : 's'}`
|
|
95
163
|
}
|
|
96
164
|
|
|
97
165
|
/**
|
|
98
|
-
* @param {
|
|
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.
|
|
166
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
126
167
|
* @returns {string} The ESLint messages converted to a format
|
|
127
|
-
*
|
|
168
|
+
* suitable as output in GitLab CI job logs.
|
|
128
169
|
*/
|
|
129
170
|
function gitlabConsoleFormatter(results) {
|
|
130
171
|
// Severity labels manually padded to have equal lengths and end with spaces
|
|
131
|
-
const
|
|
132
|
-
const
|
|
172
|
+
const labelFatal = `${chalk.magenta('fatal')} `
|
|
173
|
+
const labelError = `${chalk.red('error')} `
|
|
174
|
+
const labelWarn = `${chalk.yellow('warn')} `
|
|
133
175
|
|
|
134
|
-
const lines = ['']
|
|
176
|
+
const lines = ['']
|
|
135
177
|
|
|
136
|
-
|
|
178
|
+
/** @type {string | undefined} */
|
|
179
|
+
let gitLabBaseURL
|
|
137
180
|
if (CI_PROJECT_URL && CI_COMMIT_SHORT_SHA) {
|
|
138
|
-
gitLabBaseURL = `${CI_PROJECT_URL}/-/blob/${CI_COMMIT_SHORT_SHA}
|
|
181
|
+
gitLabBaseURL = `${CI_PROJECT_URL}/-/blob/${CI_COMMIT_SHORT_SHA}/`
|
|
139
182
|
}
|
|
140
183
|
|
|
141
|
-
|
|
184
|
+
let fatal = 0
|
|
185
|
+
let errors = 0
|
|
186
|
+
let warnings = 0
|
|
187
|
+
let maxRuleIdLength = 0
|
|
188
|
+
let maxMsgLength = 0
|
|
142
189
|
|
|
143
190
|
for (const result of results) {
|
|
144
|
-
|
|
145
|
-
|
|
191
|
+
fatal += result.fatalErrorCount
|
|
192
|
+
errors += result.errorCount - result.fatalErrorCount
|
|
193
|
+
warnings += result.warningCount
|
|
194
|
+
for (const message of result.messages) {
|
|
195
|
+
if (message.ruleId) {
|
|
196
|
+
maxRuleIdLength = Math.max(maxRuleIdLength, message.ruleId.length)
|
|
197
|
+
}
|
|
198
|
+
maxMsgLength = Math.max(maxMsgLength, message.message.length)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
for (const result of results) {
|
|
203
|
+
const { filePath, messages } = result
|
|
204
|
+
const repoFilePath = relative(CI_PROJECT_DIR, filePath)
|
|
146
205
|
|
|
147
206
|
for (const message of messages) {
|
|
148
|
-
let line
|
|
149
|
-
line
|
|
150
|
-
line +=
|
|
151
|
-
line += message.message.padEnd(stats.maxMsgLength + 2);
|
|
207
|
+
let line = message.fatal ? labelFatal : message.severity === 1 ? labelWarn : labelError
|
|
208
|
+
line += String(message.ruleId || '').padEnd(maxRuleIdLength + 2)
|
|
209
|
+
line += message.message.padEnd(maxMsgLength + 2)
|
|
152
210
|
|
|
153
211
|
if (gitLabBaseURL) {
|
|
154
212
|
// Create link to referenced file in GitLab
|
|
155
|
-
|
|
156
|
-
|
|
213
|
+
let anchor = `#L${message.line}`
|
|
214
|
+
if (message.endLine != null && message.endLine !== message.line) {
|
|
215
|
+
anchor += `-${message.endLine}`
|
|
216
|
+
}
|
|
217
|
+
line += chalk.blue(`${gitLabBaseURL}${repoFilePath}${anchor}`)
|
|
157
218
|
} else {
|
|
158
|
-
line += `${filePath}:${message.line
|
|
219
|
+
line += `${filePath}:${message.line}:${message.column}`
|
|
159
220
|
}
|
|
160
221
|
|
|
161
|
-
lines.push(line)
|
|
222
|
+
lines.push(line)
|
|
162
223
|
}
|
|
163
224
|
}
|
|
164
225
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
226
|
+
const total = warnings + errors + fatal
|
|
227
|
+
if (total > 0) {
|
|
228
|
+
const details = `(${fatal} fatal, ${plural(errors, 'error')}, ${plural(warnings, 'warning')})`
|
|
229
|
+
lines.push('', `${chalk.red('✖')} ${plural(total, 'problem')} ${details}`)
|
|
168
230
|
} else {
|
|
169
|
-
lines.push(`${chalk.green('✔')} No problems found`)
|
|
231
|
+
lines.push(`${chalk.green('✔')} No problems found`)
|
|
170
232
|
}
|
|
171
233
|
|
|
172
|
-
lines.push('')
|
|
173
|
-
return lines.join(EOL)
|
|
234
|
+
lines.push('')
|
|
235
|
+
return lines.join(EOL)
|
|
174
236
|
}
|
|
175
237
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
238
|
+
/**
|
|
239
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
240
|
+
* @param {LintResultData} data The ESLint report result data.
|
|
241
|
+
*/
|
|
242
|
+
module.exports = (results, data) => {
|
|
243
|
+
/* c8 ignore start */
|
|
244
|
+
if (GITLAB_CI === 'true') {
|
|
245
|
+
chalk.level = 1
|
|
179
246
|
}
|
|
247
|
+
|
|
248
|
+
/* c8 ignore stop */
|
|
180
249
|
if (CI_JOB_NAME || ESLINT_CODE_QUALITY_REPORT) {
|
|
181
|
-
const
|
|
182
|
-
const outputPath = ESLINT_CODE_QUALITY_REPORT || getOutputPath()
|
|
183
|
-
const dir = dirname(outputPath)
|
|
184
|
-
mkdirSync(dir, { recursive: true })
|
|
185
|
-
writeFileSync(outputPath, JSON.stringify(
|
|
250
|
+
const issues = convert(results, data)
|
|
251
|
+
const outputPath = ESLINT_CODE_QUALITY_REPORT || getOutputPath()
|
|
252
|
+
const dir = dirname(outputPath)
|
|
253
|
+
mkdirSync(dir, { recursive: true })
|
|
254
|
+
writeFileSync(outputPath, JSON.stringify(issues, null, 2))
|
|
186
255
|
}
|
|
187
256
|
|
|
188
|
-
return gitlabConsoleFormatter(results)
|
|
189
|
-
}
|
|
257
|
+
return gitlabConsoleFormatter(results)
|
|
258
|
+
}
|
package/package.json
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-formatter-gitlab",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.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",
|
|
7
7
|
"homepage": "https://gitlab.com/remcohaszing/eslint-formatter-gitlab#readme",
|
|
8
|
-
"repository":
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://gitlab.com/remcohaszing/eslint-formatter-gitlab.git/issues"
|
|
14
|
-
},
|
|
8
|
+
"repository": "gitlab:remcohaszing/eslint-formatter-gitlab",
|
|
9
|
+
"funding": "https://github.com/sponsors/remcohaszing",
|
|
10
|
+
"bugs": "https://gitlab.com/remcohaszing/eslint-formatter-gitlab/-/issues",
|
|
11
|
+
"exports": "./index.js",
|
|
15
12
|
"files": [
|
|
16
13
|
"index.js"
|
|
17
14
|
],
|
|
18
15
|
"scripts": {
|
|
19
|
-
"test": "
|
|
16
|
+
"test": "c8 node --test --test-reporter @reporters/junit --test-reporter-destination=junit.xml --test-reporter spec --test-reporter-destination stdout"
|
|
20
17
|
},
|
|
21
18
|
"keywords": [
|
|
22
19
|
"eslint",
|
|
@@ -27,28 +24,22 @@
|
|
|
27
24
|
],
|
|
28
25
|
"dependencies": {
|
|
29
26
|
"chalk": "^4.0.0",
|
|
30
|
-
"
|
|
27
|
+
"yaml": "^2.0.0"
|
|
31
28
|
},
|
|
32
29
|
"peerDependencies": {
|
|
33
30
|
"eslint": "^5 || ^6 || ^7 || ^8"
|
|
34
31
|
},
|
|
35
32
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"eslint": "^
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"eslint
|
|
42
|
-
"eslint-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
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"
|
|
33
|
+
"@reporters/junit": "^1.0.0",
|
|
34
|
+
"@types/eslint": "^8.0.0",
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"c8": "^8.0.0",
|
|
37
|
+
"codeclimate-types": "^0.3.0",
|
|
38
|
+
"eslint": "^8.0.0",
|
|
39
|
+
"eslint-config-remcohaszing": "^9.0.0",
|
|
40
|
+
"prettier": "^2.0.0",
|
|
41
|
+
"remark-cli": "^11.0.0",
|
|
42
|
+
"remark-preset-remcohaszing": "^1.0.0",
|
|
43
|
+
"typescript": "^5.0.0"
|
|
53
44
|
}
|
|
54
45
|
}
|