avo
avo

Reputation: 10701

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

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:

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

Answers (3)

Mr.
Mr.

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:

  • if the changes are breaking changes (non-backwards compatible), 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 approaches 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 committed to the repository
  3. use conventional commits and leverage semantic-release to manage semantic versioning

Upvotes: 4

Akshay
Akshay

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

avo
avo

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

Related Questions