diff --git a/README.md b/README.md index b88788fd..43d9ad81 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ With this example: #### releaseRules -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. +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). ##### Rules definition @@ -79,7 +79,7 @@ This is an `Array` of rule objects. A rule object has a `release` property and 1 "preset": "angular", "releaseRules": [ {"type": "docs", "scope": "README", "release": "patch"}, - {"type": "refactor", "scope": "/core-.*/", "release": "minor"}, + {"type": "refactor", "scope": "core-*", "release": "minor"}, {"type": "refactor", "release": "patch"} ] }], @@ -97,7 +97,7 @@ See [release types](lib/default-release-types.js) for the release types hierarch With the previous example: - Commits with `type` 'docs' and `scope` 'README' will be associated with a `patch` release. - Commits with `type` 'refactor' and `scope` starting with 'core-' (i.e. 'core-ui', 'core-rules', ...) will be associated with a `minor` release. -- Other commits with `type` 'refactor' (without `scope` or with a `scope` not matching the regexp `/core-.*/`) will be associated with a `patch` release. +- Other commits with `type` 'refactor' (without `scope` or with a `scope` not matching the glob `core-*`) will be associated with a `patch` release. ##### Default rules matching @@ -139,7 +139,7 @@ For example with `eslint` preset: ["semantic-release/commit-analyzer", { "preset": "eslint", "releaseRules": [ - {"tag": "Docs", "message":"/README/", "release": "patch"}, + {"tag": "Docs", "message":"*README*", "release": "patch"}, {"type": "New", "release": "patch"} ] }], @@ -174,7 +174,7 @@ With this configuration: // File: config/release-rules.js module.exports = [ {type: 'docs', scope: 'README', release: 'patch'}, - {type: 'refactor', scope: /core-.*/, release: 'minor'}, + {type: 'refactor', scope: 'core-*', release: 'minor'}, {type: 'refactor', release: 'patch'}, ]; ``` diff --git a/lib/analyze-commit.js b/lib/analyze-commit.js index d5263312..dc918e1b 100644 --- a/lib/analyze-commit.js +++ b/lib/analyze-commit.js @@ -1,4 +1,5 @@ -const {isMatchWith, isRegExp} = require('lodash'); +const {isMatchWith, isString} = require('lodash'); +const micromatch = require('micromatch'); const debug = require('debug')('semantic-release:commit-analyzer'); const RELEASE_TYPES = require('./default-release-types'); const compareReleaseTypes = require('./compare-release-types'); @@ -22,7 +23,7 @@ module.exports = (releaseRules, commit) => { (!revert || commit.revert) && // Otherwise match the regular rules isMatchWith(commit, rule, (obj, src) => - /^\/.*\/$/.test(src) || isRegExp(src) ? new RegExp(/^\/(.*)\/$/.exec(src)[1]).test(obj) : undefined + isString(src) && isString(obj) ? micromatch.isMatch(obj, src) : undefined ) ) .every(match => { diff --git a/package.json b/package.json index 83de9d42..91702748 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "conventional-commits-parser": "^3.0.0", "debug": "^4.0.0", "import-from": "^2.1.0", - "lodash": "^4.17.4" + "lodash": "^4.17.4", + "micromatch": "^3.1.10" }, "devDependencies": { "ava": "^0.25.0", diff --git a/test/analyze-commit.test.js b/test/analyze-commit.test.js index d2141f32..d6109c59 100644 --- a/test/analyze-commit.test.js +++ b/test/analyze-commit.test.js @@ -36,9 +36,9 @@ test('Match multiple criteria with revert', t => { }); test('Match multiple criteria', t => { - const commit = {type: 'feat', scope: 'test'}; + const commit = {type: 'feat', scope: 1}; - t.is(analyzeCommit([{type: 'feat', scope: 'test', release: 'major'}], commit), 'major'); + t.is(analyzeCommit([{type: 'feat', scope: 1, release: 'major'}], commit), 'major'); }); test('Match only if all criteria are verified', t => { @@ -62,21 +62,20 @@ test('Return undefined if there is no match', t => { t.is(analyzeCommit([{type: 'feat', breaking: true, release: 'major'}], commit), undefined); }); -test('Match with regex', t => { - const rules = [{type: 'docs', scope: /test\(.*\)/, release: 'minor'}]; - const match = {type: 'docs', scope: 'test(readme): message'}; - const notMatch = {type: 'docs', scope: 'test2(readme): message'}; +test('Return undefined for commit with falsy properties', t => { + const commit = {type: null}; - t.is(analyzeCommit(rules, match), 'minor'); - t.is(analyzeCommit(rules, notMatch), undefined); + t.is(analyzeCommit([{type: 'feat'}], commit), undefined); }); -test('Match with regex as string', t => { - const rules = [{type: 'docs', scope: '/test\\(.*\\)/', release: 'minor'}]; - const match = {type: 'docs', scope: 'test(readme): message'}; - const notMatch = {type: 'docs', scope: 'test2(readme): message'}; +test('Match with glob', t => { + const rules = [{type: 'docs', scope: 'b*', release: 'minor'}]; + const match = {type: 'docs', scope: 'bar'}; + const match2 = {type: 'docs', scope: 'baz'}; + const notMatch = {type: 'docs', scope: 'foo'}; t.is(analyzeCommit(rules, match), 'minor'); + t.is(analyzeCommit(rules, match2), 'minor'); t.is(analyzeCommit(rules, notMatch), undefined); }); diff --git a/test/integration.test.js b/test/integration.test.js index f01f7536..df4a3339 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -141,10 +141,10 @@ test('Return "patch" if there is only types set to "patch", using default releas t.true(t.context.log.calledWith('Analysis of %s commits complete: %s release', 2, 'patch')); }); -test('Allow to use regex in "releaseRules" configuration', async t => { +test('Allow to use glob in "releaseRules" configuration', async t => { const commits = [{message: 'Chore: First chore (fixes #123)'}, {message: 'Docs: update README (fixes #456)'}]; const releaseType = await analyzeCommits( - {preset: 'eslint', releaseRules: [{tag: 'Chore', release: 'patch'}, {message: '/README/', release: 'minor'}]}, + {preset: 'eslint', releaseRules: [{tag: 'Chore', release: 'patch'}, {message: '*README*', release: 'minor'}]}, {cwd, commits, logger: t.context.logger} );