-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: validate commit messages (#4903)
- Loading branch information
Showing
5 changed files
with
156 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
require('../lib/bootstrap-local'); | ||
|
||
const validateCommitMessage = require('./validate-commit-message'); | ||
const exec = require('child_process').exec; | ||
const chalk = require('chalk'); | ||
const Logger = require('@ngtools/logger').Logger; | ||
require('rxjs/add/operator/filter'); | ||
|
||
// Configure logger | ||
const logger = new Logger('test-commit-messages'); | ||
|
||
logger.subscribe((entry) => { | ||
let color = chalk.white; | ||
let output = process.stdout; | ||
switch (entry.level) { | ||
case 'info': color = chalk.white; break; | ||
case 'warn': color = chalk.yellow; break; | ||
case 'error': color = chalk.red; output = process.stderr; break; | ||
case 'fatal': color = (x) => chalk.bold(chalk.red(x)); output = process.stderr; break; | ||
} | ||
|
||
output.write(color(entry.message) + '\n'); | ||
}); | ||
|
||
logger | ||
.filter((entry) => entry.level == 'fatal') | ||
.subscribe(() => { | ||
process.stderr.write('A fatal error happened. See details above.'); | ||
process.exit(1); | ||
}); | ||
|
||
// Note: This is based on the gulp task found in the angular/angular repository | ||
|
||
exec( | ||
'git fetch origin master && git log --reverse --format=%s origin/master.. --no-merges', | ||
(error, stdout, stderr) => { | ||
if (error) { | ||
logger.fatal(stderr); | ||
return; | ||
} | ||
|
||
const output = stdout.trim(); | ||
if (output.length == 0) { | ||
logger.warn('There are zero new commits between this HEAD and master'); | ||
return; | ||
} | ||
|
||
const commitsByLine = output.split(/\n/); | ||
|
||
logger.info(`Examining ${commitsByLine.length} commit(s) between HEAD and master`); | ||
|
||
const someCommitsInvalid = !commitsByLine.every(validateCommitMessage); | ||
|
||
if (someCommitsInvalid) { | ||
logger.error('Please fix the failing commit messages before continuing...'); | ||
logger.fatal( | ||
'Commit message guidelines: https://github.com/angular/angular-cli/blob/master/CONTRIBUTING.md#commit'); | ||
} else { | ||
logger.info('All commit messages are valid.'); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"maxLength": 100, | ||
"types": [ | ||
"build", | ||
"ci", | ||
"docs", | ||
"feat", | ||
"fix", | ||
"perf", | ||
"refactor", | ||
"style", | ||
"test" | ||
], | ||
"scopes": [ | ||
"@angular/cli", | ||
"@ngtools/json-schema", | ||
"@ngtools/logger", | ||
"@ngtools/webpack", | ||
|
||
"packaging", | ||
"changelog" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
module.exports = require('./validate-commit-message'); |
61 changes: 61 additions & 0 deletions
61
scripts/validate-commit-message/validate-commit-message.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#!/usr/bin/env node | ||
|
||
/** | ||
* @license | ||
* Copyright Google Inc. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
/** | ||
* GIT commit message format enforcement | ||
* | ||
* Note: this script was originally written by Vojta for AngularJS :-) | ||
*/ | ||
|
||
/* eslint-disable no-console */ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
const configPath = path.resolve(__dirname, './commit-message.json'); | ||
const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); | ||
const PATTERN = /^(revert\: )?(\w+)(?:\(([^)]+)\))?\: (.+)$/; | ||
|
||
module.exports = function(commitSubject) { | ||
if (commitSubject.length > config['maxLength']) { | ||
error(`The commit message is longer than ${config['maxLength']} characters`, commitSubject); | ||
return false; | ||
} | ||
|
||
const match = PATTERN.exec(commitSubject); | ||
if (!match || match[2] === 'revert') { | ||
error( | ||
'The commit message does not match the format of "<type>(<scope>): <subject> OR revert: type(<scope>): <subject>"', | ||
commitSubject); | ||
return false; | ||
} | ||
|
||
const type = match[2]; | ||
if (config['types'].indexOf(type) === -1) { | ||
error( | ||
`${type} is not an allowed type.\n => TYPES: ${config['types'].join(', ')}`, commitSubject); | ||
return false; | ||
} | ||
|
||
const scope = match[3]; | ||
|
||
if (scope && !config['scopes'].includes(scope)) { | ||
error( | ||
`"${scope}" is not an allowed scope.\n => SCOPES: ${config['scopes'].join(', ')}`, | ||
commitSubject); | ||
return false; | ||
} | ||
|
||
return true; | ||
}; | ||
|
||
function error(errorMessage, commitMessage) { | ||
console.error(`INVALID COMMIT MSG: "${commitMessage}"\n => ERROR: ${errorMessage}`); | ||
} |