eslint-formatter-gitlab 6.0.0 → 7.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/README.md CHANGED
@@ -37,10 +37,10 @@ Define a GitLab job to run `eslint`.
37
37
 
38
38
  ```yaml
39
39
  eslint:
40
- image: node:20-alpine
40
+ image: node:22-alpine
41
41
  script:
42
42
  - npm ci
43
- - npx eslint --format gitlab .
43
+ - npx eslint --format gitlab
44
44
  artifacts:
45
45
  reports:
46
46
  codequality: gl-codequality.json
@@ -1,13 +1,12 @@
1
1
  /**
2
- * @import { Issue } from 'codeclimate-types'
3
- * @import { ESLint, Linter } from 'eslint'
2
+ * @import { ESLint } from 'eslint'
4
3
  */
5
4
 
6
- import { createHash } from 'node:crypto'
7
5
  import { mkdir, readFile, writeFile } from 'node:fs/promises'
8
6
  import { dirname, join, relative, resolve } from 'node:path'
9
7
  import { styleText } from 'node:util'
10
8
 
9
+ import { toCodeClimate } from 'eslint-formatter-codeclimate'
11
10
  import yaml from 'yaml'
12
11
 
13
12
  /** @type {yaml.CollectionTag} */
@@ -56,113 +55,6 @@ async function getOutputPath(projectDir, jobName) {
56
55
  return resolve(projectDir, location)
57
56
  }
58
57
 
59
- /**
60
- * @param {string} filePath
61
- * The path to the linted file.
62
- * @param {Linter.LintMessage} message
63
- * The ESLint report message.
64
- * @param {Set<string>} hashes
65
- * Hashes already encountered. Used to avoid duplicate hashes
66
- * @returns {string}
67
- * The fingerprint for the ESLint report message.
68
- */
69
- function createFingerprint(filePath, message, hashes) {
70
- const md5 = createHash('md5')
71
- md5.update(filePath)
72
- if (message.ruleId) {
73
- md5.update(message.ruleId)
74
- }
75
- md5.update(message.message)
76
-
77
- // Create copy of hash since md5.digest() will finalize it, not allowing us to .update() again
78
- let md5Tmp = md5.copy()
79
- let hash = md5Tmp.digest('hex')
80
-
81
- while (hashes.has(hash)) {
82
- // Hash collision. This happens if we encounter the same ESLint message in one file
83
- // multiple times. Keep generating new hashes until we get a unique one.
84
- md5.update(hash)
85
-
86
- md5Tmp = md5.copy()
87
- hash = md5Tmp.digest('hex')
88
- }
89
-
90
- hashes.add(hash)
91
- return hash
92
- }
93
-
94
- /**
95
- * @param {ESLint.LintResult[]} results
96
- * The ESLint report results.
97
- * @param {ESLint.LintResultData} data
98
- * The ESLint report result data.
99
- * @param {string} projectDir
100
- * The GitLab project directory.
101
- * @returns {Issue[]}
102
- * The ESLint messages in the form of a GitLab code quality report.
103
- */
104
- function convert(results, data, projectDir) {
105
- /** @type {Issue[]} */
106
- const messages = []
107
-
108
- /** @type {Set<string>} */
109
- const hashes = new Set()
110
-
111
- for (const result of results) {
112
- const relativePath = relative(projectDir, result.filePath)
113
-
114
- for (const message of result.messages) {
115
- /** @type {Issue} */
116
- const issue = {
117
- type: 'issue',
118
- categories: ['Style'],
119
- check_name: message.ruleId ?? '',
120
- description: message.message,
121
- severity: message.fatal ? 'critical' : message.severity === 2 ? 'major' : 'minor',
122
- fingerprint: createFingerprint(relativePath, message, hashes),
123
- location: {
124
- path: relativePath,
125
- lines: {
126
- begin: message.line,
127
- end: message.endLine ?? message.line
128
- }
129
- }
130
- }
131
- messages.push(issue)
132
-
133
- if (!message.ruleId) {
134
- continue
135
- }
136
-
137
- if (!data.rulesMeta[message.ruleId]) {
138
- continue
139
- }
140
-
141
- const { docs, type } = data.rulesMeta[message.ruleId]
142
- if (type === 'problem') {
143
- issue.categories.unshift('Bug Risk')
144
- }
145
-
146
- if (!docs) {
147
- continue
148
- }
149
-
150
- let body = docs.description || ''
151
- if (docs.url) {
152
- if (body) {
153
- body += '\n\n'
154
- }
155
- body += `[${message.ruleId}](${docs.url})`
156
- }
157
-
158
- if (body) {
159
- issue.content = { body }
160
- }
161
- }
162
- }
163
- return messages
164
- }
165
-
166
58
  /**
167
59
  * Make a text singular or plural based on the count.
168
60
  *
@@ -268,7 +160,7 @@ async function eslintFormatterGitLab(results, data) {
268
160
  const projectDir = process.env.CI_PROJECT_DIR ?? data.cwd
269
161
  const jobName = process.env.CI_JOB_NAME
270
162
  if (jobName || outputPath) {
271
- const issues = convert(results, data, projectDir)
163
+ const issues = toCodeClimate(results, data.rulesMeta, projectDir)
272
164
  outputPath ||= await getOutputPath(projectDir, jobName)
273
165
  const dir = dirname(outputPath)
274
166
  await mkdir(dir, { recursive: true })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-formatter-gitlab",
3
- "version": "6.0.0",
3
+ "version": "7.0.0",
4
4
  "description": "Show ESLint results directly in the GitLab code quality results",
5
5
  "type": "module",
6
6
  "author": "Remco Haszing <remcohaszing@gmail.com>",
@@ -31,14 +31,15 @@
31
31
  "gitlab-ci"
32
32
  ],
33
33
  "dependencies": {
34
+ "eslint-formatter-codeclimate": "^2.0.0",
34
35
  "yaml": "^2.0.0"
35
36
  },
36
37
  "peerDependencies": {
37
38
  "eslint": ">=9"
38
39
  },
39
40
  "devDependencies": {
40
- "@remcohaszing/eslint": "^11.0.0",
41
- "@types/node": "^22.0.0",
41
+ "@remcohaszing/eslint": "^12.0.0",
42
+ "@types/node": "^24.0.0",
42
43
  "c8": "^10.0.0",
43
44
  "codeclimate-types": "^0.3.0",
44
45
  "prettier": "^3.0.0",
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-formatter-gitlab.d.ts","sourceRoot":"","sources":["../lib/eslint-formatter-gitlab.js"],"names":[],"mappings":";AAiQA;;;;;;;GAOG;AACH,gDAPW,iBAAiB,EAAE,QAEnB,qBAAqB,GAEnB,OAAO,CAAC,MAAM,CAAC,CAgB3B;4BApRkC,QAAQ"}
1
+ {"version":3,"file":"eslint-formatter-gitlab.d.ts","sourceRoot":"","sources":["../lib/eslint-formatter-gitlab.js"],"names":[],"mappings":";AAqJA;;;;;;;GAOG;AACH,gDAPW,iBAAiB,EAAE,QAEnB,qBAAqB,GAEnB,OAAO,CAAC,MAAM,CAAC,CAgB3B;4BAzK0B,QAAQ"}