Skip to content

Commit fc9b28a

Browse files
committedNov 29, 2018
feat: use globs instead of regexp for releases rules
BREAKING CHANGE: Regexp are not supported anymore for property matching in the `releaseRules` option. Regex are replaced by [globs](https://github.com/micromatch/micromatch#matching-features). For example `/core-.*/` should be changed to `'core-*'`.
1 parent d6027fa commit fc9b28a

File tree

5 files changed

+23
-22
lines changed

5 files changed

+23
-22
lines changed
 

‎README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ With this example:
6767

6868
#### releaseRules
6969

70-
Release rules are used when deciding if the commits since the last release warrant a new release. If you define custom release rules the [default rules](lib/default-release-rules.js) will be used if nothing matched. Those rules will be matched against the commit objects resulting of [conventional-commits-parser](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser) parsing.
70+
Release rules are used when deciding if the commits since the last release warrant a new release. If you define custom release rules the [default rules](lib/default-release-rules.js) will be used if nothing matched. Those rules will be matched against the commit objects resulting of [conventional-commits-parser](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser) parsing. Each rule property can be defined as a [glob](https://github.com/micromatch/micromatch#matching-features).
7171

7272
##### Rules definition
7373

@@ -79,7 +79,7 @@ This is an `Array` of rule objects. A rule object has a `release` property and 1
7979
"preset": "angular",
8080
"releaseRules": [
8181
{"type": "docs", "scope": "README", "release": "patch"},
82-
{"type": "refactor", "scope": "/core-.*/", "release": "minor"},
82+
{"type": "refactor", "scope": "core-*", "release": "minor"},
8383
{"type": "refactor", "release": "patch"}
8484
]
8585
}],
@@ -97,7 +97,7 @@ See [release types](lib/default-release-types.js) for the release types hierarch
9797
With the previous example:
9898
- Commits with `type` 'docs' and `scope` 'README' will be associated with a `patch` release.
9999
- Commits with `type` 'refactor' and `scope` starting with 'core-' (i.e. 'core-ui', 'core-rules', ...) will be associated with a `minor` release.
100-
- Other commits with `type` 'refactor' (without `scope` or with a `scope` not matching the regexp `/core-.*/`) will be associated with a `patch` release.
100+
- Other commits with `type` 'refactor' (without `scope` or with a `scope` not matching the glob `core-*`) will be associated with a `patch` release.
101101

102102
##### Default rules matching
103103

@@ -139,7 +139,7 @@ For example with `eslint` preset:
139139
["semantic-release/commit-analyzer", {
140140
"preset": "eslint",
141141
"releaseRules": [
142-
{"tag": "Docs", "message":"/README/", "release": "patch"},
142+
{"tag": "Docs", "message":"*README*", "release": "patch"},
143143
{"type": "New", "release": "patch"}
144144
]
145145
}],
@@ -174,7 +174,7 @@ With this configuration:
174174
// File: config/release-rules.js
175175
module.exports = [
176176
{type: 'docs', scope: 'README', release: 'patch'},
177-
{type: 'refactor', scope: /core-.*/, release: 'minor'},
177+
{type: 'refactor', scope: 'core-*', release: 'minor'},
178178
{type: 'refactor', release: 'patch'},
179179
];
180180
```

‎lib/analyze-commit.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
const {isMatchWith, isRegExp} = require('lodash');
1+
const {isMatchWith, isString} = require('lodash');
2+
const micromatch = require('micromatch');
23
const debug = require('debug')('semantic-release:commit-analyzer');
34
const RELEASE_TYPES = require('./default-release-types');
45
const compareReleaseTypes = require('./compare-release-types');
@@ -22,7 +23,7 @@ module.exports = (releaseRules, commit) => {
2223
(!revert || commit.revert) &&
2324
// Otherwise match the regular rules
2425
isMatchWith(commit, rule, (obj, src) =>
25-
/^\/.*\/$/.test(src) || isRegExp(src) ? new RegExp(/^\/(.*)\/$/.exec(src)[1]).test(obj) : undefined
26+
isString(src) && isString(obj) ? micromatch.isMatch(obj, src) : undefined
2627
)
2728
)
2829
.every(match => {

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"conventional-commits-parser": "^3.0.0",
2222
"debug": "^4.0.0",
2323
"import-from": "^2.1.0",
24-
"lodash": "^4.17.4"
24+
"lodash": "^4.17.4",
25+
"micromatch": "^3.1.10"
2526
},
2627
"devDependencies": {
2728
"ava": "^0.25.0",

‎test/analyze-commit.test.js

+11-12
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ test('Match multiple criteria with revert', t => {
3636
});
3737

3838
test('Match multiple criteria', t => {
39-
const commit = {type: 'feat', scope: 'test'};
39+
const commit = {type: 'feat', scope: 1};
4040

41-
t.is(analyzeCommit([{type: 'feat', scope: 'test', release: 'major'}], commit), 'major');
41+
t.is(analyzeCommit([{type: 'feat', scope: 1, release: 'major'}], commit), 'major');
4242
});
4343

4444
test('Match only if all criteria are verified', t => {
@@ -62,21 +62,20 @@ test('Return undefined if there is no match', t => {
6262
t.is(analyzeCommit([{type: 'feat', breaking: true, release: 'major'}], commit), undefined);
6363
});
6464

65-
test('Match with regex', t => {
66-
const rules = [{type: 'docs', scope: /test\(.*\)/, release: 'minor'}];
67-
const match = {type: 'docs', scope: 'test(readme): message'};
68-
const notMatch = {type: 'docs', scope: 'test2(readme): message'};
65+
test('Return undefined for commit with falsy properties', t => {
66+
const commit = {type: null};
6967

70-
t.is(analyzeCommit(rules, match), 'minor');
71-
t.is(analyzeCommit(rules, notMatch), undefined);
68+
t.is(analyzeCommit([{type: 'feat'}], commit), undefined);
7269
});
7370

74-
test('Match with regex as string', t => {
75-
const rules = [{type: 'docs', scope: '/test\\(.*\\)/', release: 'minor'}];
76-
const match = {type: 'docs', scope: 'test(readme): message'};
77-
const notMatch = {type: 'docs', scope: 'test2(readme): message'};
71+
test('Match with glob', t => {
72+
const rules = [{type: 'docs', scope: 'b*', release: 'minor'}];
73+
const match = {type: 'docs', scope: 'bar'};
74+
const match2 = {type: 'docs', scope: 'baz'};
75+
const notMatch = {type: 'docs', scope: 'foo'};
7876

7977
t.is(analyzeCommit(rules, match), 'minor');
78+
t.is(analyzeCommit(rules, match2), 'minor');
8079
t.is(analyzeCommit(rules, notMatch), undefined);
8180
});
8281

‎test/integration.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ test('Return "patch" if there is only types set to "patch", using default releas
141141
t.true(t.context.log.calledWith('Analysis of %s commits complete: %s release', 2, 'patch'));
142142
});
143143

144-
test('Allow to use regex in "releaseRules" configuration', async t => {
144+
test('Allow to use glob in "releaseRules" configuration', async t => {
145145
const commits = [{message: 'Chore: First chore (fixes #123)'}, {message: 'Docs: update README (fixes #456)'}];
146146
const releaseType = await analyzeCommits(
147-
{preset: 'eslint', releaseRules: [{tag: 'Chore', release: 'patch'}, {message: '/README/', release: 'minor'}]},
147+
{preset: 'eslint', releaseRules: [{tag: 'Chore', release: 'patch'}, {message: '*README*', release: 'minor'}]},
148148
{cwd, commits, logger: t.context.logger}
149149
);
150150

0 commit comments

Comments
 (0)
Please sign in to comment.