Search code examples
node.jsdockerunit-testingkubernetescicd

How to automate CI/CD pipeline unit tests for a node.js container deployment in kubernetes


I am trying to automate unit testing before deploying a node.js container to a local kubernetes cluster. It is not clear to me whether or not I need to configure this in my deployment.yaml, Dockerfile, package.json, or some combination of them. And once configured how to instruct Kubernetes to output any failures and exit before deploying.

Do I need to do as this SO answer suggests and write a shell script and modify environment variables? Or, is this something I can automate with Kubernetes deployment.yaml

If it's useful, I am using mocha with chai. And this is being deployed from Google Cloud Source Repositories to a local Kubernetes instance.

Since I'm entirely new to Kubernetes, it would be great to have as much detail as possible.

Here is my deployment.yaml:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app-container
          image: my-app-image
          imagePullPolicy: IfNotPresent

Here is my Dockerfile:

# Use base node 18-alpine image from Docker hub
FROM node:18-alpine

WORKDIR /MY_APP

# Copy package.json and install dependencies
COPY package*.json ./
RUN npm install

# Copy rest of the application source code
COPY . .

# Run index.js
ENTRYPOINT ["node", "src/index.js"]

Here is my package.json:

  "scripts": {
    "start": "node src/index.js",
    "test": "npm install mocha -g && mocha --timeout 4000 --exit"
   }

And here is a basic unit test I'm using to experiment with:

import { expect } from 'chai'

describe('Basic unit test', ()=>{
    it('Checks if 3*3=9', () => {

        expect(3*3, 9)
    })
})

Solution

  • My issue was a misunderstanding about how the CI/CD pipeline works when it comes to tests.

    It goes like this: Commit > Build (dev) > Deploy (dev) > Run tests > (pass or fail) > (if pass) promote to production commit > ... deploy.

    If the dev deploy fails the tests, the code is never committed, therefore never moves forward in the pipeline.

    In my case, my package.json file needed this:

      "scripts": {
        "start": "node src/index.js",
        "test": "npm install mocha -g && mocha --timeout 4000 --exit",
        "build": "docker image build -f ./Dockerfile -t my_project:dev ."
      },
    

    My cloudbuild.json file needed this:

    - id: "Run unit tests"
      name: node
      entrypoint: npm
      args: ["test"]
    - id: "run"
      name: node
      entrypoint: npm
      args: ["start"]
    

    If the tests pass, the deploy proceeds, otherwise the build fails.