Ngừng đánh số phiên bản thủ công: Tự động hóa quy trình Release với Semantic Release

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Nỗi khổ khi Release thủ công và Sự tiện lợi của Tự động hóa

Chúng ta đều đã từng trải qua cảm giác này: chiều Thứ Sáu, bạn đang căng mắt nhìn vào Git log để quyết định xem mười commit vừa rồi nên tăng phiên bản minor hay patch. Trong một quy trình thủ công điển hình, lập trình viên phải cập nhật package.json bằng tay, tự viết CHANGELOG.md và push các tag. Quy trình này rất dễ xảy ra sai sót. Một lỗi bug fix bị bỏ sót trong ghi chú hoặc quên tăng phiên bản có thể làm hỏng các dependency hạ nguồn hoặc gây nhầm lẫn cho người dùng.

Tự động hóa thay đổi hoàn toàn cuộc chơi. Thay vì đoán mò, một công cụ sẽ phân tích lịch sử commit của bạn để xác định bước tiếp theo hợp lý trong Semantic Versioning (SemVer). Trong một dự án gần đây, đội ngũ của chúng tôi đã chuyển sang mô hình này và cắt giảm thời gian release từ 20 phút phối hợp thủ công xuống còn con số không. Hệ thống hoạt động trơn tru và các bản release diễn ra một cách ổn định đến mức nhàm chán—đúng như những gì chúng nên có.

Sự thay đổi thực sự nằm ở việc chuyển “nguồn sự thật” (source of truth) từ trí nhớ của lập trình viên sang chính mã nguồn. Khi các thông điệp commit (commit message) tuân theo một tiêu chuẩn, việc release trở thành một sản phẩm phụ tự nhiên của quá trình làm việc. Bạn sẽ không còn phải “thực hiện release” nữa mà chỉ đơn giản là đẩy code lên.

Semantic Release có phù hợp với đội ngũ của bạn không?

Bạn cần cân nhắc giữa lợi ích tức thì và kỷ luật cần thiết để duy trì hệ thống.

Ưu điểm

  • Sự nhất quán tuyệt đối (Zero-Touch Consistency): Mọi bản release đều tuân theo logic toán học. Bạn sẽ không bao giờ vô tình nhảy cóc số phiên bản nữa.
  • Changelog tức thì: Công cụ tự động tạo file CHANGELOG.md. Nó phân loại các tính năng (features), bản sửa lỗi (fixes) và các thay đổi lớn (breaking changes) vào các danh mục gọn gàng cho người dùng.
  • Lịch sử Git sạch sẽ: Nó buộc đội ngũ phải viết commit message có ý nghĩa. Sẽ không còn những commit kiểu “fixed stuff” hay “updated CSS”.
  • Lập trình viên tập trung hơn: Sau khi Pull Request được merge, công việc của lập trình viên đã hoàn tất. CI/CD sẽ lo phần còn lại.

Những điều cần lưu ý

  • Tiêu chuẩn nghiêm ngặt: Mọi người tham gia đều phải tuân thủ quy chuẩn Conventional Commits. Một commit sai quy tắc như “hotfix” (thay vì fix: ...) có thể làm tắc nghẽn pipeline.
  • Cấu hình ban đầu: Bạn cần dành khoảng 30 phút để thiết lập GitHub secrets và quyền CI trước bản release đầu tiên.

Bản thiết kế cho một Pipeline chuyên nghiệp

Để xây dựng một quy trình vững chắc, tôi khuyên bạn nên sử dụng một stack công cụ tương thích tốt với các công cụ DevOps hiện đại. Ngay cả khi bạn không sử dụng JavaScript, công cụ dựa trên Node này vẫn là tiêu chuẩn ngành cho việc tự động hóa release:

  • Conventional Commits: Ngôn ngữ mà hệ thống tự động hóa của bạn sử dụng (ví dụ: feat:, fix:).
  • GitHub Actions: Bộ máy thực thi script release của bạn.
  • Các Plugin chính:
    • commit-analyzer: Quyết định xem bạn có cần tăng phiên bản hay không.
    • release-notes-generator: Soạn thảo bản tóm tắt cho người đọc.
    • changelog: Cập nhật file CHANGELOG.md thực tế.
    • git: Push phiên bản đã cập nhật và changelog trở lại kho lưu trữ (repo).

Hướng dẫn triển khai từng bước

Dưới đây là cách tích hợp hệ thống này vào một dự án từ đầu.

Bước 1: Cài đặt bộ công cụ

Thêm gói cốt lõi và các plugin thiết yếu vào các dependency phát triển (dev dependencies) của bạn.

npm install --save-dev semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github

Bước 2: Cấu hình Logic Release

Tạo file .releaserc trong thư mục gốc. File này đóng vai trò là “bộ não” của quy trình release, xác định chính xác điều gì sẽ xảy ra khi bạn merge vào nhánh main.

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/changelog",
      { "changelogFile": "CHANGELOG.md" }
    ],
    "@semantic-release/npm",
    [
      "@semantic-release/git",
      {
        "assets": ["package.json", "CHANGELOG.md"],
        "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ],
    "@semantic-release/github"
  ]
}

Tag [skip ci] là cực kỳ quan trọng. Nó báo cho GitHub Actions không bắt đầu một build mới khi bot push bản cập nhật phiên bản, nhằm tránh vòng lặp vô tận.

Bước 3: Làm chủ ngôn ngữ Commit

Việc đánh số phiên bản giờ đây gắn liền với cách bạn viết. Dưới đây là cách tính toán trong thực tế:

  • fix: xử lý rò rỉ bộ nhớ -> Patch (v1.0.0 lên v1.0.1)
  • feat: thêm đăng nhập Google OAuth -> Minor (v1.0.1 lên v1.1.0)
  • feat!: ngừng hỗ trợ Node 14 -> Major (v1.1.0 lên v2.0.0)

Bước 4: Tự động hóa với GitHub Actions

Tạo file .github/workflows/release.yml. Script này sẽ kích hoạt quá trình release mỗi khi bạn push lên nhánh main. Hãy đảm bảo thiết lập fetch-depth: 0 để công cụ có thể xem được toàn bộ lịch sử commit của bạn.

name: Release
on:
  push:
    branches: [main]

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      issues: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: "lts/*"
      - run: npm install
      - env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

Bước 5: Kiểm tra và Khởi chạy

Push một commit bắt đầu bằng feat: và theo dõi tab “Actions”. Bạn sẽ thấy bot phân tích commit, gắn tag cho repo và tạo một GitHub Release. Theo kinh nghiệm của tôi, mặc dù lần thiết lập đầu tiên mất 30 phút, nhưng nó sẽ mang lại giá trị ngay trong tuần đầu tiên. Nó loại bỏ yếu tố con người, đảm bảo việc đánh số phiên bản luôn chính xác về mặt logic và người dùng luôn biết chính xác những gì đã thay đổi.

Share: