Certified Jenkins Engineer

Setting up CI Pipeline

Demo Run and Test NodeJS App on Local Machine

In this guide, we’ll walk through running and testing a Solar System Node.js application on your local (or virtual) machine. We’ll cover:

  • Cloning the repository
  • Inspecting package.json
  • Reviewing application code (app.js, controllers, client)
  • Executing unit tests and enforcing coverage
  • Containerizing with Docker
  • Exploring OpenAPI specs
  • Running the app and demoing endpoints
  • Automating everything with Jenkins pipelines

Prerequisites

Ensure you have these versions installed:

node --version    # v8.11.3+
npm --version     # v6.1.0+

Install project dependencies:

npm install

Run a quick test:

npm test
npm run coverage

Repository Overview

The Solar System app uses:

  • Express for the REST API
  • Mongoose for MongoDB integration
  • Mocha & Chai for testing
  • nyc for code coverage
  • serverless-http for AWS Lambda support

The image shows a GitHub repository page for a project titled "Solar System NodeJS Application," featuring a list of files and their commit history. The repository primarily uses JavaScript, HTML, and Dockerfile.

Project Structure

File/FolderPurpose
package.jsonMetadata, scripts, dependencies
app.jsExpress setup & MongoDB connection
app.controller.jsRoute definitions & Mongoose schemas
client.jsFrontend logic for /os endpoint
app-test.jsMocha/Chai test suite
DockerfileContainerization instructions
openapi.yamlOpenAPI 3.0 definitions
index.htmlStatic frontend

1. Clone the Repository

git clone https://github.com/sidd-harth/solar-system-gitea.git
cd solar-system-gitea/

2. Inspect package.json

Open package.json to review scripts and dependencies:

{
  "name": "Solar System",
  "version": "6.7.6",
  "scripts": {
    "start": "node app.js",
    "test": "mocha app-test.js --timeout 10000 --reporter mocha-junit-reporter --exit",
    "coverage": "nyc --reporter cobertura --reporter lcov --reporter text --reporter json-summary mocha app-test"
  },
  "nyc": {
    "check-coverage": true,
    "lines": 90
  },
  "dependencies": {
    "express": "^4.18.2",
    "mongoose": "^5.13.20",
    "cors": "^2.8.5",
    "serverless-http": "^1.15.0"
  },
  "devDependencies": {
    "mocha": "*",
    "chai": "*",
    "chai-http": "*"
  }
}

Key points:

  • test runs Mocha with JUnit output.
  • coverage enforces ≥ 90% line coverage via nyc.
  • serverless-http enables AWS Lambda compatibility.

3. Application Entry Point (app.js)

This file initializes Express, connects to MongoDB, and exports the app for tests and serverless:

// app.js
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const serverless = require('serverless-http');

const app = express();
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname)));
app.use(cors());

mongoose.connect(process.env.MONGO_URI, {
  user: process.env.MONGO_USERNAME,
  pass: process.env.MONGO_PASSWORD,
  useNewUrlParser: true,
  useUnifiedTopology: true
}, err => {
  if (err) console.error('MongoDB connection error:', err);
});

// Export for tests & AWS Lambda
module.exports = app;

4. Controller & Routes (app.controller.js)

Define the Mongoose schema and API endpoints:

// app.controller.js
const os = require('os');
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const dataSchema = new Schema({
  id: Number,
  name: String,
  description: String,
  image: String,
  velocity: String,
  distance: String
});
const Planet = mongoose.model('planets', dataSchema);

app.post('/planet', (req, res) => {
  Planet.findOne({ id: req.body.id }, (err, planet) => {
    if (err) return res.status(500).send(err);
    res.json(planet);
  });
});

app.get('/os', (req, res) => {
  res.json({ os: os.hostname() });
});

app.get('/live', (req, res) => {
  res.json({ status: 'live' });
});

app.get('/ready', (req, res) => {
  res.json({ status: 'ready' });
});

5. Frontend Logic (client.js)

Fetch and display the hostname from /os:

// client.js
window.onload = () => {
  fetch('/os')
    .then(res => res.ok ? res.json() : Promise.reject('Request failed'))
    .then(data => {
      document.getElementById('hostname').innerText = `Pod - ${data.os}`;
    })
    .catch(console.error);
};

const btn = document.getElementById('submit');
if (btn) {
  btn.addEventListener('click', () => {
    // handle planet search...
  });
}

6. Unit Tests (app-test.js)

Validate endpoints with Mocha, Chai, and chai-http:

// app-test.js
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('./app');

chai.use(chaiHttp);
chai.should();

describe('Solar System API', () => {
  describe('POST /planet', () => {
    it('returns Mercury for id=1', done => {
      chai.request(app)
        .post('/planet')
        .send({ id: 1 })
        .end((err, res) => {
          res.should.have.status(200);
          res.body.should.include({ id: 1, name: 'Mercury' });
          done();
        });
    });
  });

  it('GET /os returns host information', done => {
    chai.request(app)
      .get('/os')
      .end((err, res) => {
        res.should.have.status(200);
        res.body.should.have.property('os');
        done();
      });
  });
});

7. Dockerfile

Build an Alpine-based Node.js container:

# Dockerfile
FROM node:18-alpine3.17
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
ENV MONGO_URI=uriPlaceholder
ENV MONGO_USERNAME=usernamePlaceholder
ENV MONGO_PASSWORD=passwordPlaceholder
EXPOSE 3000
CMD ["npm", "start"]

8. OpenAPI Spec (openapi.yaml)

Define three endpoints for probes and host info:

openapi: 3.0.0
info:
  title: Solar System API
  version: 1.0
paths:
  /os:
    get:
      responses:
        '200':
          description: Hostname info
  /live:
    get:
      responses:
        '200':
          description: Liveness probe
  /ready:
    get:
      responses:
        '200':
          description: Readiness probe

9. Run Locally

  1. Install dependencies:

    npm install
    
  2. Export MongoDB credentials or hard-code for quick tests:

    Note

    If MONGO_URI isn’t set, npm test will fail. Use:

    export MONGO_URI="your-mongo-uri"
    export MONGO_USERNAME="user"
    export MONGO_PASSWORD="pass"
    
  3. Run tests and coverage:

    npm test
    npm run coverage
    
  4. Add a listener in app.js to start the server:

    app.listen(3000, () => console.log('Server running on port 3000'));
    
  5. Start the application:

    npm start
    

10. Explore in Browser

Navigate to http://<VM-IP>:3000 to view and search planets:

The image shows a stylized representation of the solar system with planets orbiting the sun, accompanied by a search interface for exploring the planets.

Search for ID “3” (Earth):

The image shows a stylized depiction of Earth with a description about the planet, set against a space-themed background. It includes a "Solar System" header and a search feature for planets.

Test the JSON endpoints:

curl http://<VM-IP>:3000/os   # {"os":"jenkins-controller-1"}
curl http://<VM-IP>:3000/live # {"status":"live"}
curl http://<VM-IP>:3000/ready# {"status":"ready"}

In the next lesson, we’ll automate cloning, building, testing, coverage enforcement, and deployment with Jenkins pipelines.

Watch Video

Watch video content

Previous
NodeJS Application Overview