1

I am struggling a bit with setting a workflow for our npm repo publish and git work flow. I have implemented a solution as follows and I am not satisfied with it.

Developer --> ready to push to git --> npm version (i have a script that updates README.md with the changelog -- using sinopia which does not support changelog) --> commit and push --> accept and merge --> git ci pipeline --> builds, tests and publishes to npm repo.

The nit that I have is that if the developer forgets to version the repo then the pipeline fails. I can probably create a staging area in my git pipeline that will contain an updated README and version the repo as part of the git CI. But that does not feel right for several reasons. Mainly I would rather not pollute the GIT with dynamic changes to the source files.

So, to summarize. Is there a better way? Ideally, I would like to version the repo when the changes are ready to be accepted in GIT. But I am not sure how. BTW we are using gitlab.

1
  • Perhaps adding a prepublish script that will version the repo, but then the package.json will reflect the change and that needs to be commited to GIt. It looks like a chicken and egg to me. Any help would be appreciated Commented May 10, 2017 at 14:24

2 Answers 2

1

You can use pre-commit hook to update the file’s version automatically (assume the file is package.json).

pre-commit hook will execute before commit changes, so you can get current version by shell script, and then use the increment version to replace current version. And then git commit will also commit package.json with new version.

Assume package.json file's format as below (version is in third line):

{
    "name": "Hello World",
    "version": 0.0.1,

And the version format is major.minor.patch. the bigest value for minor and patch versions are 9 (you can specify other values). The shell script to automatically increase version number as below:

#!/bin/sh

if [ -n "$(git status --porcelain)" ]; then 
  echo "there has uncommited changes"; 
else 
{
  echo "no changes to commit!";
  exit
}
fi

line=$(sed '3!d' package.json)
IFS=: read -r var1 var2 <<< "$line"
v=$(echo "$var2" | tr -d '"')
version=$(echo "$v" | tr -d ',')
IFS=. read -r major minor patch <<< "$version"

if  [ $patch != 9 ]
then 
  patch=$((patch+1))
elif [ $minor != 9 ]
then
{
  minor=$((minor+1))
  patch=0
}
else
{
  major=$((major+1))
  minor=0
  patch=0
}
fi

newversion=$major"."$minor"."$patch
echo  "The new version is $newversion"

placestr=$(echo $var1: \"$newversion\",)
sed -i "s/${line}/${placestr}/" package.json
git add package.json
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Marina. I am not clear about the "increment version replacing the current version" - what do you mean? I tested the pre-commit and added a script to parse and update the version in package.json. All works fine until the commit happens. Then the commit only adds what was in the staged area before changes. i.e. if at the point i start git commit -a ..... and version is 1.0.0 - then that commits. after pre-commit the version is 1.0.1 - this is not committed. For that I have to do yet another commit. So I can never catch up. Can you elaborate?
I added detail script in my answer, please have a try.
Thanks!. The last command was what I was missing. I am posting my version of the script here.
0

const fs = require('fs');
const path = require('path');
let execSync = require('child_process').execSync;


let streamToString = (stream, callback) => {
  let str = '';
  stream.on('data', function(chunk) {
    str += chunk;
  });
  stream.on('end', function() {
    callback(str);
  });
};

const run = cmd => {
  return execSync(cmd, function(error, stdout) {

    streamToString(stdout, (data) => {
      console.log('Data ---- ', data);
      return data;
    });
  });
};

const packagejson = fs.readFileSync(
  path.join(__dirname, '..', 'package.json'), 'utf8');

run("cp package.json package.json.bkp");
const json = JSON.parse(packagejson);


// Update package.json

let semver = json.version.split('.');

semver[2] = Number(semver[2]) + 1;

let replacer = /,/gi;
json.version = semver.toString().replace(replacer, '.');

let changelog = {};

changelog.version = json.version;
changelog.author = run('npm config get init.author.name');

fs.writeFileSync(path.join(__dirname, '..', 'package.json'), JSON.stringify(json, null, 2));

if (changelog.author.byteLength <= 1) {
  throw Error('init.author.name is a required npm configuration attribute......');
}
run('cp README.md README.bkp');

const readme = fs.readFileSync(
  path.join(__dirname, '..', 'README.md'), 'utf8');

let header = readme.split('-----------');

console.log('Header ......... ', header);

fs.writeFileSync(
  path.join(__dirname, '..', 'README.md'), header[0] + '-----------' +
  '\r\nVersion ' + changelog.version + '\r\n' + 'Changed By ' + changelog.author + '\r\n' +
  'Change Date ' + new Date(), 'utf8'
);

run('git add package.json');
run('git add README.md');

1 Comment

I have to enhance the semver like you have.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.