Automate Git commit + versioning + tag by npm node
Ok guys, I got it! What I was looking for is to run a simple command and automate some boring tasks we have to do always in the same order for Git.
So, What I do here is, first I run this command:
$> npm run commit -- 'v.1.0.1: Fixes'
What it happens is that I firstly clean of folders/files and I dont need/want, then I run:
$> npm version patch -no-git-tag-version --force
That command increase my package.json version, not commit & not tag, So Then I add all changes as normal, then I commit my changes and after this, I create the tag with the tag:commit gulp task.
In the gulp task (attached bellow), I am getting the version of the package with require and treat it as a object.
"scripts": {
"start": "gulp start",
"initialize": "npm install & typings install",
"clean": "gulp clean:folders",
"commit:example": "echo 'npm run commit -- 'v.1.0.1: Fixes'",
"commit:patch": "npm version patch --no-git-tag-version --force",
"commit:minor": "npm version minor --no-git-tag-version --force",
"commit:major": "npm version major --no-git-tag-version --force",
"precommit": "npm run clean && npm run commit:patch && git add --all",
"postcommit": "gulp tag:commit && git push origin master && git status && gulp commit:done",
"commit": "git commit -m "
},
and then, I have this in my gulp file:
///// ***** GIT ***** /////
gulp.task('tag:commit', function () {
var version = pjson.version;
console.log(colors.bgWhite.black.bold(' \nTagging the version ' + version + ' \n'));
return run('git tag ' + version).exec();
});
I didn't want to use gulp-git as I knew there was a way to do that, If I need to merge, create brunch or whatever, I will run the console and fix it, but for daily commits, it's painful to remember to tag, update the package version, put it in the git commit....
I hope that's useful for someone else!
Cheers,
How about just one npm script called commit
added to the package.json :
"scripts": {
...
"commit": "node commit"
...
},
Used like so:
$> npm run commit patch "Your commit message goes here"
Where patch
can be replaced by minor
or major
, depending on what version bump you want/need.
The ./commit.js
script content looks like this:
#!/usr/bin/env node
'use strict';
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const spawn = require('child_process').spawnSync;
async function version(versionType) {
const { stdout, stderr } = await exec(`npm version ${versionType} --no-git-tag-version --force`);
if (stderr) throw stderr;
return stdout;
}
async function branch() {
const { stdout, stderr } = await exec(`git rev-parse --abbrev-ref HEAD`);
if (stderr) throw stderr;
return stdout;
}
const run = async () => {
try {
const versionType = process.argv[2];
const gitMessage = process.argv[3];
if (versionType !== 'patch' && versionType !== 'minor' && versionType !== 'major') throw new Error('You need to specify npm version! [patch|minor|major]');
if (!gitMessage) throw new Error('You need to provide a git commit message!');
const npmVersion = await version(versionType);
await spawn('git', ['add', 'package.json', 'package-lock.json'], { stdio: 'inherit' });
await spawn('git', ['commit', '-m', gitMessage.trim()], { stdio: 'inherit' });
await spawn('git', ['tag', npmVersion.trim()], { stdio: 'inherit' });
await spawn('git', ['status'], { stdio: 'inherit' });
const currentBranch = await branch();
await spawn('git', ['push', 'origin', currentBranch.trim()], { stdio: 'inherit' });
} catch (err) {
console.log('Something went wrong:');
console.error(err.message);
console.error('\nPlease use this format: \nnpm run commit [patch|minor|major] "Commit message"');
}
};
run();
Please note that I didn't add git add --all
since I prefer to be more selective with my commits, however the format of this script should be easy enough for anyone to grok and expand upon. Alas I do have git add package.json
so each execution of this script will bump the version of the package.json
/package-lock.json
and commit these files at minimum. My strategy would be to perform git add
prior executing the higher mentioned command.
Another thing to consider here is that this script is fully compatible with husky hooks
, specifically pre-commit
which in my case drives lint-staged
coupled to eslint
and prettier
. This way everything is nicely automated, slim, and standardized.
I hope this helps someone, Cheers!