Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
611 views
Welcome To Ask or Share your Answers For Others

1 Answer

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...