Reputation: 10701
I can't seem to see the forest behind the trees. I want to have a simple CI pipeline that builds and publishes an NPM package. I use appveyor, but I don't think my issue is specific to it. I simply want my CI script to be performing something like this:
git clone "https://git_repo_url" .
npm run build
npm run test
npm version patch --git-tag-version
npm publish -tag beta
The problem is:
If I don't do the npm version patch
step, the publishing will fail with the feed already contains the package 'abc' at version 'x.y.z'
error.
If I do that step, then I'd have to push the new commit (the version change) back to the git repo. Otherwise, it will fail as above next time me or someone else build it. Yet I don't feel like doing git push
in the back-end pipeline would be the right thing.
Lastly, if this CI script just builds the NPM package without publishing it, how do I consume it in other projects which are depending on it?
What are the industry standard ways of doing this?
For instance, if I need to test a non-production feature version of my package with another project, should I make my CI script to patch the package's package.json
with a generated, unique semver-compatible version (without commiting it), and then publish it with an npm
tag that would match my git branch name? Is it a good idea?
Upvotes: 19
Views: 15916
Reputation: 10102
I'd still be very interested to learn about the best DevOps practices to publish internal/per-release NPM packages with CI during normal development cycle.
usually the maintainer of the project bumps the version, based on the features and\or changes made to the project.
for instance:
there are many approaches for the patch version. here are 2:
Upvotes: 4
Reputation: 639
I did it as below, in my javascript project.
Note: get your key form .npmrc
publish:
image: <your project image>
stage: publish
script:
- echo _auth=$NPM_PUBLSH_KEY >> .npmrc
- echo email=<youremail> >> .npmrc
- echo always-auth=true >> .npmrc
# - cat .npmrc
- npm version --no-git-tag-version $(npm view <yourProject>@latest version)
- npm version --no-git-tag-version prerelease
- npm publish
dependencies:
- build
build:
image: <your project image>
stage: build
script:
- node --version
- npm --version
- npm ci
- npm run build -- --watch=false
- npm run build:prod
Upvotes: 19
Reputation: 10701
Answering myself. As suggested in the comment above, I've decided to adopt semantic-release
for publishing from master
branch.
For building and publishing from development branches, I've created a custom node script to generate a semver-compatible pre-release version based on git commit's hash, current major.minor.patch version and current time:
const cp = require('child_process');
// get current semver version without prerelease suffix
const pkg = require('./package.json');
const curVer = pkg.version.trim().split(/[.-]/).slice(0, 3).join('.');
// get the commit id
const commit = cp.execSync('git rev-parse --short HEAD', {encoding: 'utf-8'}).trim();
console.log(`Package: ${pkg.name}, version: ${curVer}, commit: ${commit}`);
// generate a new unique semver-compliant version based the commit it and current time
const uniqueVer = `${curVer}-beta-${commit}-${Math.random().toFixed(8).substr(2)}.${Date.now()}`
// use npm version to update package.json
cp.execSync(`npm version ${uniqueVer} --no-git-tag-version`, {stdio: 'inherit'});
// publish and tag with commit id
cp.execSync(`npm publish --tag ${commit}`, {stdio: 'inherit'});
This way, I can check-in my stuff into my dev branch, have the CI pipeline build and publish the package for me and then consume it with npm install mypackage@commitid
. A pseudo-unique version will be generated and published to NPM registry, but the modded package.json
will not be checked-in.
This approach should work for me for now, but I'd still be very interested to learn about the best DevOps practices to publish internal/per-release NPM packages with CI during normal development cycle.
Upvotes: 9