Skip to content

Commit

Permalink
test: validate commit messages (#4903)
Browse files Browse the repository at this point in the history
  • Loading branch information
clydin authored and hansl committed Feb 22, 2017
1 parent b15d1f3 commit fd1296a
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 1 deletion.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
"build": "node ./scripts/publish/build.js",
"build:patch": "node ./scripts/patch.js",
"build:packages": "for PKG in packages/*; do echo Building $PKG...; tsc -p $PKG; done",
"test": "npm-run-all -c test:packages test:cli test:deps test:licenses",
"test": "npm-run-all -c test:packages test:cli test:deps test:licenses test:messages",
"e2e": "npm run test:e2e",
"e2e:nightly": "node tests/run_e2e.js --nightly",
"test:e2e": "node tests/run_e2e.js",
"test:cli": "node tests/runner",
"test:deps": "node scripts/publish/validate_dependencies.js",
"test:inspect": "node --inspect --debug-brk tests/runner",
"test:licenses": "node scripts/test-licenses.js",
"test:messages": "node scripts/test-commit-messages.js",
"test:packages": "node scripts/run-packages-spec.js",
"eslint": "eslint .",
"tslint": "tslint \"**/*.ts\" -c tslint.json -e \"**/config/schema.d.ts\" -e \"**/tests/**\" -e \"**/blueprints/*/files/**/*.ts\" -e \"node_modules/**\" -e \"tmp/**\" -e \"dist/**\"",
Expand Down
61 changes: 61 additions & 0 deletions scripts/test-commit-messages.js
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.');
}
});
23 changes: 23 additions & 0 deletions scripts/validate-commit-message/commit-message.json
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"
]
}
9 changes: 9 additions & 0 deletions scripts/validate-commit-message/index.js
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 scripts/validate-commit-message/validate-commit-message.js
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}`);
}

0 comments on commit fd1296a

Please sign in to comment.