Gitlab CI/CD for npm packages

Gitlab CI/CD for npm packages:

 First of all in your package.json you should scope your project cause Gitlab requires packages to be scoped.

For example:

{
"name": "@scope/example-package-name",
"version": "1.0.0"
}

After we have this setup, if we use a .npmrc file or npm config set registry we can tell npm where we want it to publish our package. Looks something like this:

//gitlab.example.com/api/v4/projects/${PROJECT_ID}/packages/npm/:_authToken=${GITLAB_DEPLOY_TOKEN}

If the repository is set to internal or private you need to use a Gitlab deploy token. On how to get one, you can read at Deploy tokens documentation.

After running npm publish you should be able to see your package in the registry of your repository.

Gitlab registry

And you should be able to see a version 1.0.0 that says it was pushed manually.

CI/CD

To make our life and the life of our colleagues better we can make good use of the gitlabs CI/CD system here.
We can use .gitlab-ci.yml configuration that looks like this:

stages:
  - build
  - test
  - publish

build:
  stage: build
  only:
    - tags
  cache:
    key: build-cache
    paths:
      - node_modules/
      - lib/
      - .npmrc
    policy: push
  script:
    - echo "//gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm install
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm run build
test:
  stage: test
  only:
    - tags
  cache:
    key: build-cache
    paths:
      - node_modules/
      - lib/
      - .npmrc
    policy: pull
  script:
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm run test
lint:
  stage: test
  only:
    - tags
  cache:
    key: build-cache
    paths:
      - node_modules/
      - lib/
      - .npmrc
    policy: pull
  script:
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm run lint

publish:
  stage: publish
  only:
    - tags
  cache:
    key: build-cache
    paths:
      - node_modules/
      - lib/
      - .npmrc
    policy: pull
  script:
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm version --no-git-tag-version ${CI_COMMIT_TAG}
    - docker run -v $(pwd):/app -v /home:/home -w="/app" -u="$(id -u):$(id -g)" -e HOME node:14 npm publish

Notable points:

  • In build stage we make a .npmrc file that contains the path of the registry made by using the CI environment variables
  • All the stages run only on tags, a special way to tell the CI/CD system to only activate when you tag the code in your repository
  • We build a cache for node_modules, lib and .npmrc as such we limit the number of scripts we need to run after the build step
  • Only the build step makes the cache others only use it, it is defined by push/pull policy
  • In publish stage we use a npm version --no-git-tag-version ${CI_COMMIT_TAG} command. npm version is a noisy command that tags and commits code if it detects a directory being a git repository so that’s why we use --no-git-tag-version here. As the stage was triggered by us tagging the code, we have the ${CI_COMMIT_TAG} environment variable available to use for package versioning. After that we just publish the package.

Note
I didn’t have a gitlab runner that was setup to use docker normally nor did I have node and npm installed on the machine so I had to use docker run commands like shown. So… not the most elegant way of doing it.

The end result is this:

Pipeline

Now the developers don’t have to run any scripts locally, just to commit to the repository and tag the code.

from Tumblr https://generouspiratequeen.tumblr.com/post/657407840224493568

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s