99 Ngày Spring — Ngày 94: CI/CD cho Spring Boot
Triển khai bằng tay phụ thuộc vào trí nhớ của một người và chạy khác nhau mỗi lần. CI/CD biến đường đi từ commit tới production thành một pipeline lặp lại được: mọi thay đổi đều được build và test theo cùng một cách, và thứ được triển khai chính là thứ đã được kiểm tra. Bài này dùng GitHub Actions, nhưng nguyên tắc áp dụng cho mọi công cụ.

1. CI: build và test mọi thay đổi
Workflow nằm trong .github/workflows và chạy trên mỗi pull request cũng như mỗi lần đẩy vào main. Bước setup-java cài JDK 21 và cache thư mục Maven để các lần chạy sau nhanh hơn. Lệnh verify chạy cả unit test lẫn integration test; với Testcontainers, runner của GitHub đã có sẵn Docker. Pull request không qua CI thì không được merge.
name: ci
on:
pull_request:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
cache: maven
- run: ./mvnw -B verify2. Đóng image và đánh phiên bản bất biến
Sau khi test qua trên main, pipeline đóng image và đẩy lên registry. Tag của image là mã commit: nó không bao giờ bị ghi đè, nên luôn biết chính xác code nào đang chạy và rollback chỉ là triển khai lại tag cũ. Tag latest không nói được điều đó. Phiên bản dạng 1.4.0 cho người đọc có thể gắn thêm vào cùng image khi phát hành.
image:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions: { contents: read, packages: write }
env:
IMAGE: ghcr.io/${{ github.repository }}:${{ github.sha }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: 21, cache: maven }
- run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- run: ./mvnw -B -DskipTests spring-boot:build-image -Dspring-boot.build-image.imageName=$IMAGE
- run: docker push $IMAGE3. Build một lần, triển khai nhiều môi trường
Cùng một image đi qua staging rồi tới production; thứ khác nhau chỉ là cấu hình, như đã nói ở ngày 91. Build lại cho từng môi trường nghĩa là thứ lên production chưa từng được test. GitHub Environments cho phép gắn secret riêng và quy tắc bảo vệ cho từng môi trường: staging tự động, production cần người duyệt.
deploy-staging:
needs: image
environment: staging
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh staging ${{ github.sha }}
deploy-production:
needs: deploy-staging
environment: production # required reviewers configured in GitHub
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh production ${{ github.sha }}4. Những điều làm pipeline đáng tin
Pipeline chỉ có giá trị khi đội tin kết quả của nó. Test chập chờn làm mọi người quen bấm chạy lại và bỏ qua lỗi thật. Pipeline chậm làm người ta gom nhiều thay đổi vào một lần, tăng rủi ro. Thay đổi schema database phải tương thích ngược với phiên bản code đang chạy, vì trong lúc rolling update cả hai phiên bản cùng tồn tại.
Giữ CI dưới khoảng mười phút; song song hóa và cache trước khi cắt test.
Secret của pipeline nằm trong kho secret của nền tảng; ưu tiên OIDC thay cho khóa dài hạn.
Ghim phiên bản action và base image.
Sau khi triển khai, kiểm tra health và tự rollback nếu thất bại.
Chạy migration bằng Flyway theo kiểu mở rộng trước, thu hẹp sau.
CI/CD tốt làm cho việc triển khai trở nên nhàm chán, và đó là mục tiêu. Ngày 95 xem nơi image được đưa tới: Kubernetes.
Tài liệu đối chiếu
https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-java-with-maven
https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment
Site Admin
Engineer and writer. Building things with TypeScript and distributed systems.
Bình luận (0)
Bạn cần đăng nhập bằng Google để bình luận.
Hãy là người bình luận đầu tiên.


