0

[Java Backend Zero to Hello] [Phase 7] BÀI 7.6: CI/CD VỚI GITHUB ACTIONS

📚 Series: Java Backend Zero to Hello 📂 Phân đoạn: Phase 7: Testing & DevOps 📖 Nội dung: BÀI 7.6: CI/CD VỚI GITHUB ACTIONS 💡 Khóa học lập trình Backend Java & Spring Boot chuẩn doanh nghiệp từ con số 0.


BÀI 7.6: CI/CD VỚI GITHUB ACTIONS

Mục tiêu

  • Hiểu CI/CD
  • Tạo GitHub Actions workflow
  • Build, test, deploy tự động
  • Tích hợp Docker

1. CI/CD LÀ GÌ?

  • CI (Continuous Integration) - Tích hợp liên tục: tự động build, test khi push code
  • CD (Continuous Deployment/Delivery) - Triển khai liên tục: tự động deploy khi pass test

Lợi ích

  • Phát hiện lỗi sớm
  • Giảm thời gian deploy
  • Tăng chất lượng code
  • Tự động hóa quy trình

2. GITHUB ACTIONS

2.1 Khái niệm

  • Workflow - Quy trình CI/CD
  • Job - Tập các step
  • Step - Hành động đơn lẻ
  • Action - Đơn vị tái sử dụng
  • Runner - Máy chạy workflow

2.2 Cấu trúc file

.github/
└── workflows/
    ├── ci.yml
    └── deploy.yml

3. WORKFLOW CƠ BẢN

3.1 .github/workflows/ci.yml

name: CI

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

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Cache Maven dependencies
        uses: actions/cache@v3
        with:
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-m2-

      - name: Build with Maven
        run: mvn clean package -DskipTests

      - name: Run tests
        run: mvn test

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: app-jar
          path: target/*.jar

4. TRIGGERS

on:
  # Push
  push:
    branches: [ main ]
    paths: [ 'src/**' ]  # Chỉ khi thay đổi src

  # Pull Request
  pull_request:
    branches: [ main ]

  # Schedule (cron)
  schedule:
    - cron: '0 0 * * *'  # Mỗi ngày lúc 0h

  # Manual
  workflow_dispatch:

  # Khi release
  release:
    types: [ published ]

5. JOBS VÀ STEPS

5.1 Multiple jobs

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mvn test

  build:
    needs: test  # Chờ test xong
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mvn package

  deploy:
    needs: [test, build]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - run: echo "Deploying..."

5.2 Matrix strategy

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        java-version: [17, 21]
    steps:
      - uses: actions/setup-java@v4
        with:
          java-version: ${{ matrix.java-version }}
      - run: mvn test

6. SERVICES (DATABASE TRONG CI)

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:8
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: testdb
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5

    steps:
      - uses: actions/checkout@v4
      - run: mvn test
        env:
          SPRING_DATASOURCE_URL: jdbc:mysql://localhost:3306/testdb

7. SECRETS

7.1 Cấu hình

Vào Settings → Secrets and variables → Actions → New repository secret

7.2 Sử dụng

steps:
  - name: Deploy
    run: ./deploy.sh
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

8. BUILD VÀ PUSH DOCKER IMAGE

jobs:
  docker:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            username/myapp:latest
            username/myapp:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

9. DEPLOY LÊN SERVER

9.1 SSH Deploy

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Deploy to server
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /app
            git pull
            docker-compose pull
            docker-compose up -d

9.2 Deploy lên Cloud

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to AWS
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
          aws-region: ap-southeast-1

      - name: Deploy to ECS
        run: |
          aws ecs update-service \
            --cluster my-cluster \
            --service my-service \
            --force-new-deployment

10. WORKFLOW HOÀN CHỈNH

name: CI/CD Pipeline

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

env:
  REGISTRY: docker.io
  IMAGE_NAME: username/myapp

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: test
          POSTGRES_DB: testdb
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Cache Maven
        uses: actions/cache@v3
        with:
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

      - name: Run tests
        run: mvn test
        env:
          SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/testdb

      - name: Upload coverage
        uses: codecov/codecov-action@v3

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Build JAR
        run: mvn clean package -DskipTests

      - name: Build & Push Docker
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Deploy
        run: echo "Deploying to production..."

11. BADGES

Thêm badge vào README:

![CI](https://github.com/user/repo/workflows/CI/badge.svg)

12. BÀI TẬP THỰC HÀNH

Bài 1: CI Workflow

Tạo workflow build và test cho Spring Boot project.

Bài 2: Docker Build

Thêm job build và push Docker image.

Bài 3: Auto Deploy

Setup auto deploy khi merge vào main.


13. TÓM TẮT

Khái niệm Mô tả
Workflow Quy trình CI/CD
Job Tập step
Step Hành động
Action Đơn vị tái sử dụng
Trigger Sự kiện kích hoạt
Secrets Biến bí mật
Matrix Chạy nhiều config

Bài tiếp theo: 7.7 Triển khai lên Cloud


🧭 Điều hướng bài học

⭐ Hãy bookmark (clip) lại series để tiện theo dõi các bài học tiếp theo nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí