2

In an NPM project, I'd like to have a commit for each build version. This will allow me to go back to the current build version, fix a bug, without having to go through all the QA of a new version.

We can commit using npm scripts like this (see this answer):

package.json

"scripts": {
  "git": "git add . && git commit -m",
}

Then invoke the script by running:

npm run git -- "Message of the commit"

I'd like to automate it to run after npm run build. For this purpose we can create a new command.

package.json

"scripts": {
  "buildAndCommit": "npm run build && git add . && git commit -m",
}

This could be run using npm run buildAndCommit -- "commit for a new build"

The only thing left is that I'd like to identify this commit as one that could be linked to a commit. Is it possible to start the message automatically with "BUILD -" and to add to that the unique message which is passed in the command line? Something like:

package.json

"scripts": {
  "buildAndCommit": "npm run build && git add . && git commit -'Build' + $uniqueMessageFromTheCommandLine`",
}

If it is not possible to template the string in package.json, how could I achieve it using a command line script? (Powershell is my command line tool).

5
  • Using Powershell it's probably simpler to run npm run buildAndCommit -- "BUILD - commit for a new build", i.e. include the BUILD - prefix. However running on *nix the solution if fairly trivial.
    – RobC
    Commented Apr 3, 2019 at 12:30
  • Out of interest, why do you not want to include the BUILD - part in the argument passed to npm run buildAndCommit ?
    – RobC
    Commented Apr 3, 2019 at 12:34
  • @RobC, thanks! This is really helpful. The idea behind this is that the build process is separate from the Version control process. Every new version requires some QA. I try to create new features in a separate branch. But sometimes I do change the code on the master branch. Than, If an immediate patch is required to the live version, which can't wait till the next version is released. I'd like to return to the stable build, which was tested, and just change the necessary. Makes snese?
    – Ben Carp
    Commented Apr 3, 2019 at 12:43
  • So, is the BUILD - prefix a way to identify the last stable build which was tested ?
    – RobC
    Commented Apr 3, 2019 at 12:50
  • @RobC, yes. Obviously testing comes after the build, so "BUILD" by itself doesn't mean that I can identify it as a tested version. But I can still distinguish it from other commits, and hopefully it can bring me very close to the specific commit I am looking for.
    – Ben Carp
    Commented Apr 3, 2019 at 13:42

1 Answer 1

13

Running on *nix platforms

On a *nix platform npm utilizes sh by default to execute the npm script(s). In this scenario you can simply use a shell function and reference the git message argument passed via the CLI using the $1 positional parameter.

Your npm script would be redefined like this:

"scripts": {
  "build": "...",
  "buildAndCommit": "func() { npm run build && git add . && git commit -m \"BUILD - $1\"; }; func"
}

Cross platform

Unfortunately, via Windows Powershell the solution is not quite as simple and terse.

When using Powershell npm utilizes cmd by default to execute npm script(s). Likewise npm utilizes cmd by default via other Windows consoles too, such as Command Prompt.

One way to achieve your requirement is to invoke a node.js via your npm script. The following provides two different methods that are essentially the same. Either will run successfully cross-platform (in your case via Powershell).

Method A - Using a separate node.js script

  1. Create the following node.js script. Let's name the file script.js and save it in the root of the project directory, i.e. in the same directory where package.json resides.

    script.js

    const execSync = require('child_process').execSync;
    const mssg = 'BUILD - ' + process.argv[2];
    execSync('npm run build && git add . && git commit -m \"' + mssg + '\"', { stdio:[0, 1, 2] });
    

    Explanation

    • The node.js builtin process.argv captures the argument at index two, i.e. the git commit message, that was provided via the CLI. The git commit message is concatenated with with the substring BUILD - to form the desired commit message. The resultant string is assigned to the variable mssg.

    • We then utilize the node.js builtin execSync() to execute your given npm script. As you can see, the value of the mssg variable is used as the git commit message.

    • The stdio option is utilized to ensure the correct configuration of the pipes, i.e. stdin, stdout, 'stderr', are established between the parent and child process.

  2. Define your npm script named buildAndCommit as follows:

    package.json

    "scripts": {
      "build": "...",
      "buildAndCommit": "node script"
    }
    

    Above node invokes script.js.

Method B - Inline the node.js script in npm script

Alternatively, the aforementioned node.js script (i.e. script.js) can be provided inline in your npm script instead - therefore negating the use of a separate .js file.

package.json

"scripts": {
  "build": "...",
  "buildAndCommit": "node -e \"const mssg = 'BUILD - ' + process.argv[1]; require('child_process').execSync('npm run build && git add . && git commit -m \\\"' + mssg + '\\\"', { stdio:[0, 1, 2] })\""
}

This utilizes the same code from Method A albeit it slightly refactored. The notable differences are:

  • The nodejs command line option -e is utilized to evaluate the inline JavaScript.
  • process.argv this time will capture the argument, i.e. the git commit message, at index one in the array of arguments.
  • Additional escaping of the double quotes is necessary, i.e. \\\"

Running the npm script

Using either Method A or Method B run the command via your CLI as desired: For instance:

$ npm run buildAndCommit -- "commit for a new build"

This will produce the following git commit message:

BUILD - commit for a new build

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.