Customer: Use Case (5: Implementing Simple Jenkins Continuous Integration)

amalja0

Amalia Hajarani

Posted on November 30, 2023

Customer: Use Case (5: Implementing Simple Jenkins Continuous Integration)

Prerequisites

  1. Installed Node version of: v20.10.0.
  2. Installed and configured Jenkins. If you want to know how, you can check my post on how to do it in How to: SonarQube Code Coverage in Jenkins with Maven Project, you can leave the steps related to the SonarQube.
  3. Empty Jenkinsfile (assuming you make the project skeleton as I did).

Before doing this tutorial

  1. Make sure you don't run any services (ExpressJS service, NestJS service, and Front-end service) on your local.

Configuring Jenkins for Node project

  1. To configure Jenkins for Node, go to your Jenkins UI. Mine is at http://localhost:8085.
  2. From Dashboard, go to Manage Jenkins which you can find on left navigation bar. Image description
  3. Choose Plugins. Image description
  4. Go to Available plugins section and type NodeJS Plugin. I've already installed the plugin, so I cannot show you the step, but this is the plugin: Image description
  5. Back to Manage Jenkins.
  6. Choose Tools. Image description
  7. Scroll until you see NodeJS installations. Don't mind the edited, because I already have configured mine. Image description
  8. Choose Add NojeJS. You can fill the field like mine. I preferred to use my locally installed Node instead of download it from Jenkins environment: Image description
  9. Click Save.
  10. (OPTOPNAL) Check if your NodeJS is correctly configured at Jenkins. Choose New Item located above Manage Jenkins. Image description
  11. Enter a name something like test-node-configuration. Choose Pipeline project. Then click OK. Image description
  12. In Pipeline section, add below script and click Save.

    pipeline {
        agent any
        tools {
            nodejs 'NodeJS'
        }
        stages {
            stage('Check NPM Version') {
                steps {
                    bat 'npm version'
                }
            }
        }
    }
    

    Image description

  13. You will get redirected into you newly created project. Click Build Now. Then you will see you project being built.
    Image description

  14. When it's done, click on #1.
    Image description

  15. Choose Console Output. And you will see some logs. If your Node configured correctly, you will see this on your console output:
    Image description

Upload .env files from every service to Jenkins

Since we are depending on .env file for every service, we need to upload it into Jenkins server.

  1. Go to Manage Jenkins.
  2. In Security section, choose Credentials. Image description
  3. Click System on Stores scoped to Jenkins section. Image description
  4. Choose Global credentials (unrestricted). Image description
  5. Click on Add Credentials.
    Image description

  6. Click dropdown in Kind section. Choose Secret File.
    Image description

  7. Click at Choose File (mine is Pilih File).
    Image description

  8. For first .env, choose from express-service.

  9. Give it some ID so you won't forget what this is .env for. Mine is: customer-express-env. Don't mind the warning, because I already have it configured.
    Image description

  10. Click Create.

  11. Do the same for .env in nest-service service and front-end-service. I ID'd the nest-service with customer-nest-env and for front-end-service I set the ID as customer-react-env.

Writing Jenkinsfile

This is actually very exciting for me because it is the first time I do CI with Jenkins by writing the Jenkinsfile first. I recommend you to write it in an IDE like Visual Studio Code, and if you use VS Code, I recommend you to install an extension called JenkinsFile Support.

Defining the pipeline

First we are going to create the Jenkinsfile pipeline.

pipeline{
}
Enter fullscreen mode Exit fullscreen mode

Defining agent

Since I don't know much about Jenkins, I define the agent as any.

agent any
Enter fullscreen mode Exit fullscreen mode

Defining secret environment

Since we need .env to run all service, we have to provide the credential IDs for all .env that we already upload on Jenkins Server.

environment {
    SECRET_FILE_EXPRESS = credentials("customer-express-env")
    SECRET_FILE_NEST = credentials("customer-nest-env")
    SECRET_FILE_REACT = credentials("customer-react-env")
}
Enter fullscreen mode Exit fullscreen mode

Defining tool

We have to define the tools to build the project. Which is NodeJS.

tools {
    nodejs "NodeJS" // change the NodeJS with the name you give when you configuring tools of NodeJS in Jenkins Server
}
Enter fullscreen mode Exit fullscreen mode

Defining stages

We are going to have few stages.

  1. Creating .env file for every services.

        stage("Create ExpressJs Service ENV"){
            steps{
              dir("express-service") {
                script {
                  withCredentials([file(credentialsId: "customer-express-env", variable: "SECRET_FILE_EXPRESS")]) {
                    writeFile file: '.env', text: readFile(file: "${SECRET_FILE_EXPRESS}")
                  }
                }
              }
            }
        }
        stage("Create NestJs Service ENV"){
          steps{
            dir("nest-service") {
              script {
                withCredentials([file(credentialsId: "customer-nest-env", variable: "SECRET_FILE_NEST")]) {
                  writeFile file: '.env', text: readFile(file: "${SECRET_FILE_NEST}")
                }
              }
            }
          }
        }
        stage("Create React Service ENV"){
          steps{
            dir("front-end-service") {
              script {
                withCredentials([file(credentialsId: "customer-react-env", variable: "SECRET_FILE_REACT")]) {
                  writeFile file: '.env', text: readFile(file: "${SECRET_FILE_REACT}")
                }
              }
            }
          }
        }
    
  2. Running all service in parallel because if we defined it in sequence, Jenkins build will stuck on what ever run first, so this is how:

        stage("Build ExpressJs and NestJs Service") {
          steps {
            parallel (
              "run express" : {
                dir("express-service") {
                  bat "npm install"
                  bat "node -r dotenv/config index.js"
                  bat "node -r dotenv/config src/configs/db.config.js"
                  bat "node index.js"
                }
              },
              "run nest": {
                dir("nest-service") {
                  bat "npm install"
                  bat "npm run start"
                }
              },
              "run react": {
                dir("front-end-service") {
                  bat "npm install"
                  bat "npm run dev"
                }
              }
            )
          }
        }
    

Final look of Jenkinsfile

This is the final look of our Jenkinsfile.

pipeline {
  agent any
  environment {
    SECRET_FILE_EXPRESS = credentials("customer-express-env")
    SECRET_FILE_NEST = credentials("customer-nest-env")
    SECRET_FILE_REACT = credentials("customer-react-env")
  }
  tools {
    nodejs "NodeJS"
  }
  stages {
    stage("Create ExpressJs Service ENV"){
        steps{
          dir("express-service") {
            script {
              withCredentials([file(credentialsId: "customer-express-env", variable: "SECRET_FILE_EXPRESS")]) {
                writeFile file: '.env', text: readFile(file: "${SECRET_FILE_EXPRESS}")
              }
            }
          }
        }
    }
    stage("Create NestJs Service ENV"){
      steps{
        dir("nest-service") {
          script {
            withCredentials([file(credentialsId: "customer-nest-env", variable: "SECRET_FILE_NEST")]) {
              writeFile file: '.env', text: readFile(file: "${SECRET_FILE_NEST}")
            }
          }
        }
      }
    }
    stage("Create React Service ENV"){
      steps{
        dir("front-end-service") {
          script {
            withCredentials([file(credentialsId: "customer-react-env", variable: "SECRET_FILE_REACT")]) {
              writeFile file: '.env', text: readFile(file: "${SECRET_FILE_REACT}")
            }
          }
        }
      }
    }
    stage("Build ExpressJs and NestJs Service") {
      steps {
        parallel (
          "run express" : {
            dir("express-service") {
              bat "npm install"
              bat "node -r dotenv/config index.js"
              bat "node -r dotenv/config src/configs/db.config.js"
              bat "node index.js"
            }
          },
          "run nest": {
            dir("nest-service") {
              bat "npm install"
              bat "npm run start"
            }
          },
          "run react": {
            dir("front-end-service") {
              bat "npm install"
              bat "npm run dev"
            }
          }
        )
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Build Jenkins Project.

  1. Push the change you created in Jenkinsfile to your Git repository.
  2. Choose New Item at Jenkins Dashboard.
  3. Enter the name for your Jenkins project. choose Pipeline. Click OK. Image description
  4. Once you got redirected to your project configuration, go to Pipeline section.
  5. In Definition dropdown, choose Pipeline script from SCM. Image description
  6. In SCM dropdown, choose Git. Image description
  7. Enter your repository url. The one that you use to clone your repository. I don't set any credential since my repository is public. Image description
  8. Choose the branch you want to build, mine is main. Image description
  9. I don't change anything at Script Path section since my Jenkinsfile name is Jenkinsfile. Please mind that it is case sensitive.
  10. Click Save.
  11. You will be redirected to your project. Choose Build Now.
  12. If things are fine you will mostlikely see this: Image description
  13. Since we are running our project, Jenkins will keep on going on build stage. To see if we done it right, go to your build history. Click on the latest build, which is #1. Image description
  14. Choose Console Output. Carefuly read the output to see if our services are running. If it does, try to go to front-end service address (still using the local address).
  15. You will see your own interface even when you're not running it in your local because it is being run by Jenkins Server. Image description
💖 💪 🙅 🚩
amalja0
Amalia Hajarani

Posted on November 30, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related