Skip to content

Commit b22bea9

Browse files
committed
feat(core): Allow to configure with json, yaml and package.json
Fix conventional-changelog#73
1 parent e6ef072 commit b22bea9

File tree

18 files changed

+191
-56
lines changed

18 files changed

+191
-56
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
extends: ['./first-extended'],
3+
rules: {
4+
zero: 0
5+
}
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
extends: ['./second-extended'],
3+
rules: {
4+
one: 1
5+
}
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
two: 2
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": ["./first-extended"],
3+
"rules": {
4+
"zero": 0
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
extends: ['./second-extended'],
3+
rules: {
4+
one: 1
5+
}
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
two: 2
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
extends: ['./second-extended'],
3+
rules: {
4+
one: 1
5+
}
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
two: 2
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"commitlint": {
3+
"extends": ["./first-extended"],
4+
"rules": {
5+
"zero": 0
6+
}
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
extends:
2+
- "./first-extended"
3+
rules:
4+
zero: 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
extends: ['./second-extended'],
3+
rules: {
4+
one: 1
5+
}
6+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
two: 2
4+
}
5+
};

@commitlint/core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@
8686
"chalk": "^2.0.1",
8787
"conventional-changelog-angular": "^1.3.3",
8888
"conventional-commits-parser": "^1.3.0",
89+
"cosmiconfig": "^3.0.1",
8990
"find-up": "^2.1.0",
9091
"franc": "^2.0.0",
9192
"git-raw-commits": "^1.1.2",
92-
"import-from": "^2.1.0",
9393
"lodash": "^4.17.4",
9494
"mz": "^2.6.0",
9595
"path-exists": "^3.0.0",

@commitlint/core/src/load.js

+23-23
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path';
2-
import importFrom from 'import-from';
32
import {entries, merge, mergeWith, pick} from 'lodash';
43
import rc from 'rc';
4+
import cosmiconfig from 'cosmiconfig';
55
import resolveFrom from 'resolve-from';
66

77
import resolveExtends from './library/resolve-extends';
@@ -12,19 +12,23 @@ const valid = input => pick(input, 'extends', 'rules', 'parserPreset');
1212

1313
export default async (seed = {}) => {
1414
// Obtain config from .rc files
15-
const raw = file();
16-
15+
const raw = await file();
1716
// Merge passed config with file based options
1817
const config = valid(merge(raw, seed));
1918
const opts = merge({extends: [], rules: {}}, pick(config, 'extends'));
2019

2120
// Resolve parserPreset key
2221
if (typeof config.parserPreset === 'string') {
23-
const resolvedParserPreset = resolveFrom(process.cwd(), config.parserPreset);
22+
const resolvedParserPreset = resolveFrom(
23+
process.cwd(),
24+
config.parserPreset
25+
);
2426

2527
config.parserPreset = {
2628
name: config.parserPreset,
27-
path: `./${path.posix.relative(process.cwd(), resolvedParserPreset)}`.split(path.sep).join('/'),
29+
path: `./${path.posix.relative(process.cwd(), resolvedParserPreset)}`
30+
.split(path.sep)
31+
.join('/'),
2832
opts: require(resolvedParserPreset)
2933
};
3034
}
@@ -39,7 +43,10 @@ export default async (seed = {}) => {
3943
const preset = valid(mergeWith(extended, config, w));
4044

4145
// Await parser-preset if applicable
42-
if (typeof preset.parserPreset === 'object' && typeof preset.parserPreset.opts === 'object') {
46+
if (
47+
typeof preset.parserPreset === 'object' &&
48+
typeof preset.parserPreset.opts === 'object'
49+
) {
4350
preset.parserPreset.opts = await preset.parserPreset.opts;
4451
}
4552

@@ -73,14 +80,16 @@ export default async (seed = {}) => {
7380
}, preset);
7481
};
7582

76-
function file() {
83+
async function file() {
7784
const legacy = rc('conventional-changelog-lint');
7885
const legacyFound = typeof legacy.config === 'string';
86+
const explorer = cosmiconfig('commitlint', {
87+
rcExtensions: true,
88+
stopDir: process.cwd()
89+
});
90+
const config = await explorer.load('.');
7991

80-
const found = resolveable('./commitlint.config');
81-
const raw = found ? importFrom(process.cwd(), './commitlint.config') : {};
82-
83-
if (legacyFound && !found) {
92+
if (legacyFound && !config) {
8493
console.warn(
8594
`Using legacy ${path.relative(
8695
process.cwd(),
@@ -89,7 +98,7 @@ function file() {
8998
);
9099
}
91100

92-
if (legacyFound && found) {
101+
if (legacyFound && config) {
93102
console.warn(
94103
`Ignored legacy ${path.relative(
95104
process.cwd(),
@@ -98,18 +107,9 @@ function file() {
98107
);
99108
}
100109

101-
if (found) {
102-
return raw;
110+
if (config) {
111+
return config.config;
103112
}
104113

105114
return legacy;
106115
}
107-
108-
function resolveable(id) {
109-
try {
110-
resolveFrom(process.cwd(), id);
111-
return true;
112-
} catch (err) {
113-
return false;
114-
}
115-
}

@commitlint/core/src/load.test.js

+94-31
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,24 @@ test.afterEach.always(t => {
99
t.context.back();
1010
});
1111

12-
test('extends-empty should have no rules', async t => {
12+
test.serial('extends-empty should have no rules', async t => {
1313
t.context.back = chdir('fixtures/extends-empty');
1414
const actual = await load();
1515
t.deepEqual(actual.rules, {});
1616
});
1717

18-
test('uses seed as configured', async t => {
18+
test.serial('uses seed as configured', async t => {
1919
t.context.back = chdir('fixtures/extends-empty');
2020
const actual = await load({rules: {foo: 'bar'}});
2121
t.is(actual.rules.foo, 'bar');
2222
});
2323

24-
test('uses seed with parserPreset', async t => {
24+
test.serial('uses seed with parserPreset', async t => {
2525
t.context.back = chdir('fixtures/parser-preset');
2626

27-
const {parserPreset: actual} = await load({parserPreset: './conventional-changelog-custom'});
27+
const {parserPreset: actual} = await load({
28+
parserPreset: './conventional-changelog-custom'
29+
});
2830
t.is(actual.name, './conventional-changelog-custom');
2931
t.deepEqual(actual.opts, {
3032
parserOpts: {
@@ -33,24 +35,24 @@ test('uses seed with parserPreset', async t => {
3335
});
3436
});
3537

36-
test('invalid extend should throw', t => {
38+
test.serial('invalid extend should throw', t => {
3739
t.context.back = chdir('fixtures/extends-invalid');
3840
t.throws(load());
3941
});
4042

41-
test('empty file should have no rules', async t => {
43+
test.serial('empty file should have no rules', async t => {
4244
t.context.back = chdir('fixtures/empty-object-file');
4345
const actual = await load();
4446
t.deepEqual(actual.rules, {});
4547
});
4648

47-
test('empty file should extend nothing', async t => {
49+
test.serial('empty file should extend nothing', async t => {
4850
t.context.back = chdir('fixtures/empty-file');
4951
const actual = await load();
5052
t.deepEqual(actual.extends, []);
5153
});
5254

53-
test('recursive extends', async t => {
55+
test.serial('recursive extends', async t => {
5456
t.context.back = chdir('fixtures/recursive-extends');
5557
const actual = await load();
5658
t.deepEqual(actual, {
@@ -63,30 +65,88 @@ test('recursive extends', async t => {
6365
});
6466
});
6567

66-
test('parser preset overwrites completely instead of merging', async t => {
67-
t.context.back = chdir('fixtures/parser-preset-override');
68+
test.serial('recursive extends with json file', async t => {
69+
t.context.back = chdir('fixtures/recursive-extends-json');
6870
const actual = await load();
71+
t.deepEqual(actual, {
72+
extends: ['./first-extended'],
73+
rules: {
74+
zero: 0,
75+
one: 1,
76+
two: 2
77+
}
78+
});
79+
});
6980

70-
t.is(actual.parserPreset.name, './custom');
71-
t.is(typeof actual.parserPreset.opts, 'object');
72-
t.deepEqual(actual.parserPreset.opts, {
73-
b: 'b',
74-
parserOpts: {
75-
headerPattern: /.*/
81+
test.serial('recursive extends with yaml file', async t => {
82+
t.context.back = chdir('fixtures/recursive-extends-yaml');
83+
const actual = await load();
84+
t.deepEqual(actual, {
85+
extends: ['./first-extended'],
86+
rules: {
87+
zero: 0,
88+
one: 1,
89+
two: 2
90+
}
91+
});
92+
});
93+
94+
test.serial('recursive extends with js file', async t => {
95+
t.context.back = chdir('fixtures/recursive-extends-js');
96+
const actual = await load();
97+
t.deepEqual(actual, {
98+
extends: ['./first-extended'],
99+
rules: {
100+
zero: 0,
101+
one: 1,
102+
two: 2
103+
}
104+
});
105+
});
106+
107+
test.serial('recursive extends with package.json file', async t => {
108+
t.context.back = chdir('fixtures/recursive-extends-package');
109+
const actual = await load();
110+
t.deepEqual(actual, {
111+
extends: ['./first-extended'],
112+
rules: {
113+
zero: 0,
114+
one: 1,
115+
two: 2
76116
}
77117
});
78118
});
79119

80-
test('recursive extends with parserPreset', async t => {
120+
test.serial(
121+
'parser preset overwrites completely instead of merging',
122+
async t => {
123+
t.context.back = chdir('fixtures/parser-preset-override');
124+
const actual = await load();
125+
126+
t.is(actual.parserPreset.name, './custom');
127+
t.is(typeof actual.parserPreset.opts, 'object');
128+
t.deepEqual(actual.parserPreset.opts, {
129+
b: 'b',
130+
parserOpts: {
131+
headerPattern: /.*/
132+
}
133+
});
134+
}
135+
);
136+
137+
test.serial('recursive extends with parserPreset', async t => {
81138
t.context.back = chdir('fixtures/recursive-parser-preset');
82139
const actual = await load();
83140

84141
t.is(actual.parserPreset.name, './conventional-changelog-custom');
85142
t.is(typeof actual.parserPreset.opts, 'object');
86-
t.deepEqual(actual.parserPreset.opts.parserOpts.headerPattern, /^(\w*)(?:\((.*)\))?-(.*)$/);
143+
t.deepEqual(
144+
actual.parserPreset.opts.parserOpts.headerPattern,
145+
/^(\w*)(?:\((.*)\))?-(.*)$/
146+
);
87147
});
88148

89-
test('ignores unknow keys', async t => {
149+
test.serial('ignores unknow keys', async t => {
90150
t.context.back = chdir('fixtures/trash-file');
91151
const actual = await load();
92152
t.deepEqual(actual, {
@@ -98,7 +158,7 @@ test('ignores unknow keys', async t => {
98158
});
99159
});
100160

101-
test('ignores unknow keys recursively', async t => {
161+
test.serial('ignores unknow keys recursively', async t => {
102162
t.context.back = chdir('fixtures/trash-extend');
103163
const actual = await load();
104164
t.deepEqual(actual, {
@@ -110,7 +170,7 @@ test('ignores unknow keys recursively', async t => {
110170
});
111171
});
112172

113-
test('supports legacy .conventional-changelog-lintrc', async t => {
173+
test.serial('supports legacy .conventional-changelog-lintrc', async t => {
114174
t.context.back = chdir('fixtures/legacy');
115175
const actual = await load();
116176
t.deepEqual(actual, {
@@ -121,16 +181,19 @@ test('supports legacy .conventional-changelog-lintrc', async t => {
121181
});
122182
});
123183

124-
test('commitlint.config.js overrides .conventional-changelog-lintrc', async t => {
125-
t.context.back = chdir('fixtures/overriden-legacy');
126-
const actual = await load();
127-
t.deepEqual(actual, {
128-
extends: [],
129-
rules: {
130-
legacy: false
131-
}
132-
});
133-
});
184+
test.serial(
185+
'commitlint.config.js overrides .conventional-changelog-lintrc',
186+
async t => {
187+
t.context.back = chdir('fixtures/overriden-legacy');
188+
const actual = await load();
189+
t.deepEqual(actual, {
190+
extends: [],
191+
rules: {
192+
legacy: false
193+
}
194+
});
195+
}
196+
);
134197

135198
function chdir(target) {
136199
const to = path.resolve(cwd, target.split('/').join(path.sep));

0 commit comments

Comments
 (0)