Jump to navigation Jump to search

Feature Releases using GitLab CI - Practical Approach

We need to split our continuously growing monolithic application into modules (we call them features) with an independent release cycle. A strategy and technical approach is required -- also it should be simple, because we all have enough other problems ;-)

Why GitLab CI?
I like the flexibility and easiness of GitLab CI/CD. Last years we used Jenkins, but I see GitLab CI as the next-generation tooling.
The biggest change is the deep integration into the Git project, which includes a drastical change in responsibilities, enabling a "DevOps" culture.
Azure Team Foundation Service my be another alternative -- but a MSDN subscription must be purchased for each developer and stakeholder.

A general option is to have separate GitLab projects for each feature, having project specific CI/CD pipeline. This is the micro services way of doing it. Micro services are per definitionem fairly independent. The development team triggers the pipeline at any time, to initiate builds, tests and deployments.

For our infrastructure (may be also yours) a common challenge are the feature dependencies. BTW: This is not always a problem of the kind: "If you would understand micro services, you won't have these dependencies!"

Anyway, we need versions for features and maintain dependencies somehow. Git tags does not help much from my experience. Even deployments must be managed in so called feature trains.

I really like the easiness of NPM dependency management and considering some options how to manage the functional dependencies lead the the reuse of npm. So NPM requires node.js to run, but a package itself does not need to be a node.js library.

Basic Idea

  1. features live in separate Git projects and are npm modules by having a package.json
  2. features are published as packages into a local private npm repository using GitLab CI
  3. a central infrastructure management (Git project) deploy dedicated packages as feature trains using GitLab CI calling npm

GitLab FunctionRelease with NPM.png

Set Up

I assume, that you have already GitLab installation. Also at least one GitLab runner set up is required. The runner must be able to execute npm, so node.js must be installed in the runners environment.

Easiest way is to install GitLab, a GitLab "shell runner" and node.js on one VM (or server) -- if you just do an evaluation of this approach.

Please check out, how I did my GitLab CE set up

Additionally you need to enable the runner to use npm:

sudo su gitlab-runner 
npm set registry http://<dockerhost>:4873
npm adduser 

Private NPM Repository

Set up instructions:

Feature Projects

Each feature project need:

  1. a package.json to make it a NPM package
  2. a CI flow to build, test and most important, to publish the package

Feature versioning is done via the package.json and not using Git tags.

Example package.json:

  "name": "my-awsome-feature",
  "version": "1.0.0",
  "scripts": {
    "install": ""

Example .gitlab-ci.yml:

  #- test
  #- build
  - publish
  stage: publish
    - npm publish
    - nodejsrunner

PS: Don't forget to assign the runner for this project in the GtiLab admin area

My sample project has an index.js and a Dockerfile to build and run a container.

GitLab FeaturePrj.png

After the CI run, the project is in the NPM repo:


Managing and Deploying Feature Trains

This is a separate GitLab project, containing:

  1. a package.json defining the feature train in the dependencies
  2. a CI flow to deploy the feature train

The feature train itself has also a version, defined in the package.json.

Example package.json:

  "name": "application-infrastructure",
  "version": "1.0.0",
  "dependencies": {
    "my-awsome-feature": "^1.0.0",

Example .gitlab-ci.yml:

  #- test
  - deploy
  stage: deploy
    - npm install
    - nodejsrunner

Again: Don't forget to assign the runner for this project in the GtiLab admin area

This CI flow will pull "my-awsome-feature" from the NPM repo and store it on the local node_modules sub folder. After that the install script defined in my-awsome-feature/package.json will we called to install the feature.

GitLab FeatureTrain.png

Realistic CI/CD Flow

Function release CI flow:

  1. run unit tests
  2. build Docker container into GitLab docker registry
  3. deploy container into test env
  4. run end-to-end tests

Release train CD flow:

  1. Pre-installation steps (e.g. database backup, stop message processing, ...)
  2. replace production docker containers: script provided by functions, triggered by "npm install" script
  3. Post-installation steps (populate data, restart processing)

Further Options

  1. define staging using "environment" defined in the CI flow
  2. manual approval, use "when: manual"