Java CI/CD Guide: Complete Tutorial

1️⃣ Introduction

Continuous Integration and Continuous Deployment (CI/CD) are essential practices for modern Java development. This guide covers everything you need to know about implementing CI/CD for Java applications.

Key areas covered:

  • CI/CD Pipeline Setup
  • Build Automation
  • Testing Strategies
  • Deployment Automation
  • Monitoring & Feedback
  • Best Practices

2️⃣ GitHub Actions Pipeline

🔹 Workflow Configuration

name: Java CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    
    - name: Set up JDK 17
      uses: actions/setup-java@v2
      with:
        java-version: '17'
        distribution: 'adopt'
        
    - name: Cache Maven packages
      uses: actions/cache@v2
      with:
        path: ~/.m2
        key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
        restore-keys: ${{ runner.os }}-m2
        
    - name: Build with Maven
      run: mvn -B package --file pom.xml
      
    - name: Run Tests
      run: mvn test
      
    - name: Generate Test Report
      run: mvn surefire-report:report
      
    - name: Upload Test Results
      uses: actions/upload-artifact@v2
      with:
        name: test-results
        path: target/site/surefire-report.html

🔹 Quality Gates

name: Quality Gates

on:
  push:
    branches: [ main ]

jobs:
  sonarcloud:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    
    - name: SonarCloud Scan
      uses: SonarSource/sonarcloud-github-action@master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      with:
        args: >
          -Dsonar.projectKey=my-project
          -Dsonar.organization=my-org
          -Dsonar.java.binaries=target/classes
          -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
          
    - name: Check Quality Gate
      run: |
        QUALITY_GATE=$(curl -s -u ${{ secrets.SONAR_TOKEN }}: \
          "https://sonarcloud.io/api/qualitygates/project_status?projectKey=my-project" \
          | jq -r '.projectStatus.status')
        if [ "$QUALITY_GATE" != "OK" ]; then
          echo "Quality Gate failed"
          exit 1
        fi

3️⃣ Jenkins Pipeline

🔹 Jenkinsfile Configuration

pipeline {
    agent any
    
    tools {
        maven 'Maven 3.8.4'
        jdk 'JDK 17'
    }
    
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/user/repo.git'
            }
        }
        
        stage('Build') {
            steps {
                sh 'mvn clean package'
            }
        }
        
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit '**/target/surefire-reports/*.xml'
                }
            }
        }
        
        stage('Code Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh 'mvn sonar:sonar'
                }
            }
        }
        
        stage('Deploy to Staging') {
            when {
                branch 'develop'
            }
            steps {
                sh '''
                    docker build -t myapp:${BUILD_NUMBER} .
                    docker push myapp:${BUILD_NUMBER}
                    kubectl apply -f k8s/staging/
                '''
            }
        }
        
        stage('Deploy to Production') {
            when {
                branch 'main'
            }
            steps {
                input 'Deploy to production?'
                sh '''
                    docker build -t myapp:${BUILD_NUMBER} .
                    docker push myapp:${BUILD_NUMBER}
                    kubectl apply -f k8s/production/
                '''
            }
        }
    }
    
    post {
        always {
            cleanWs()
        }
        success {
            slackSend channel: '#deployments',
                color: 'good',
                message: "Build successful: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
        }
        failure {
            slackSend channel: '#deployments',
                color: 'danger',
                message: "Build failed: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
        }
    }
}

4️⃣ Deployment Configuration

🔹 Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: java-app
  template:
    metadata:
      labels:
        app: java-app
    spec:
      containers:
      - name: java-app
        image: myapp:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1"
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
  name: java-app-service
  namespace: production
spec:
  selector:
    app: java-app
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

🔹 Helm Chart

apiVersion: v2
name: java-app
description: A Helm chart for Java application
version: 0.1.0

dependencies:
  - name: postgresql
    version: 11.6.3
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled

values:yaml:
  replicaCount: 3
  
  image:
    repository: myapp
    tag: latest
    pullPolicy: Always
  
  service:
    type: LoadBalancer
    port: 80
  
  ingress:
    enabled: true
    annotations:
      kubernetes.io/ingress.class: nginx
    hosts:
      - host: app.example.com
        paths:
          - path: /
            pathType: Prefix
  
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: 1
      memory: 1Gi
  
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
    targetCPUUtilizationPercentage: 80

5️⃣ Monitoring & Feedback

🔹 Prometheus Configuration

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'java-app'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['java-app:8080']
    
  - job_name: 'jenkins'
    metrics_path: '/prometheus'
    static_configs:
      - targets: ['jenkins:8080']

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

rule_files:
  - 'alert.rules'

6️⃣ Q&A / Frequently Asked Questions

Key practices: (1) Automate everything. (2) Use version control. (3) Implement comprehensive testing. (4) Use quality gates. (5) Implement security scanning. (6) Use infrastructure as code. (7) Monitor deployments. (8) Implement rollback strategies.

Deployment strategies: (1) Use blue-green deployments. (2) Implement canary releases. (3) Set up proper monitoring. (4) Use health checks. (5) Implement automated rollbacks. (6) Test in staging environment. (7) Use feature flags.

Common issues: (1) Flaky tests. (2) Long build times. (3) Environment inconsistencies. (4) Security vulnerabilities. (5) Resource constraints. (6) Configuration drift. (7) Deployment failures. (8) Monitoring gaps.

7️⃣ Best Practices & Pro Tips 🚀

  • Automate everything possible
  • Use version control effectively
  • Implement comprehensive testing
  • Set up quality gates
  • Use infrastructure as code
  • Monitor deployments
  • Implement security scanning
  • Use proper branching strategy
  • Maintain deployment documentation
  • Regular performance testing
  • Implement proper logging
  • Use feature flags

Read Next 📖

Conclusion

Implementing a robust CI/CD pipeline is crucial for modern Java applications. By following the patterns and practices outlined in this guide, you can create reliable and efficient deployment pipelines.

Remember to focus on automation, testing, monitoring, and continuous improvement of your CI/CD processes.