Xây Dựng Jenkins Pipeline Duy Nhất Cho Nhiều Môi Trường (Dev, Stg, Prod) Trên GitLab
CI/CD (Continuous Integration/Continuous Deployment) đã trở thành một phần không thể thiếu trong việc phát triển phần mềm hiện đại. Jenkins, một công cụ CI/CD phổ biến, thường được sử dụng để tự động hóa quy trình build, test và deploy. Trong bài viết này, chúng ta sẽ tìm hiểu cách viết một Jenkinsfile duy nhất để quản lý nhiều môi trường (Dev, Stg, Prod) trên GitLab. Đồng thời, chúng ta sẽ làm thế nào để hiển thị rõ ràng thông tin môi trường trên giao diện Jenkins, giúp dễ dàng quản lý và theo dõi quy trình build.
1. Bài toán đặt ra
Khi bạn phát triển một ứng dụng với nhiều môi trường như Development (Dev), Staging (Stg), và Production (Prod), thường bạn sẽ có các nhánh tương ứng trên GitLab để quản lý mã nguồn của từng môi trường. Đối với mỗi môi trường, quy trình build, test và deploy có thể tương tự nhau, chỉ khác ở một vài tham số.
Mục tiêu:
Viết một Jenkinsfile duy nhất để dùng cho tất cả các nhánh (Dev, Stg, Prod), thay vì phải tạo một Jenkinsfile riêng cho mỗi nhánh.
Làm sao để hiển thị tên môi trường (Dev, Stg, Prod) và thông tin cần thiết trên giao diện Jenkins giúp dễ dàng quản lý các build?
2. Tạo Jenkinsfile
duy nhất cho nhiều môi trường
2.1. Xác định nhánh hiện tại
Trong Jenkins, biến môi trường env.GIT_BRANCH
sẽ chứa thông tin về nhánh hiện tại mà Jenkins đang build. Dựa vào biến này, chúng ta có thể quyết định hành động cụ thể cho từng môi trường.
2.2. Định nghĩa function dùng chung
Nếu quá trình build, test, deploy của các môi trường là tương tự nhau, chúng ta có thể định nghĩa một function chung để tái sử dụng cho mọi môi trường. Bạn chỉ cần truyền các tham số khác nhau tương ứng với môi trường cụ thể.
Ví dụ Jenkinsfile
:
pipeline {
agent any
environment {
BRANCH_NAME = "${env.GIT_BRANCH}"
}
stages {
stage('Set Build Display Name') {
steps {
script {
// Đặt tên hiển thị của build dựa trên môi trường
if (BRANCH_NAME == 'dev') {
currentBuild.displayName = "#${BUILD_NUMBER} - Dev Environment"
currentBuild.description = "Building for Dev"
} else if (BRANCH_NAME == 'stg') {
currentBuild.displayName = "#${BUILD_NUMBER} - Staging Environment"
currentBuild.description = "Building for Staging"
} else if (BRANCH_NAME == 'prod') {
currentBuild.displayName = "#${BUILD_NUMBER} - Production Environment"
currentBuild.description = "Building for Production"
} else {
currentBuild.displayName = "#${BUILD_NUMBER} - Unknown Environment"
currentBuild.description = "Unknown branch: ${BRANCH_NAME}"
}
}
}
}
stage('Build') {
steps {
script {
// Xác định môi trường và các tham số khác nhau dựa trên nhánh
buildProject(BRANCH_NAME)
}
}
}
}
}
def buildProject(branch) {
echo "Building for branch: ${branch}"
// Các bước build, test, deploy tùy thuộc vào nhánh.
sh './build.sh'
}
pipeline {
agent any
environment {
BRANCH_NAME = "${env.GIT_BRANCH}"
}
stages {
stage('Build') {
steps {
script {
// Xác định môi trường và các tham số khác nhau dựa trên nhánh
if (BRANCH_NAME == 'dev') {
buildProject('Dev', 'build-dev.sh', 'test-dev.sh', 'deploy-dev.sh')
} else if (BRANCH_NAME == 'stg') {
buildProject('Staging', 'build-stg.sh', 'test-stg.sh', 'deploy-stg.sh')
} else if (BRANCH_NAME == 'prod') {
buildProject('Production', 'build-prod.sh', 'test-prod.sh', 'deploy-prod.sh')
} else {
error "Unknown branch: ${BRANCH_NAME}. Stopping build."
}
}
}
}
}
}
def buildProject(envName, buildScript, testScript, deployScript) {
echo "Building for ${envName} environment"
// Bước Build
echo "Running build script: ${buildScript}"
sh "./${buildScript}"
// Bước Test
echo "Running test script: ${testScript}"
sh "./${testScript}"
// Bước Deploy (nếu cần thiết)
echo "Running deploy script: ${deployScript}"
sh "./${deployScript}"
}
2.3. Cách hoạt động của Jenkinsfile
BRANCH_NAME: Chúng ta sử dụng biến
env.GIT_BRANCH
để xác định tên nhánh mà Jenkins đang build.Set Display Name: Tên của build trên giao diện Jenkins sẽ được thay đổi theo từng môi trường (
Dev
,Stg
,Prod
), giúp dễ dàng phân biệt.Sử dụng
currentBuild.displayName
để đặt tên build dựa trên số build (BUILD_NUMBER
) và môi trường.currentBuild.description
để mô tả thêm chi tiết về build.
buildProject function: Một function chung được định nghĩa để thực hiện các bước build, test, và deploy. Tùy vào nhánh hiện tại, các thông số tương ứng sẽ được truyền vào.
3. Hiển thị thông tin môi trường trên giao diện Jenkins
3.1. Thay đổi tên hiển thị của build
Khi sử dụng Jenkins, tên của các build thường mặc định chỉ là số build (#1
, #2
,...). Điều này không cung cấp đủ thông tin để phân biệt các môi trường. Vì vậy, chúng ta có thể sử dụng currentBuild.displayName
để thay đổi tên build, giúp hiển thị rõ ràng môi trường mà build đang chạy.
Ví dụ:
Build của nhánh Dev sẽ hiển thị:
#12 - Dev Environment
.Build của nhánh Prod sẽ hiển thị:
#15 - Production Environment
.
Điều này giúp quản trị viên dễ dàng nhận biết build đang chạy cho môi trường nào ngay trên giao diện Jenkins.
3.2. Hiển thị mô tả chi tiết
Ngoài tên build, bạn có thể sử dụng currentBuild.description
để thêm mô tả chi tiết hơn cho mỗi build, ví dụ như: "Building for Staging" hoặc "Deploying to Production". Thông tin này sẽ hiển thị ngay bên dưới tên build, giúp người quản trị hiểu rõ hơn về trạng thái của từng build.
3.3. Sử dụng Multibranch Pipeline cho nhiều nhánh
Nếu dự án của bạn có nhiều nhánh và bạn muốn quản lý các nhánh một cách tự động, Multibranch Pipeline là lựa chọn tốt. Jenkins sẽ tự động phát hiện và tạo các pipeline cho từng nhánh, đồng thời gắn tên nhánh vào từng build.
Cách sử dụng:
Trong Jenkins, chọn New Item > Multibranch Pipeline.
Thiết lập nguồn GitLab để lấy các nhánh.
Jenkins sẽ tự động tạo và quản lý pipeline cho từng nhánh. Trên giao diện, bạn sẽ thấy rõ tên nhánh và trạng thái build của từng nhánh.
4. Kết hợp với các plugin UI để cải thiện giao diện
Jenkins có nhiều plugin hỗ trợ làm đẹp và cải thiện giao diện người dùng. Một số plugin hữu ích để hiển thị thông tin môi trường bao gồm:
Blue Ocean: Giao diện đẹp và dễ sử dụng hơn so với giao diện mặc định của Jenkins. Nó hiển thị rõ ràng các pipeline, nhánh, và trạng thái build.
Build Name and Description Setter: Plugin này tự động thay đổi tên và mô tả của build dựa trên các điều kiện cụ thể, như nhánh hay môi trường.
5. Kết luận
Việc sử dụng một Jenkinsfile duy nhất cho nhiều môi trường (Dev, Stg, Prod) không chỉ giúp đơn giản hóa quản lý pipeline mà còn dễ dàng mở rộng và bảo trì. Kết hợp với việc hiển thị rõ ràng thông tin môi trường trên giao diện Jenkins, bạn có thể dễ dàng phân biệt và theo dõi trạng thái của từng môi trường.
Bằng cách sử dụng các kỹ thuật như currentBuild.displayName, currentBuild.description, và Multibranch Pipeline, quy trình CI/CD của bạn sẽ trở nên rõ ràng, hiệu quả và dễ dàng quản lý hơn.