This commit is contained in:
319
jf
Normal file
319
jf
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
// === BACKEND SERVICE CONFIGURATION ===
|
||||||
|
parameters {
|
||||||
|
string(name: 'HARBOR_REGISTRY', defaultValue: 'harbor.example.com', description: 'Harbor registry URL')
|
||||||
|
string(name: 'HARBOR_PROJECT', defaultValue: 'inventory', description: 'Harbor project name')
|
||||||
|
string(name: 'IMAGE_NAME', defaultValue: 'backend', description: 'Image name')
|
||||||
|
string(name: 'GIT_BRANCH', defaultValue: 'main', description: 'Git branch to build')
|
||||||
|
string(name: 'ENVIRONMENT', defaultValue: 'prod', description: 'Target environment (dev/staging/prod)')
|
||||||
|
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: 'Skip test execution')
|
||||||
|
booleanParam(name: 'AUTO_DEPLOY', defaultValue: true, description: 'Auto-sync ArgoCD after push')
|
||||||
|
}
|
||||||
|
|
||||||
|
environment {
|
||||||
|
// Service-specific paths
|
||||||
|
SERVICE_NAME = 'backend-service'
|
||||||
|
SERVICE_DIR = "${WORKSPACE}/${SERVICE_NAME}"
|
||||||
|
|
||||||
|
// Image configuration
|
||||||
|
IMAGE_FULL_NAME = "${params.HARBOR_REGISTRY}/${params.HARBOR_PROJECT}/${params.IMAGE_NAME}"
|
||||||
|
IMAGE_TAG = "${params.GIT_BRANCH}-${env.BUILD_NUMBER}-${env.GIT_COMMIT?.take(7) ?: 'latest'}"
|
||||||
|
|
||||||
|
// K8s manifests
|
||||||
|
K8S_MANIFESTS_DIR = "${WORKSPACE}/k8s-manifests"
|
||||||
|
KUSTOMIZE_DIR = "${K8S_MANIFESTS_DIR}/overlays/${params.ENVIRONMENT}"
|
||||||
|
|
||||||
|
// Credentials
|
||||||
|
HARBOR_CREDENTIALS = credentials('harbor-credentials')
|
||||||
|
ARGOCD_CREDENTIALS = credentials('argocd-credentials')
|
||||||
|
|
||||||
|
// ArgoCD
|
||||||
|
ARGOCD_SERVER = 'argocd.example.com'
|
||||||
|
ARGOCD_APP_NAME = 'inventory-app'
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
// === STAGE 1: CHECKOUT CODE ===
|
||||||
|
stage('Checkout') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
echo "🔄 Cloning repository for Backend Service..."
|
||||||
|
checkout scm
|
||||||
|
|
||||||
|
env.GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
|
||||||
|
env.GIT_AUTHOR = sh(returnStdout: true, script: 'git log -1 --pretty=format:%an').trim()
|
||||||
|
|
||||||
|
echo """
|
||||||
|
✅ Checkout completed
|
||||||
|
📦 Service: ${SERVICE_NAME}
|
||||||
|
🔖 Commit: ${env.GIT_COMMIT}
|
||||||
|
👤 Author: ${env.GIT_AUTHOR}
|
||||||
|
🌿 Branch: ${params.GIT_BRANCH}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === STAGE 2: RUN TESTS ===
|
||||||
|
stage('Test Backend') {
|
||||||
|
when {
|
||||||
|
expression { return !params.SKIP_TESTS }
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
dir(SERVICE_DIR) {
|
||||||
|
script {
|
||||||
|
echo "🧪 Running backend tests..."
|
||||||
|
|
||||||
|
// Install dependencies
|
||||||
|
sh 'npm ci'
|
||||||
|
|
||||||
|
// Run tests with coverage
|
||||||
|
sh 'npm test'
|
||||||
|
|
||||||
|
// Optional: Publish test results
|
||||||
|
// junit 'coverage/junit.xml'
|
||||||
|
// publishHTML(target: [
|
||||||
|
// reportDir: 'coverage',
|
||||||
|
// reportFiles: 'index.html',
|
||||||
|
// reportName: 'Test Coverage Report'
|
||||||
|
// ])
|
||||||
|
|
||||||
|
echo "✅ Backend tests passed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === STAGE 3: CODE QUALITY (OPTIONAL) ===
|
||||||
|
// Uncomment to enable SonarQube scanning
|
||||||
|
// stage('SonarQube Analysis') {
|
||||||
|
// steps {
|
||||||
|
// dir(SERVICE_DIR) {
|
||||||
|
// script {
|
||||||
|
// echo "🔍 Running SonarQube analysis..."
|
||||||
|
// withSonarQubeEnv('SonarQube') {
|
||||||
|
// sh 'sonar-scanner'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// === STAGE 4: BUILD DOCKER IMAGE ===
|
||||||
|
stage('Build Image') {
|
||||||
|
steps {
|
||||||
|
dir(SERVICE_DIR) {
|
||||||
|
script {
|
||||||
|
echo "🐳 Building Docker image for backend..."
|
||||||
|
|
||||||
|
sh """
|
||||||
|
docker build \
|
||||||
|
-t ${IMAGE_FULL_NAME}:${IMAGE_TAG} \
|
||||||
|
-t ${IMAGE_FULL_NAME}:${params.GIT_BRANCH}-latest \
|
||||||
|
--label "git.commit=${env.GIT_COMMIT}" \
|
||||||
|
--label "build.number=${env.BUILD_NUMBER}" \
|
||||||
|
--label "service=${SERVICE_NAME}" \
|
||||||
|
.
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo """
|
||||||
|
✅ Image built successfully
|
||||||
|
🏷️ ${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
🏷️ ${IMAGE_FULL_NAME}:${params.GIT_BRANCH}-latest
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === STAGE 5: SECURITY SCAN (OPTIONAL) ===
|
||||||
|
// Uncomment to enable Trivy security scanning
|
||||||
|
// stage('Security Scan') {
|
||||||
|
// steps {
|
||||||
|
// script {
|
||||||
|
// echo "🔒 Scanning image for vulnerabilities..."
|
||||||
|
// sh """
|
||||||
|
// trivy image \
|
||||||
|
// --severity HIGH,CRITICAL \
|
||||||
|
// --exit-code 0 \
|
||||||
|
// ${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
// """
|
||||||
|
// echo "✅ Security scan completed"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// === STAGE 6: PUSH TO HARBOR ===
|
||||||
|
stage('Push to Harbor') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
echo "📦 Pushing backend image to Harbor..."
|
||||||
|
|
||||||
|
// Login to Harbor
|
||||||
|
sh """
|
||||||
|
echo ${HARBOR_CREDENTIALS_PSW} | docker login ${params.HARBOR_REGISTRY} \
|
||||||
|
-u ${HARBOR_CREDENTIALS_USR} \
|
||||||
|
--password-stdin
|
||||||
|
"""
|
||||||
|
|
||||||
|
// Push images
|
||||||
|
sh """
|
||||||
|
docker push ${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
docker push ${IMAGE_FULL_NAME}:${params.GIT_BRANCH}-latest
|
||||||
|
"""
|
||||||
|
|
||||||
|
// Logout
|
||||||
|
sh "docker logout ${params.HARBOR_REGISTRY}"
|
||||||
|
|
||||||
|
echo """
|
||||||
|
✅ Images pushed to Harbor
|
||||||
|
📦 ${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
📦 ${IMAGE_FULL_NAME}:${params.GIT_BRANCH}-latest
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === STAGE 7: UPDATE K8S MANIFESTS (GITOPS) ===
|
||||||
|
stage('Update Manifests') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
echo "📝 Updating Kubernetes manifests..."
|
||||||
|
|
||||||
|
dir(KUSTOMIZE_DIR) {
|
||||||
|
// Install kustomize if not available
|
||||||
|
sh '''
|
||||||
|
if ! command -v kustomize &> /dev/null; then
|
||||||
|
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||||
|
sudo mv kustomize /usr/local/bin/
|
||||||
|
fi
|
||||||
|
'''
|
||||||
|
|
||||||
|
// Update image tag using kustomize
|
||||||
|
sh """
|
||||||
|
kustomize edit set image \
|
||||||
|
gitea.example.com/inventory/backend=${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo "📄 Updated kustomization.yaml:"
|
||||||
|
sh "cat kustomization.yaml"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit and push changes
|
||||||
|
sh """
|
||||||
|
cd ${K8S_MANIFESTS_DIR}
|
||||||
|
git config user.email "jenkins@example.com"
|
||||||
|
git config user.name "Jenkins Backend Pipeline"
|
||||||
|
git add overlays/${params.ENVIRONMENT}/kustomization.yaml
|
||||||
|
git commit -m "chore(backend): update image to ${IMAGE_TAG}
|
||||||
|
|
||||||
|
Build: ${env.BUILD_NUMBER}
|
||||||
|
Commit: ${env.GIT_COMMIT}
|
||||||
|
Branch: ${params.GIT_BRANCH}
|
||||||
|
Environment: ${params.ENVIRONMENT}
|
||||||
|
|
||||||
|
Co-Authored-By: ${env.GIT_AUTHOR}" || echo "No changes to commit"
|
||||||
|
|
||||||
|
git push origin ${params.GIT_BRANCH}
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo "✅ Manifests updated and pushed to Git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === STAGE 8: DEPLOY WITH ARGOCD ===
|
||||||
|
stage('Deploy') {
|
||||||
|
when {
|
||||||
|
expression { return params.AUTO_DEPLOY }
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
echo "🚀 Triggering ArgoCD sync..."
|
||||||
|
|
||||||
|
// Install ArgoCD CLI if needed
|
||||||
|
sh '''
|
||||||
|
if ! command -v argocd &> /dev/null; then
|
||||||
|
curl -sSL -o /tmp/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
|
||||||
|
chmod +x /tmp/argocd
|
||||||
|
ARGOCD_CMD=/tmp/argocd
|
||||||
|
else
|
||||||
|
ARGOCD_CMD=argocd
|
||||||
|
fi
|
||||||
|
'''
|
||||||
|
|
||||||
|
// Login and sync
|
||||||
|
sh """
|
||||||
|
ARGOCD_CMD=\$(command -v argocd || echo /tmp/argocd)
|
||||||
|
|
||||||
|
\$ARGOCD_CMD login ${ARGOCD_SERVER} \
|
||||||
|
--username ${ARGOCD_CREDENTIALS_USR} \
|
||||||
|
--password ${ARGOCD_CREDENTIALS_PSW} \
|
||||||
|
--insecure
|
||||||
|
|
||||||
|
\$ARGOCD_CMD app sync ${ARGOCD_APP_NAME} \
|
||||||
|
--prune \
|
||||||
|
--timeout 300
|
||||||
|
|
||||||
|
\$ARGOCD_CMD app wait ${ARGOCD_APP_NAME} \
|
||||||
|
--health \
|
||||||
|
--timeout 300
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo "✅ Backend service deployed successfully"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === POST ACTIONS ===
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
script {
|
||||||
|
echo "🧹 Cleaning up..."
|
||||||
|
sh """
|
||||||
|
docker rmi ${IMAGE_FULL_NAME}:${IMAGE_TAG} || true
|
||||||
|
docker rmi ${IMAGE_FULL_NAME}:${params.GIT_BRANCH}-latest || true
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success {
|
||||||
|
script {
|
||||||
|
echo """
|
||||||
|
✅ ========================================
|
||||||
|
BACKEND BUILD SUCCESSFUL
|
||||||
|
========================================
|
||||||
|
📦 Service: ${SERVICE_NAME}
|
||||||
|
🏷️ Image: ${IMAGE_FULL_NAME}:${IMAGE_TAG}
|
||||||
|
🔖 Commit: ${env.GIT_COMMIT}
|
||||||
|
🔢 Build: ${env.BUILD_NUMBER}
|
||||||
|
🌍 Environment: ${params.ENVIRONMENT}
|
||||||
|
========================================
|
||||||
|
"""
|
||||||
|
|
||||||
|
// Optional: Send notification
|
||||||
|
// slackSend(
|
||||||
|
// color: 'good',
|
||||||
|
// message: "✅ Backend build ${env.BUILD_NUMBER} succeeded\nImage: ${IMAGE_TAG}"
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
failure {
|
||||||
|
script {
|
||||||
|
echo """
|
||||||
|
BACKEND BUILD FAILED
|
||||||
|
"""
|
||||||
|
|
||||||
|
// Optional: Send notification
|
||||||
|
// slackSend(
|
||||||
|
// color: 'danger',
|
||||||
|
// message: "❌ Backend build ${env.BUILD_NUMBER} failed"
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user