Automate Git commit + versioning + tag by npm node

12,224

Solution 1

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,

Solution 2

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!

Share:
12,224

Related videos on Youtube

Alejandro Lora
Author by

Alejandro Lora

Angular developer and Typescript enthusiast, passionate with Firebase and web technologies.

Updated on June 04, 2022

Comments

  • Alejandro Lora
    Alejandro Lora almost 2 years

    What I have been trying to get is, work with npm version to update the package.json and create a tag and then commit my changes. In this way, I will be able to have tags by version, auto versioning and commit with the info.

    The problem I am having is, when I am using npm version, it's doing a tag + commit automatically and then it can not be done if you have previously some changes, So for me, it doesn't make sense to increase the version of your project, before to do the changes/implementation/fixes.

    Then, another problem I was having is that I first increase the version as a 'patch', then I do some changes, I add all, I commit and then I publish, at the end, I have 2 commits, 1 because of the npm version patch, and the other one the good one.

    I saw in the documentation here that there is a parameter that allow you to disable this auto tag + commit, but then I would really like to use a command in the console to be able to update the package console and get that version set up as a tag.

    By another hand, not sure if this that I am saying it does make sense because as far as I know, when you create a tag, you can go back in your project to that point, So how I pretend to work like that if I am disabling the auto commit?

    Finally, What I want to make clear is my goal, What I really want to reach is handle by node scripts a semi-automated script to be able to increase the version of the project, create a tag with the new version, add all changes, commit and push.

    Note: I don't want to use gulp-git as I think there is a way to handle this without it.

    Not sure if I was clear enough, if not, please ask and help me :)

  • Hvaandres
    Hvaandres over 2 years
    I'm trying to use this, but it seems that I'm getting an undefined value: "npm run commit major "update" > [email protected] commit > node commit "major" "update" Something went wrong: undefined Please use this format: npm run commit [patch|minor|major] "Commit message""
  • Hvaandres
    Hvaandres over 2 years
    I'm currently trying to use this but it seems that I'm just getting an undefined value. Do we have to install any npm dependency or libary or what could be missing?
  • Bartekus
    Bartekus over 2 years
    Which node version are you using? As the script is using async/await, you'll need at least node v7.6 to use it
  • Hvaandres
    Hvaandres over 2 years
    I'm using node 14