mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-10-27 01:53:45 +00:00
Compare commits
3 Commits
security-f
...
git-linter
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e3cfbd887 | ||
|
|
720f42ca80 | ||
|
|
e18ba5dab6 |
@@ -28,7 +28,13 @@ cache:
|
|||||||
- app/node_modules
|
- app/node_modules
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run travis
|
- echo $TRAVIS_COMMIT_RANGE
|
||||||
|
- echo ${TRAVIS_COMMIT_RANGE/.../..}
|
||||||
|
- echo "test"
|
||||||
|
- git log -4
|
||||||
|
- node ./tools/gitlint --ci-mode
|
||||||
|
- npm run travis
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
webhooks:
|
webhooks:
|
||||||
urls:
|
urls:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ os: Previous Visual Studio 2015
|
|||||||
|
|
||||||
cache:
|
cache:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Install-Product node 6 x64
|
- ps: Install-Product node 6 x64
|
||||||
- git reset --hard HEAD
|
- git reset --hard HEAD
|
||||||
@@ -20,5 +20,6 @@ install:
|
|||||||
build: off
|
build: off
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
|
- node ./tools/gitlint --ci-mode
|
||||||
- npm run test
|
- npm run test
|
||||||
- npm run test-e2e
|
- npm run test-e2e
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
"pack": "electron-builder --dir",
|
"pack": "electron-builder --dir",
|
||||||
"dist": "electron-builder",
|
"dist": "electron-builder",
|
||||||
"mas": "electron-builder --mac mas",
|
"mas": "electron-builder --mac mas",
|
||||||
|
"setup-gitlint-hooks": "node ./tools/gitlint/setup-gitlint-hook",
|
||||||
|
"lint-commits": "node ./tools/gitlint --all-commits",
|
||||||
"travis": "cd ./scripts && ./travis-build-test.sh"
|
"travis": "cd ./scripts && ./travis-build-test.sh"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
@@ -107,6 +109,7 @@
|
|||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"assert": "1.4.1",
|
"assert": "1.4.1",
|
||||||
|
"chalk": "^2.3.0",
|
||||||
"cp-file": "^5.0.0",
|
"cp-file": "^5.0.0",
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron": "1.7.10",
|
"electron": "1.7.10",
|
||||||
@@ -151,6 +154,12 @@
|
|||||||
"import/no-extraneous-dependencies": 0,
|
"import/no-extraneous-dependencies": 0,
|
||||||
"no-prototype-builtins": 0
|
"no-prototype-builtins": 0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": "scripts/gitlint/*.js",
|
||||||
|
"rules": {
|
||||||
|
"unicorn/no-process-exit": 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
|||||||
31
tools/gitlint/ci.js
Normal file
31
tools/gitlint/ci.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const {run} = require('./helpers');
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
if (process.argv.TRAVIS !== undefined) {
|
||||||
|
return travis();
|
||||||
|
}
|
||||||
|
|
||||||
|
return appveyor();
|
||||||
|
};
|
||||||
|
|
||||||
|
function travis() {
|
||||||
|
if (!process.env.TRAVIS_PULL_REQUEST) {
|
||||||
|
// Building against master last commit
|
||||||
|
return run('git log -1 HEAD');
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmd = `git log ${process.env.TRAVIS_COMMIT_RANGE}`;
|
||||||
|
const commitRange = run(`git diff --name-only ${process.env.TRAVIS_COMMIT_RANGE}`);
|
||||||
|
process.stdout.write(`COMMIT_RANGE: ${commitRange}`, 'utf8');
|
||||||
|
return run(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appveyor() {
|
||||||
|
if (!process.env.APPVEYOR_PULL_REQUEST_NUMBER) {
|
||||||
|
return run('git log -1 HEAD');
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmd =
|
||||||
|
`git log origin/master...${process.env.APPVEYOR_PULL_REQUEST_HEAD_COMMIT}`;
|
||||||
|
return run(cmd);
|
||||||
|
}
|
||||||
91
tools/gitlint/helpers.js
Normal file
91
tools/gitlint/helpers.js
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
const {spawnSync} = require('child_process');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
|
||||||
|
const commitMsgRegex = /[A-Z]+.*\.$/;
|
||||||
|
const isFullCommitRegex = /(\w|\W){1,}:\s{1}/;
|
||||||
|
const fullCommitRegex = /(\w|\W){1,}:\s{1}[A-Z]+.*\.$/;
|
||||||
|
|
||||||
|
function run(script) {
|
||||||
|
script = script.split(' ');
|
||||||
|
const cmd = script.splice(0, 1)[0];
|
||||||
|
const args = script;
|
||||||
|
const output = spawnSync(cmd, args, {
|
||||||
|
cwd: process.cwd(),
|
||||||
|
encoding: 'utf8',
|
||||||
|
windowsHide: true
|
||||||
|
}).stdout;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function garbageCollect(a) {
|
||||||
|
a.forEach((content, index) => {
|
||||||
|
if (content === '' || content === undefined) {
|
||||||
|
a.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAllCommits(output) {
|
||||||
|
output = output.split('\ncommits');
|
||||||
|
if (!output.length > 1) {
|
||||||
|
exports.error('There are no commits to lint.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
output = garbageCollect(output);
|
||||||
|
output.forEach((commit, index) => {
|
||||||
|
output[index] = 'commit' + commit;
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCommit(output) {
|
||||||
|
output = output.split('\n\n');
|
||||||
|
|
||||||
|
let commit = output[0].replace('commit ', '');
|
||||||
|
commit = commit.replace(/\n.*/g, '');
|
||||||
|
let commitHash = commit.split('');
|
||||||
|
commitHash = commitHash.slice(commitHash.length - 7);
|
||||||
|
commitHash = commitHash.join('');
|
||||||
|
|
||||||
|
const fullCommit = output[1].split('\n');
|
||||||
|
const commitMsg = fullCommit[0];
|
||||||
|
let lintingStatus = commitMsgRegex.test(commitMsg);
|
||||||
|
lintingStatus = (commitMsg.length <= 72);
|
||||||
|
|
||||||
|
if (lintingStatus && isFullCommitRegex(commitMsg)) {
|
||||||
|
lintingStatus = fullCommitRegex.test(commitMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
failed: !lintingStatus,
|
||||||
|
commitHash
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function logSuccess() {
|
||||||
|
console.log(chalk`{green commit linter:} commit linter passed.`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(...args) {
|
||||||
|
args.unshift(chalk.red('ERROR! '));
|
||||||
|
console.error.apply(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function warn() {
|
||||||
|
// console.error(chalk`{yellow ${msg}}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
run,
|
||||||
|
getAllCommits,
|
||||||
|
parseCommit,
|
||||||
|
logSuccess,
|
||||||
|
error,
|
||||||
|
warn
|
||||||
|
};
|
||||||
44
tools/gitlint/index.js
Normal file
44
tools/gitlint/index.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
const helpers = require('./helpers');
|
||||||
|
const getCICmd = require('./ci');
|
||||||
|
|
||||||
|
let checkAllCommits = false;
|
||||||
|
let ciMode = false;
|
||||||
|
if (process.argv[2]) {
|
||||||
|
checkAllCommits = process.argv[2].includes('-a');
|
||||||
|
ciMode = process.argv[2] === '--ci-mode';
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd;
|
||||||
|
if (ciMode) {
|
||||||
|
cmd = getCICmd();
|
||||||
|
} else {
|
||||||
|
cmd =
|
||||||
|
checkAllCommits ? 'git log upstream/master...HEAD' : 'git log -1 HEAD';
|
||||||
|
}
|
||||||
|
|
||||||
|
const commits = helpers.run(cmd);
|
||||||
|
const commitsArray = helpers.getAllCommits(commits);
|
||||||
|
let lintFailed = false;
|
||||||
|
commitsArray.forEach(commit => {
|
||||||
|
const res = helpers.parseCommit(commit);
|
||||||
|
if (res.failed) {
|
||||||
|
const {commitHash} = res;
|
||||||
|
helpers.error(`commit ${commitHash} does not pass our commit style.`);
|
||||||
|
lintFailed = true;
|
||||||
|
} else {
|
||||||
|
helpers.logSuccess('Commit[s] follow the zulip-electron commit rules.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lintFailed) {
|
||||||
|
helpers.warn(`
|
||||||
|
commit msg linting failed
|
||||||
|
-------------------------------
|
||||||
|
Reasons it does not have:
|
||||||
|
a) capitial latter at start of message
|
||||||
|
b) period at the end of commit or
|
||||||
|
c) Commit msg length is more than 72 charaters
|
||||||
|
`);
|
||||||
|
helpers.warn('Run with --no-verify flag to skip the commit-linter');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
73
tools/gitlint/setup-gitlint-hook.js
Normal file
73
tools/gitlint/setup-gitlint-hook.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// This script sets up the pre-push
|
||||||
|
// git hook which will be used to lint
|
||||||
|
// commits
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const gitHooks = '../../.git/hooks';
|
||||||
|
const postCommitPath = path.resolve(__dirname, `${gitHooks}/post-commit`);
|
||||||
|
const prePushPath = path.resolve(__dirname, `${gitHooks}/pre-push`);
|
||||||
|
|
||||||
|
function scriptTemplate(cmds) {
|
||||||
|
cmds = cmds.join('');
|
||||||
|
const script = [
|
||||||
|
'#!/bin/sh',
|
||||||
|
'set -e',
|
||||||
|
'echo running gitlint...',
|
||||||
|
cmds,
|
||||||
|
'exit $?'
|
||||||
|
];
|
||||||
|
|
||||||
|
return script.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
const postCommitFile = scriptTemplate`node scripts/gitlint`;
|
||||||
|
const prePushFile = scriptTemplate`node scripts/gitlint --all-commits`;
|
||||||
|
|
||||||
|
function writeAndChmod(file, data) {
|
||||||
|
fs.writeFile(file, data, err => {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.chmod(file, '777', err => {
|
||||||
|
if (err) {
|
||||||
|
const msg =
|
||||||
|
'chmod post-commit, pre-push hooks, at .git/hooks 0777 so they work!';
|
||||||
|
console.error(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[postCommitPath, prePushPath].forEach((file, index) => {
|
||||||
|
fs.open(file, 'w+', err => {
|
||||||
|
if (err && err.code !== 'EEXIST') {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = index === 0 ? postCommitFile : prePushFile;
|
||||||
|
writeAndChmod(file, data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove .sample files since
|
||||||
|
// sometimes the hooks do not work
|
||||||
|
const postCommitSampleFile = `${postCommitPath}.sample`;
|
||||||
|
const prePushSampleFile = `${prePushPath}.sample`;
|
||||||
|
function removeSampleFile(file) {
|
||||||
|
fs.unlink(file, err => {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[postCommitSampleFile, prePushSampleFile].forEach(file => {
|
||||||
|
fs.exists(file, exists => {
|
||||||
|
if (exists) {
|
||||||
|
removeSampleFile(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user