Reputation: 535
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.
Upvotes: 1
Views: 619
Reputation: 535
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');
Upvotes: 0
Reputation: 38106
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
Upvotes: 1