Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 80 additions & 124 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,125 +1,81 @@
pipeline {
agent any

environment {
SONARQUBE_SERVER = 'SonarQube'
DOCKER_IMAGE = 'your-docker-image'
APP_PORT = '3201'
APP_NAME = 'your-app-name'
GIT_URL = 'https://github.com/ohmjess/DevSecOps'
}

parameters {
string(name: 'BRANCH_NAME', defaultValue: 'main', description: 'Branch name for the build')
string(name: 'DOCKER_TAG', defaultValue: 'latest', description: 'Docker image tag')
}

stages {
stage('Checkout') {
steps {
script {
cleanWs()
git branch: "${params.BRANCH_NAME}", url: "${GIT_URL}"
}
}
}

stage('Verify Branch') {
steps {
script {
if ("${params.BRANCH_NAME}" != "main") {
error("This pipeline only runs on the main branch. Current branch: ${params.BRANCH_NAME}")
}
}
}
}

stage('Pulling Project')
{
steps {
echo 'Pulling the project...'
sh "git pull origin ${params.BRANCH_NAME}"
}
}

stage('Build') {
steps {
echo 'Building the project...'
sh 'npm install'
}
}

stage('Test') {
steps {
echo 'Running unit tests...'
sh 'npm test'
}
}

stage('Scan') {
steps {
withCredentials([string(credentialsId: 'jenkin-sonaqube', variable: 'SONAR_TOKEN')]) {
sh '''
npm install sonar-scanner
npx sonar-scanner \
-Dsonar.projectKey=mywebapp \
-Dsonar.host.url=http://sonarqube:9000 \
-Dsonar.login=$SONAR_TOKEN
'''
}
}
}

// stage('Clear Image')
// {
// steps {
// echo 'Clearing Docker image...'
// sh "docker rmi -f ${DOCKER_IMAGE}:${params.DOCKER_TAG}"
// }
// }

// stage('Build Docker Image') {
// steps {
// echo 'Building Docker image...'
// sh "docker build -t ${DOCKER_IMAGE}:${params.DOCKER_TAG} ."
// echo "Docker image built: ${DOCKER_IMAGE}:${params.DOCKER_TAG}"
// }
// }

// stage('Clear Container') {
// steps {
// script {
// def containers = sh(script: "docker ps -q --filter publish=${APP_PORT}", returnStdout: true).trim()
// if (containers) {
// echo "Stopping and removing containers using port ${APP_PORT}..."
// sh "echo ${containers} | xargs docker stop"
// sh "echo ${containers} | xargs docker rm"
// } else {
// echo "No containers are using port ${APP_PORT}."
// }
// }
// }
// }

stage('Deploy') {
steps {
echo 'Deploying the application...'
// ตัวอย่างการนำไปใช้โดยใช้ Docker
// sh "docker run -d -p ${APP_PORT}:3000 ${DOCKER_IMAGE}:${params.DOCKER_TAG}"
sh "docker-compose up -d --build"
}
}
}

post {
success {
echo 'Pipeline completed successfully!'
}
failure {
echo 'Pipeline failed.'
}
cleanup {
echo 'Cleaning up...'
}
}
pipeline {
agent any
environment {
APP_PORT = '3201'
GIT_URL = 'https://github.com/BSO-Space/DevSecOps'
}
parameters {
string(name: 'BRANCH_NAME', defaultValue: 'main', description: 'Branch name for the build')
string(name: 'DOCKER_TAG', defaultValue: 'latest', description: 'Docker image tag')
}
stages {
stage('Checkout & Pulling') {
steps {
script {
cleanWs()
git branch: "${params.BRANCH_NAME}", url: "${GIT_URL}"
if ("${params.BRANCH_NAME}" != "main") {
error("This pipeline only runs on the main branch. Current branch: ${params.BRANCH_NAME}")
}
echo 'Pulling the project...'
sh "git pull origin ${params.BRANCH_NAME}"
}
}
}

stage('Install Dependencies') {
steps {
echo 'Building the project...'
sh 'npm install'
}
}

stage('Testing with Jest') {
steps {
echo 'Running unit tests...'
sh 'npm test'
}
}

stage('Code analysis') {
steps {
withCredentials([string(credentialsId: 'test-sonar', variable: 'SONAR_TOKEN')]) {
sh '''
npm install sonar-scanner
npx sonar-scanner \
-Dsonar.projectKey=mywebapp \
-Dsonar.host.url=http://sonarqube-dso-demo:9000 \
-Dsonar.login=$SONAR_TOKEN
'''
}
}
post {
success {
echo 'Code analysis passed.'
}
failure {
echo 'Code analysis failed. Stopping the pipeline.'
error("Quality gate failed. Pipeline stopped.")
}
}
}

stage('Docker Deployment') {
steps {
echo 'Deploying the application...'
sh "docker-compose up -d --build"
}
}
}
post {
success {
echo 'Pipeline completed successfully!'
}
failure {
echo 'Pipeline failed.'
}
cleanup {
echo 'Cleaning up...'
}
}
}
48 changes: 34 additions & 14 deletions __test__/app.spec.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
// __tests__/app.test.js
const request = require('supertest');
const app = require('../app'); // ปรับตามเส้นทางที่ถูกต้อง
const request = require("supertest");
const app = require("../app"); // ปรับตามเส้นทางที่ถูกต้อง

describe('GET /', () => {
it('responds with status 200 and returns the expected message', async () => {
const response = await request(app).get('/');
expect(response.status).toBe(200);
expect(response.text).toBe('Hello I am senior devsecops engineer'); // ปรับให้ตรงกับข้อความที่ตอบกลับ
});
describe("GET /", () => {
it("responds with status 200 and returns the expected message", async () => {
const response = await request(app).get("/");
expect(response.status).toBe(200);
expect(response.text).toBe(
"<h1>Hello world! This is our first project towards becoming DevSecOps engineers.😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎</h1>"
);
});
});

describe('GET /about', () => {
it('responds with status 200 and renders the about page', async () => {
const response = await request(app).get('/about');
expect(response.status).toBe(200);
expect(response.text).toContain('about gay'); // เปลี่ยนข้อความให้ตรงกับเนื้อหาใน about.html
});
describe("GET /about", () => {
it("responds with status 200 and renders the about page", async () => {
const response = await request(app).get("/about");
expect(response.status).toBe(200);
expect(response.text).toContain("about page"); // เปลี่ยนข้อความให้ตรงกับเนื้อหาใน about.html
});
});

describe("GET /", () => {
it("responds with status 200 and returns the expected message", async () => {
const response = await request(app).get("/");
expect(response.status).toBe(200);
expect(response.text).toBe(
"<h1>Hello world! This is our first project towards becoming DevSecOps engineers.😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎</h1>"
); // ปรับให้ตรงกับข้อความที่ตอบกลับ
});
});

describe("GET /about", () => {
it("responds with status 200 and renders the about page", async () => {
const response = await request(app).get("/about");
expect(response.status).toBe(200);
expect(response.text).toContain("about page"); // เปลี่ยนข้อความให้ตรงกับเนื้อหาใน about.html
});
});
16 changes: 12 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ app.use(express.static("public"));
// Define routes
app.get("/", (req, res) => {
// Unused variable
const unusedVar = "Hello I am senior devsecops engineer";
res.status(200).send(unusedVar);
const unusedVar = "This variable is not used anywhere";
res
.status(200)
.send(
"<h1>Hello world! This is our first project towards becoming DevSecOps engineers.😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎😎</h1>"
);
});

app.get("/about", (req, res) => {
// Redundant code
res.send("about gay");
res.send("about page");
res.send("This line will never execute"); // This line is unreachable
});

app.get("/helloworld", (req, res) => {
res.send("helloworld");
});

// Function with no purpose
function uselessFunction() {
var text = "bom gay";
var text = "This is useless variable";
// This function does nothing but takes up space
}

Expand Down