Skip to content
This repository has been archived by the owner on Feb 5, 2018. It is now read-only.

Commit

Permalink
Merge pull request #65 from Garbee/garbee/filter-scopes
Browse files Browse the repository at this point in the history
Add support for scope validation
  • Loading branch information
spirosikmd committed Jan 26, 2017
2 parents 04facc4 + 3149921 commit 815bc77
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 3 deletions.
11 changes: 11 additions & 0 deletions .all-contributorsrc
Expand Up @@ -247,6 +247,17 @@
"contributions": [
"bug"
]
},
{
"login": "Garbee",
"name": "Jonathan Garbee",
"avatar_url": "https://avatars.githubusercontent.com/u/868301?v=3",
"profile": "http://jonathan.garbee.me",
"contributions": [
"code",
"doc",
"test"
]
}
]
}
38 changes: 36 additions & 2 deletions README.md
Expand Up @@ -7,7 +7,7 @@
[![downloads][downloads-badge]][npm-stat]
[![MIT License][license-badge]][LICENSE]

[![All Contributors](https://img.shields.io/badge/all_contributors-24-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-25-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Donate][donate-badge]][donate]
[![Code of Conduct][coc-badge]][coc]
Expand All @@ -34,6 +34,12 @@ You can specify options in `.vcmrc`
```js
{
"types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "revert"], // default
"scope": {
required: false, // default,
allowed: ['button', 'card'], // default is '*' for anything,
validate: false, // default,
multiple: false // default
},
"warnOnFail": false, // default
"maxSubjectLength": 100, // default
"subjectPattern": ".+", // default
Expand All @@ -50,6 +56,12 @@ or in `package.json`
"config": {
"validate-commit-msg": {
"types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "chore", "revert"], // default
"scope": {
required: false, // default,
allowed: ['button', 'card'], // default is '*' for anything,
validate: false, // default,
multiple: false // default
},
"warnOnFail": false, // default
"maxSubjectLength": 100, // default
"subjectPattern": ".+", // default
Expand All @@ -73,6 +85,28 @@ Or you can specify the name of a module that exports types according to the
[conventional-commit-types](https://github.com/adjohnson916/conventional-commit-types)
spec, e.g. `"types": "conventional-commit-types"`.

#### scope

This object defines scope requirements for the commit message. Possible properties are:

##### required

A boolean to define whether a scope is required for all commit messages.

##### allowed

An array of scopes that are allowed for your commit message.

You may also define it as `"*"` which is the default to allow any scope names.

##### validate

A boolean to define whether or not to validate the scope(s) provided.

##### multiple

A boolean to define whether or not to allow multiple scopes.

#### warnOnFail

If this is set to `true` errors will be logged to the console, however the commit will still pass.
Expand Down Expand Up @@ -155,7 +189,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars.githubusercontent.com/u/2112202?v=3" width="100px;"/><br /><sub>Shawn Erquhart</sub>](http://www.professant.com)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=erquhart) | [<img src="https://avatars.githubusercontent.com/u/194482?v=3" width="100px;"/><br /><sub>Tushar Mathur</sub>](http://tusharm.com)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=tusharmath) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=tusharmath) | [<img src="https://avatars.githubusercontent.com/u/904007?v=3" width="100px;"/><br /><sub>Jason Dreyzehner</sub>](https://twitter.com/bitjson)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=bitjson) | [<img src="https://avatars.githubusercontent.com/u/9654923?v=3" width="100px;"/><br /><sub>Abimbola Idowu</sub>](http://twitter.com/hisabimbola)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=hisabimbola) | [<img src="https://avatars.githubusercontent.com/u/2212006?v=3" width="100px;"/><br /><sub>Gleb Bahmutov</sub>](https://glebbahmutov.com/)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=bahmutov) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=bahmutov) | [<img src="https://avatars.githubusercontent.com/u/332905?v=3" width="100px;"/><br /><sub>Dennis</sub>](http://dennis.io)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=ds82) | [<img src="https://avatars.githubusercontent.com/u/6425649?v=3" width="100px;"/><br /><sub>Matt Lewis</sub>](https://mattlewis.me/)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=mattlewis92) |
| [<img src="https://avatars.githubusercontent.com/u/323761?v=3" width="100px;"/><br /><sub>Tom Vincent</sub>](https://tlvince.com)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=tlvince) | [<img src="https://avatars.githubusercontent.com/u/615381?v=3" width="100px;"/><br /><sub>Anders D. Johnson</sub>](https://andrz.me/)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=adjohnson916) | [<img src="https://avatars.githubusercontent.com/u/1643758?v=3" width="100px;"/><br /><sub>James Zetlen</sub>](jameszetlen.com)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=zetlen) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=zetlen) | [<img src="https://avatars.githubusercontent.com/u/235784?v=3" width="100px;"/><br /><sub>Paul Bienkowski</sub>](http://opatut.de)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=opatut) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=opatut) | [<img src="https://avatars.githubusercontent.com/u/324073?v=3" width="100px;"/><br /><sub>Barney Scott</sub>](https://github.com/bmds)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=bmds) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=bmds) | [<img src="https://avatars.githubusercontent.com/u/5572221?v=3" width="100px;"/><br /><sub>Emmanuel Murillo Sánchez</sub>](https://github.com/Emmurillo)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=Emmurillo) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=Emmurillo) | [<img src="https://avatars.githubusercontent.com/u/968267?v=3" width="100px;"/><br /><sub>Hans Kristian Flaatten</sub>](https://starefossen.github.io)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=Starefossen) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=Starefossen) |
| [<img src="https://avatars.githubusercontent.com/u/16605186?v=3" width="100px;"/><br /><sub>Bo Lingen</sub>](https://github.com/citycide)<br />[📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=citycide) | [<img src="https://avatars.githubusercontent.com/u/1057324?v=3" width="100px;"/><br /><sub>Spyros Ioakeimidis</sub>](http://www.spyros.io)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) | [<img src="https://avatars.githubusercontent.com/u/126441?v=3" width="100px;"/><br /><sub>Matt Travi</sub>](https://matt.travi.org)<br />[🐛](https://github.com/kentcdodds/validate-commit-msg/issues?q=author%3Atravi) |
| [<img src="https://avatars.githubusercontent.com/u/16605186?v=3" width="100px;"/><br /><sub>Bo Lingen</sub>](https://github.com/citycide)<br />[📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=citycide) | [<img src="https://avatars.githubusercontent.com/u/1057324?v=3" width="100px;"/><br /><sub>Spyros Ioakeimidis</sub>](http://www.spyros.io)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=spirosikmd) | [<img src="https://avatars.githubusercontent.com/u/126441?v=3" width="100px;"/><br /><sub>Matt Travi</sub>](https://matt.travi.org)<br />[🐛](https://github.com/kentcdodds/validate-commit-msg/issues?q=author%3Atravi) | [<img src="https://avatars.githubusercontent.com/u/868301?v=3" width="100px;"/><br /><sub>Jonathan Garbee</sub>](http://jonathan.garbee.me)<br />[💻](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) [📖](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) [⚠️](https://github.com/kentcdodds/validate-commit-msg/commits?author=Garbee) |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
43 changes: 42 additions & 1 deletion lib/validateMessage.js
Expand Up @@ -82,6 +82,8 @@ exports.validateMessage = function validateMessage(raw) {
isValid = false;
}

isValid = validateScope(isValid, scope);

if (config.autoFix) {
subject = lowercaseFirstLetter(subject);
}
Expand All @@ -94,7 +96,6 @@ exports.validateMessage = function validateMessage(raw) {

// Some more ideas, do want anything like this ?
// - Validate the rest of the message (body, footer, BREAKING CHANGE annotations)
// - allow only specific scopes (eg. fix(docs) should not be allowed ?
// - auto add empty line after subject ?
// - auto remove empty () ?
// - auto correct typos in type ?
Expand Down Expand Up @@ -128,3 +129,43 @@ function lowercase(string) {
function lowercaseFirstLetter(string) {
return lowercase(string.charAt(0)) + string.slice(1);
}

function validateScope(isValid, scope) {
config.scope = config.scope || {};
var validateScopes = config.scope.validate || false;
var multipleScopesAllowed = config.scope.multiple || false;
var allowedScopes = config.scope.allowed || '*';
var scopeRequired = config.scope.required || false;
var scopes = scope ? scope.split(',') : [];

function validateIndividualScope(item) {
if (allowedScopes[0].trim() === '*') {
return;
}
if (allowedScopes.indexOf(item) === -1) {
error('"%s" is not an allowed scope ! Valid scope are: %s', item, allowedScopes.join(', '));
isValid = false;
}
}

if (validateScopes) {
if (scopeRequired && scopes.length === 0) {
error('a scope is required !');
isValid = false;
}
if (isValid && multipleScopesAllowed) {
scopes.forEach(validateIndividualScope);
}
if (isValid && !multipleScopesAllowed) {
if (scopes.length > 1) {
error('only one scope can be provided !');
isValid = false;
}
if (isValid) {
validateIndividualScope(scopes[0]);
}
}
}

return isValid;
};
75 changes: 75 additions & 0 deletions test/validateMessage.test.js
Expand Up @@ -157,6 +157,81 @@ describe('validate-commit-msg.js', function() {
expect(logs).to.deep.equal([msg]);
});

it('should require a scope', function() {
var msg = 'feat: Add new feature';

m.config.scope = {
validate: true,
allowed: '*',
required: true
};

expect(m.validateMessage(msg)).to.equal(INVALID);
expect(errors[0]).to.equal('INVALID COMMIT MSG: a scope is required !');
expect(logs).to.deep.equal([msg]);

m.config.scope = undefined;
});

it('should validate scope', function() {
var msg = 'feat(nonexistant): Add new feature';

m.config.scope = {
validate: true,
allowed: ['button', 'card']
};

expect(m.validateMessage(msg)).to.equal(INVALID);
expect(errors[0]).to.equal('INVALID COMMIT MSG: "nonexistant" is not an allowed scope ! Valid scope are: ' + m.config.scope.allowed.join(', '));
expect(logs).to.deep.equal([msg]);

m.config.scope = undefined;
});

it('should only allow a single scope when multiples is off', function() {
var msg = 'feat(button,card): Add new feature';

m.config.scope = {
validate: true,
allowed: '*'
};

expect(m.validateMessage(msg)).to.equal(INVALID);
expect(errors[0]).to.equal('INVALID COMMIT MSG: only one scope can be provided !');
expect(logs).to.deep.equal([msg]);

m.config.scope = undefined;
});

it('should catch an invalid scope among many', function() {
var msg = 'feat(button,card,ripple): Add new feature';

m.config.scope = {
validate: true,
allowed: ['button', 'card'],
multiple: true
};

expect(m.validateMessage(msg)).to.equal(INVALID);
expect(errors[0]).to.equal('INVALID COMMIT MSG: "ripple" is not an allowed scope ! Valid scope are: ' + m.config.scope.allowed.join(', '));
expect(logs).to.deep.equal([msg]);

m.config.scope = undefined;
});

it('should allow any scope if "*" is defined', function() {
var msg = 'feat(anything): Fixed';

m.config.scope = {
validate: true
};

expect(m.validateMessage(msg)).to.equal(VALID);
expect(logs).to.deep.equal([]);

m.config.scope = undefined;
});

it('should allow empty scope', function() {
expect(m.validateMessage('fix: blablabla')).to.equal(VALID);
expect(errors).to.deep.equal([]);
Expand Down

0 comments on commit 815bc77

Please sign in to comment.