eslint-formatter-gitlab 2.2.0 → 4.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 +15 -12
- package/index.js +227 -43
- package/package.json +22 -21
- package/CHANGELOG.md +0 -56
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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
|
|
4
6
|
|
|
5
7
|
## Requirements
|
|
6
8
|
|
|
7
|
-
This requires at least
|
|
9
|
+
This package requires at least Node.js 14 and ESLint 5.
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -14,13 +16,15 @@ Install `eslint` and `eslint-formatter-gitlab` using your package manager.
|
|
|
14
16
|
npm install --save-dev eslint eslint-formatter-gitlab
|
|
15
17
|
```
|
|
16
18
|
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
17
21
|
Define a GitLab job to run `eslint`.
|
|
18
22
|
|
|
19
23
|
_.gitlab-ci.yml_:
|
|
20
24
|
|
|
21
25
|
```yaml
|
|
22
26
|
eslint:
|
|
23
|
-
image: node:
|
|
27
|
+
image: node:18-alpine
|
|
24
28
|
script:
|
|
25
29
|
- npm ci
|
|
26
30
|
- npx eslint --format gitlab .
|
|
@@ -34,17 +38,16 @@ code quality report based on the GitLab configuration file.
|
|
|
34
38
|
|
|
35
39
|
## Example
|
|
36
40
|
|
|
37
|
-
An example of the results can be seen in
|
|
41
|
+
An example of the results can be seen in
|
|
42
|
+
[Merge Request !1](https://gitlab.com/remcohaszing/eslint-formatter-gitlab/merge_requests/1) of
|
|
43
|
+
`eslint-formatter-gitlab` itself.
|
|
38
44
|
|
|
39
45
|
## Configuration Options
|
|
40
46
|
|
|
41
|
-
ESLint formatters don’t take any configuration options.
|
|
42
|
-
|
|
47
|
+
ESLint formatters don’t take any configuration options. `eslint-formatter-gitlab` uses GitLab
|
|
48
|
+
environment variables to configure the output. In addition, the environment variable
|
|
49
|
+
`ESLINT_CODE_QUALITY_REPORT` is used to override the location to store the code quality report.
|
|
43
50
|
|
|
44
|
-
|
|
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. |
|
|
47
|
-
| `ESLINT_FORMATTER` | The ESLint formatter to use for the console output. This defaults to stylish, the default ESLint formatter. |
|
|
51
|
+
# License
|
|
48
52
|
|
|
49
|
-
[
|
|
50
|
-
[merge request !1]: https://gitlab.com/remcohaszing/eslint-formatter-gitlab/merge_requests/1
|
|
53
|
+
[MIT](LICENSE.md) @ [Remco Haszing](https://gitlab.com/remcohaszing)
|
package/index.js
CHANGED
|
@@ -1,18 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('eslint').ESLint.LintResult} LintResult
|
|
3
|
+
* @typedef {import('eslint').ESLint.LintResultData} LintResultData
|
|
4
|
+
* @typedef {import('eslint').Linter.LintMessage} LintMessage
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {object} GitLabReports
|
|
9
|
+
* @property {string} [codequality]
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} GitLabArtifacts
|
|
14
|
+
* @property {GitLabReports} [reports]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {object} GitLabJob
|
|
19
|
+
* @property {GitLabArtifacts} [artifacts]
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {Record<string, GitLabJob>} GitLabCI
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {object} CodeClimateLines
|
|
28
|
+
* @property {number} begin
|
|
29
|
+
* @property {number} end
|
|
30
|
+
*/
|
|
4
31
|
|
|
5
|
-
|
|
6
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {object} CodeClimateContents
|
|
34
|
+
* @property {string} body
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {object} CodeClimateLocation
|
|
39
|
+
* https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#locations
|
|
40
|
+
* @property {string} path
|
|
41
|
+
* @property {CodeClimateLines} lines
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {object} CodeClimateIssue
|
|
46
|
+
* https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#issues
|
|
47
|
+
* @property {'issue'} type
|
|
48
|
+
* @property {string} check_name
|
|
49
|
+
* @property {string} description
|
|
50
|
+
* @property {CodeClimateContents} [contents]
|
|
51
|
+
* @property {'info' | 'minor' | 'major' | 'critical' | 'blocker'} severity
|
|
52
|
+
* @property {string} [fingerprint]
|
|
53
|
+
* @property {CodeClimateLocation} location
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
const { createHash } = require('node:crypto');
|
|
57
|
+
const { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } = require('node:fs');
|
|
58
|
+
const { EOL } = require('node:os');
|
|
59
|
+
const { dirname, join, relative, resolve } = require('node:path');
|
|
60
|
+
|
|
61
|
+
const chalk = require('chalk');
|
|
62
|
+
const yaml = require('yaml');
|
|
7
63
|
|
|
8
64
|
const {
|
|
9
65
|
CI_CONFIG_PATH = '.gitlab-ci.yml',
|
|
10
66
|
CI_JOB_NAME,
|
|
11
67
|
CI_PROJECT_DIR = process.cwd(),
|
|
68
|
+
CI_PROJECT_URL,
|
|
69
|
+
CI_COMMIT_SHORT_SHA,
|
|
12
70
|
ESLINT_CODE_QUALITY_REPORT,
|
|
13
|
-
|
|
71
|
+
GITLAB_CI,
|
|
72
|
+
NODE_ENV,
|
|
14
73
|
} = process.env;
|
|
15
74
|
|
|
75
|
+
/**
|
|
76
|
+
* @type {yaml.CollectionTag}
|
|
77
|
+
*/
|
|
78
|
+
const reference = {
|
|
79
|
+
tag: '!reference',
|
|
80
|
+
collection: 'seq',
|
|
81
|
+
default: false,
|
|
82
|
+
resolve() {
|
|
83
|
+
// We only allow the syntax. We don’t actually resolve the reference.
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
16
87
|
/**
|
|
17
88
|
* @returns {string} The output path of the code quality artifact.
|
|
18
89
|
*/
|
|
@@ -27,9 +98,11 @@ function getOutputPath() {
|
|
|
27
98
|
' Please manually provide a path via the ESLINT_CODE_QUALITY_REPORT variable.',
|
|
28
99
|
);
|
|
29
100
|
}
|
|
30
|
-
const jobs =
|
|
31
|
-
|
|
32
|
-
|
|
101
|
+
const jobs = /** @type {GitLabCI} */ (
|
|
102
|
+
yaml.parse(readFileSync(configPath, 'utf8'), { version: '1.1', customTags: [reference] })
|
|
103
|
+
);
|
|
104
|
+
const { artifacts } = jobs[/** @type {string} */ (CI_JOB_NAME)];
|
|
105
|
+
const location = artifacts?.reports?.codequality;
|
|
33
106
|
const msg = `Expected ${CI_JOB_NAME}.artifacts.reports.codequality to be one exact path`;
|
|
34
107
|
if (!location) {
|
|
35
108
|
throw new Error(`${msg}, but no value was found.`);
|
|
@@ -41,8 +114,8 @@ function getOutputPath() {
|
|
|
41
114
|
}
|
|
42
115
|
|
|
43
116
|
/**
|
|
44
|
-
* @param {string} filePath
|
|
45
|
-
* @param {
|
|
117
|
+
* @param {string} filePath The path to the linted file.
|
|
118
|
+
* @param {LintMessage} message The ESLint report message.
|
|
46
119
|
* @returns {string} The fingerprint for the ESLint report message.
|
|
47
120
|
*/
|
|
48
121
|
function createFingerprint(filePath, message) {
|
|
@@ -56,44 +129,155 @@ function createFingerprint(filePath, message) {
|
|
|
56
129
|
}
|
|
57
130
|
|
|
58
131
|
/**
|
|
59
|
-
* @param {
|
|
60
|
-
* @
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
132
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
133
|
+
* @param {LintResultData} data The ESLint report result data.
|
|
134
|
+
* @returns {CodeClimateIssue[]} The ESLint messages in the form of a GitLab code quality report.
|
|
135
|
+
*/
|
|
136
|
+
function convert(results, data) {
|
|
137
|
+
/** @type {CodeClimateIssue[]} */
|
|
138
|
+
const messages = [];
|
|
139
|
+
for (const result of results) {
|
|
140
|
+
for (const message of result.messages) {
|
|
141
|
+
const relativePath = relative(CI_PROJECT_DIR, result.filePath);
|
|
142
|
+
|
|
143
|
+
/** @type {CodeClimateIssue} */
|
|
144
|
+
const issue = {
|
|
145
|
+
type: 'issue',
|
|
146
|
+
check_name: message.ruleId ?? '',
|
|
147
|
+
description: message.message,
|
|
148
|
+
severity: message.severity === 2 ? 'major' : 'minor',
|
|
149
|
+
fingerprint: createFingerprint(relativePath, message),
|
|
150
|
+
location: {
|
|
151
|
+
path: relativePath,
|
|
152
|
+
lines: {
|
|
153
|
+
begin: message.line,
|
|
154
|
+
end: message.endLine ?? message.line,
|
|
78
155
|
},
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
const docs = message.ruleId ? data.rulesMeta[message.ruleId]?.docs : undefined;
|
|
159
|
+
if (docs) {
|
|
160
|
+
let body = docs.description || '';
|
|
161
|
+
if (docs.url) {
|
|
162
|
+
if (body) {
|
|
163
|
+
body += '\n\n';
|
|
164
|
+
}
|
|
165
|
+
body += `[${message.ruleId}](${docs.url})`;
|
|
166
|
+
}
|
|
167
|
+
if (body) {
|
|
168
|
+
issue.contents = { body };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
messages.push(issue);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return messages;
|
|
84
175
|
}
|
|
85
176
|
|
|
86
|
-
|
|
177
|
+
/**
|
|
178
|
+
* @param {LintMessage} message The ESLint report message.
|
|
179
|
+
* @returns {boolean} `true` if the message is at error level, `false` if it represents a warning
|
|
180
|
+
*/
|
|
181
|
+
function messageIsLevelError(message) {
|
|
182
|
+
return message.fatal || message.severity === 2;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Make a text singular or plural based on the count.
|
|
187
|
+
*
|
|
188
|
+
* @param {number} count The count of the data.
|
|
189
|
+
* @param {string} text The text to make singular or plural.
|
|
190
|
+
* @returns {string} The formatted text.
|
|
191
|
+
*/
|
|
192
|
+
function plural(count, text) {
|
|
193
|
+
return `${count} ${text}${count === 1 ? '' : 's'}`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
198
|
+
* @returns {string} The ESLint messages converted to a format
|
|
199
|
+
* suitable as output in GitLab CI job logs.
|
|
200
|
+
*/
|
|
201
|
+
function gitlabConsoleFormatter(results) {
|
|
202
|
+
// Severity labels manually padded to have equal lengths and end with spaces
|
|
203
|
+
const labelError = `${chalk.red('error')} `;
|
|
204
|
+
const labelWarn = `${chalk.yellow('warn')} `;
|
|
205
|
+
|
|
206
|
+
const lines = [''];
|
|
207
|
+
|
|
208
|
+
/** @type {string | undefined} */
|
|
209
|
+
let gitLabBaseURL;
|
|
210
|
+
if (CI_PROJECT_URL && CI_COMMIT_SHORT_SHA) {
|
|
211
|
+
gitLabBaseURL = `${CI_PROJECT_URL}/-/blob/${CI_COMMIT_SHORT_SHA}/`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let errors = 0;
|
|
215
|
+
let warnings = 0;
|
|
216
|
+
let maxRuleIdLength = 0;
|
|
217
|
+
let maxMsgLength = 0;
|
|
218
|
+
|
|
219
|
+
for (const result of results) {
|
|
220
|
+
for (const message of result.messages) {
|
|
221
|
+
const isError = messageIsLevelError(message);
|
|
222
|
+
errors += isError ? 1 : 0;
|
|
223
|
+
warnings += isError ? 0 : 1;
|
|
224
|
+
maxRuleIdLength = message.ruleId
|
|
225
|
+
? Math.max(maxRuleIdLength, message.ruleId.length)
|
|
226
|
+
: maxRuleIdLength;
|
|
227
|
+
maxMsgLength = Math.max(maxMsgLength, message.message.length);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
for (const result of results) {
|
|
232
|
+
const { filePath, messages } = result;
|
|
233
|
+
const repoFilePath = relative(CI_PROJECT_DIR, filePath);
|
|
234
|
+
|
|
235
|
+
for (const message of messages) {
|
|
236
|
+
let line;
|
|
237
|
+
line = messageIsLevelError(message) ? labelError : labelWarn;
|
|
238
|
+
line += String(message.ruleId || '').padEnd(maxRuleIdLength + 2);
|
|
239
|
+
line += message.message.padEnd(maxMsgLength + 2);
|
|
240
|
+
|
|
241
|
+
if (gitLabBaseURL) {
|
|
242
|
+
// Create link to referenced file in GitLab
|
|
243
|
+
const anchor = message.line === undefined ? '' : `#L${message.line}`;
|
|
244
|
+
line += chalk.blue(`${gitLabBaseURL}${repoFilePath}${anchor}`);
|
|
245
|
+
} else {
|
|
246
|
+
line += `${filePath}:${message.line || 0}:${message.column || 0}`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
lines.push(line);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const total = warnings + errors;
|
|
254
|
+
if (total > 0) {
|
|
255
|
+
const details = `(${plural(errors, 'error')}, ${plural(warnings, 'warning')})`;
|
|
256
|
+
lines.push('', `${chalk.red('✖')} ${plural(total, 'problem')} ${details}`);
|
|
257
|
+
} else {
|
|
258
|
+
lines.push(`${chalk.green('✔')} No problems found`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
lines.push('');
|
|
262
|
+
return lines.join(EOL);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @param {LintResult[]} results The ESLint report results.
|
|
267
|
+
* @param {LintResultData} data The ESLint report result data.
|
|
268
|
+
*/
|
|
269
|
+
module.exports = (results, data) => {
|
|
270
|
+
/* istanbul ignore next */
|
|
271
|
+
if (GITLAB_CI === 'true' && NODE_ENV !== 'test') {
|
|
272
|
+
chalk.level = 1;
|
|
273
|
+
}
|
|
87
274
|
if (CI_JOB_NAME || ESLINT_CODE_QUALITY_REPORT) {
|
|
88
|
-
const
|
|
275
|
+
const issues = convert(results, data);
|
|
89
276
|
const outputPath = ESLINT_CODE_QUALITY_REPORT || getOutputPath();
|
|
90
277
|
const dir = dirname(outputPath);
|
|
91
278
|
mkdirSync(dir, { recursive: true });
|
|
92
|
-
writeFileSync(outputPath, JSON.stringify(
|
|
279
|
+
writeFileSync(outputPath, JSON.stringify(issues, null, 2));
|
|
93
280
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
formatter = CLIEngine.getFormatter();
|
|
97
|
-
}
|
|
98
|
-
return formatter(results);
|
|
281
|
+
|
|
282
|
+
return gitlabConsoleFormatter(results);
|
|
99
283
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-formatter-gitlab",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.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",
|
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://gitlab.com/remcohaszing/eslint-formatter-gitlab.git"
|
|
11
11
|
},
|
|
12
|
+
"funding": "https://github.com/sponsors/remcohaszing",
|
|
12
13
|
"bugs": {
|
|
13
14
|
"url": "https://gitlab.com/remcohaszing/eslint-formatter-gitlab.git/issues"
|
|
14
15
|
},
|
|
16
|
+
"exports": "./index.js",
|
|
15
17
|
"files": [
|
|
16
18
|
"index.js"
|
|
17
19
|
],
|
|
18
20
|
"scripts": {
|
|
19
|
-
"test": "jest"
|
|
21
|
+
"test": "jest --coverage"
|
|
20
22
|
},
|
|
21
23
|
"keywords": [
|
|
22
24
|
"eslint",
|
|
@@ -25,29 +27,28 @@
|
|
|
25
27
|
"gitlab",
|
|
26
28
|
"gitlab-ci"
|
|
27
29
|
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=14.0.0"
|
|
32
|
+
},
|
|
28
33
|
"dependencies": {
|
|
29
|
-
"
|
|
34
|
+
"chalk": "^4.0.0",
|
|
35
|
+
"yaml": "^2.0.0"
|
|
30
36
|
},
|
|
31
37
|
"peerDependencies": {
|
|
32
|
-
"eslint": "^5 || ^6 || ^7"
|
|
38
|
+
"eslint": "^5 || ^6 || ^7 || ^8"
|
|
33
39
|
},
|
|
34
40
|
"devDependencies": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"eslint
|
|
39
|
-
"eslint-
|
|
40
|
-
"eslint-plugin-jest": "^
|
|
41
|
-
"eslint-plugin-jest-formatting": "^
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
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"
|
|
41
|
+
"@types/eslint": "^8.0.0",
|
|
42
|
+
"@types/jest": "^29.0.0",
|
|
43
|
+
"@types/node": "^18.0.0",
|
|
44
|
+
"eslint": "^8.0.0",
|
|
45
|
+
"eslint-config-remcohaszing": "^7.0.0",
|
|
46
|
+
"eslint-plugin-jest": "^27.0.0",
|
|
47
|
+
"eslint-plugin-jest-formatting": "^3.0.0",
|
|
48
|
+
"jest": "^29.0.0",
|
|
49
|
+
"jest-junit": "^14.0.0",
|
|
50
|
+
"memfs": "^3.0.0",
|
|
51
|
+
"prettier": "^2.0.0",
|
|
52
|
+
"typescript": "^4.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.
|