How to publish an NPM package from the CI build pipeline and still automate versioning?

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.


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

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:

  • if the changes are breaking changes (non-backwords compatiable), the maintainer will bump the major version
  • if the changes are new features (helper functions, refactoring, etc.), the maintainer will bump the minor version

there are many approches for the patch version. here are 2:

  1. git pre-push hook, which bumps the patch number and commit it to the repository, which eliminates the build\ci system changing the project source code
  2. use the build number in the build\ci system as the patch number, ignoring the patch version commited to the repository