GitHub Actions cho ASP.NET Core: Tự động hóa quy trình Build, Test và Deploy (CI/CD)

Chào mừng các bạn trở lại với series “ASP.NET Core Roadmap“! Trên hành trình trở thành một lập trình viên .NET chuyên nghiệp, chúng ta đã cùng nhau đi qua nhiều khái niệm nền tảng và nâng cao, từ việc làm chủ ngôn ngữ C#, hiểu rõ Hệ sinh thái .NET và sử dụng .NET CLI, đến việc quản lý mã nguồn hiệu quả với Git, xây dựng API với RESTful hay gRPC, và đặc biệt là làm chủ các kỹ thuật kiểm thử (Unit Test, Integration Test, E2E Test). Hôm nay, chúng ta sẽ bước sang một khía cạnh cực kỳ quan trọng trong quy trình phát triển phần mềm hiện đại: **Tự động hóa quy trình Tích hợp Liên tục (CI) và Triển khai Liên tục (CD)** với một công cụ mạnh mẽ và phổ biến: **GitHub Actions**.

Trong thế giới phát triển phần mềm nhanh chóng ngày nay, việc dựa vào các quy trình thủ công để build, test và triển khai ứng dụng không còn hiệu quả nữa. Nó tốn thời gian, dễ xảy ra lỗi do con người, và tạo ra sự không nhất quán giữa các môi trường. Đây chính là lúc Tích hợp Liên tục (CI) và Triển khai/Phân phối Liên tục (CD) phát huy sức mạnh.

CI/CD Quan Trọng Thế Nào Đối Với Dự Án .NET Của Bạn?

Hãy tưởng tượng một dự án có nhiều lập trình viên cùng đóng góp. Mỗi khi một tính năng mới được hoàn thành, mã nguồn cần được:

  1. Tích hợp vào nhánh chính (ví dụ: main hoặc develop).
  2. Build để tạo ra các file thực thi.
  3. Chạy tất cả các bài kiểm thử (Unit Test, Integration Test, v.v.) để đảm bảo không có lỗi hoặc regression.
  4. Đóng gói ứng dụng sẵn sàng cho việc triển khai.
  5. Triển khai lên môi trường Staging hoặc Production.

Nếu thực hiện thủ công, quy trình này sẽ rất chậm, đặc biệt khi có nhiều thay đổi diễn ra hàng ngày. CI/CD ra đời để giải quyết vấn đề này:

  • Tích hợp Liên tục (CI – Continuous Integration): Tự động hóa việc build và chạy kiểm thử mỗi khi có thay đổi mã nguồn được đẩy lên repository. Mục tiêu là phát hiện lỗi tích hợp càng sớm càng tốt, giảm thiểu “đau đớn” khi merge code.
  • Triển khai/Phân phối Liên tục (CD – Continuous Delivery/Deployment): Tự động hóa quy trình từ sau khi build/test thành công cho đến khi ứng dụng sẵn sàng hoặc được triển khai tự động lên môi trường đích.

Đối với các ứng dụng ASP.NET Core, việc tự động hóa quy trình CI/CD giúp chúng ta:

  • **Phản hồi nhanh hơn:** Biết ngay lập tức liệu thay đổi mới có phá vỡ build hoặc các bài kiểm thử hay không.
  • **Giảm thiểu lỗi:** Quy trình tự động nhất quán, không bị ảnh hưởng bởi các yếu tố con người.
  • **Tăng tốc độ phát hành:** Đưa các tính năng mới đến tay người dùng nhanh hơn và thường xuyên hơn.
  • **Nâng cao chất lượng mã nguồn:** Việc chạy kiểm thử tự động và thường xuyên khuyến khích viết code chất lượng cao hơn.
  • **Giảm rủi ro khi triển khai:** Đảm bảo rằng các build được triển khai đã trải qua quy trình kiểm tra chặt chẽ.

Và GitHub Actions chính là một công cụ tuyệt vời để biến những lợi ích này thành hiện thực cho dự án ASP.NET Core của bạn.

GitHub Actions Là Gì?

GitHub Actions là một nền tảng CI/CD tích hợp trực tiếp với GitHub. Nó cho phép bạn tự động hóa các workflow (quy trình làm việc) ngay trong repository của mình. Bạn có thể build, test, và triển khai code trực tiếp từ GitHub.

Các thành phần chính của GitHub Actions mà bạn cần biết:

  • Workflow: Một quy trình tự động hóa có thể tùy chỉnh. Workflow được định nghĩa bằng file YAML và được lưu trữ trong thư mục .github/workflows trong repository của bạn.
  • Event: Một hoạt động cụ thể xảy ra trong repository của bạn (ví dụ: push code, tạo pull request, mở issue) hoặc một sự kiện bên ngoài (ví dụ: cron schedule) có thể kích hoạt một workflow.
  • Job: Một tập hợp các bước (steps) được thực thi trên cùng một runner. Một workflow có thể có nhiều job, và các job này có thể chạy song song hoặc tuần tự.
  • Step: Một tác vụ riêng lẻ trong một job. Một step có thể là việc chạy một command (ví dụ: dotnet build) hoặc sử dụng một Action (một tác vụ đóng gói sẵn).
  • Action: Một ứng dụng tùy chỉnh (custom application) thực hiện một tác vụ phức tạp nhưng có thể tái sử dụng. Các Action có thể được viết bởi cộng đồng hoặc chính GitHub (ví dụ: checkout mã nguồn, cài đặt môi trường .NET). Bạn có thể tìm các Action sẵn có trên GitHub Marketplace.
  • Runner: Máy chủ (virtual machine hoặc container) nơi các job được thực thi. GitHub cung cấp các runner được host sẵn trên các hệ điều hành khác nhau (Ubuntu, Windows, macOS). Bạn cũng có thể tự host runner của mình (self-hosted runner).

Mối quan hệ đơn giản là: Một **Event** kích hoạt một **Workflow**, Workflow chứa một hoặc nhiều **Job**, mỗi Job chạy trên một **Runner** và chứa một chuỗi các **Step**. Mỗi **Step** thực hiện một command hoặc gọi một **Action**.

Thiết Lập Workflow Đầu Tiên cho ASP.NET Core

Để bắt đầu với GitHub Actions cho dự án ASP.NET Core, bạn cần tạo một thư mục có tên .github/workflows ở thư mục gốc của repository. Bên trong thư mục này, bạn sẽ tạo các file YAML (với đuôi `.yml` hoặc `.yaml`) để định nghĩa các workflow của mình.

Hãy cùng xây dựng một workflow đơn giản để build và chạy kiểm thử cho ứng dụng ASP.NET Core của chúng ta mỗi khi có code được đẩy lên nhánh main hoặc một pull request được tạo ra.

Bước 1: Tạo thư mục và file Workflow

Trong thư mục gốc của dự án, tạo cấu trúc:

your-aspnetcore-project/
├── .github/
│   └── workflows/
│       └── ci-build-test.yml
└── ... (các file và thư mục dự án khác)

Bước 2: Viết nội dung file ci-build-test.yml

Mở file ci-build-test.yml và thêm nội dung sau:

name: ASP.NET Core CI

on:
  push:
    branches: [ main ] # Kích hoạt workflow khi có push code lên nhánh main
  pull_request:
    branches: [ main ] # Kích hoạt workflow khi có pull request đến nhánh main

jobs:
  build-and-test: # Tên của job
    runs-on: ubuntu-latest # Chọn runner là máy ảo Ubuntu mới nhất

    steps:
    - name: Checkout code # Step 1: Lấy mã nguồn từ repository
      uses: actions/checkout@v4 # Sử dụng action có sẵn để checkout code

    - name: Setup .NET # Step 2: Cài đặt môi trường .NET SDK
      uses: actions/setup-dotnet@v4 # Sử dụng action có sẵn để setup .NET
      with:
        dotnet-version: '8.0.x' # Chỉ định phiên bản .NET SDK (hoặc phiên bản phù hợp với dự án của bạn)
        #dotnet-version: '6.0.x' # Ví dụ cho .NET 6

    - name: Restore dependencies # Step 3: Restore các package NuGet
      run: dotnet restore

    - name: Build project # Step 4: Build ứng dụng
      run: dotnet build --configuration Release --no-restore # --no-restore vì đã chạy restore ở trên

    - name: Run tests # Step 5: Chạy các bài kiểm thử
      run: dotnet test --no-build --verbosity normal # --no-build vì đã build ở trên
      # Đảm bảo dự án test của bạn có chứa các test cases (xUnit, NUnit, MSTest)

Hãy cùng phân tích từng phần của file YAML này:

  • name: ASP.NET Core CI: Đặt tên cho workflow, xuất hiện trên giao diện GitHub.
  • on:: Định nghĩa các sự kiện kích hoạt workflow này.
    • push: branches: [ main ]: Khi có commit được push lên nhánh main.
    • pull_request: branches: [ main ]: Khi có pull request được tạo hoặc cập nhật nhắm vào nhánh main.
  • jobs:: Bắt đầu định nghĩa các job. Workflow này chỉ có một job tên là build-and-test.
    • runs-on: ubuntu-latest: Chỉ định runner sẽ chạy job này. ubuntu-latest là một máy ảo Ubuntu do GitHub quản lý.
    • steps:: Liệt kê các bước sẽ được thực hiện tuần tự trong job này.
      • - name: Checkout code: Tên hiển thị của bước.
      • uses: actions/checkout@v4: Sử dụng Action checkout phiên bản 4 để tải mã nguồn từ repository về runner. Đây là bước cần thiết đầu tiên.
      • - name: Setup .NET: Tên bước.
      • uses: actions/setup-dotnet@v4: Sử dụng Action setup-dotnet phiên bản 4 để cài đặt .NET SDK trên runner.
      • with: dotnet-version: '8.0.x': Tham số cho Action setup-dotnet, chỉ định phiên bản .NET SDK cần cài đặt. Hãy thay đổi nếu dự án của bạn dùng phiên bản khác (ví dụ: '6.0.x').
      • - name: Restore dependencies: Tên bước.
      • run: dotnet restore: Chạy lệnh dotnet restore để tải các package NuGet cần thiết.
      • - name: Build project: Tên bước.
      • run: dotnet build --configuration Release --no-restore: Chạy lệnh dotnet build để biên dịch ứng dụng. --configuration Release để build ở chế độ Release, --no-restore để bỏ qua bước restore vì đã làm ở bước trước (giúp tối ưu thời gian).
      • - name: Run tests: Tên bước.
      • run: dotnet test --no-build --verbosity normal: Chạy lệnh dotnet test để chạy các bài kiểm thử. --no-build để bỏ qua build test project vì nó đã được build cùng với ứng dụng chính ở bước trước. Đảm bảo bạn đã viết các bài kiểm thử trong dự án của mình (sử dụng xUnit, NUnit, MSTest như đã học trong các bài trước).

Bước 3: Commit và Push code

Lưu file ci-build-test.yml, commit nó và push lên repository GitHub của bạn. Ngay khi bạn push (hoặc tạo Pull Request), GitHub sẽ tự động phát hiện file workflow mới và bắt đầu chạy job build-and-test.

Bạn có thể xem tiến trình thực thi workflow trong tab “Actions” trên trang repository GitHub của mình.

Xử Lý Các Thông Tin Nhạy Cảm (Secrets)

Ứng dụng ASP.NET Core thường cần truy cập các thông tin nhạy cảm như chuỗi kết nối cơ sở dữ liệu, khóa API, mật khẩu, v.v. (đặc biệt là khi triển khai). Bạn không bao giờ được lưu trữ các thông tin này trực tiếp trong file cấu hình trong repository. GitHub Actions cung cấp tính năng **Secrets** để lưu trữ các giá trị này một cách an toàn.

Cách sử dụng Secrets:

  1. Vào repository của bạn trên GitHub.
  2. Vào mục **Settings**.
  3. Trong menu bên trái, chọn **Secrets and variables** -> **Actions**.
  4. Chọn **New repository secret**.
  5. Nhập tên cho Secret (ví dụ: DATABASE_CONNECTION_STRING) và giá trị của nó.
  6. Nhấn **Add secret**.

Trong workflow YAML, bạn có thể truy cập Secret này bằng cú pháp ${{ secrets.YOUR_SECRET_NAME }}.

Ví dụ, nếu bạn cần một connection string cho bước kiểm thử tích hợp hoặc để build cấu hình triển khai:

# ... các bước trên
- name: Run integration tests # Bước chạy kiểm thử tích hợp (nếu có)
  run: dotnet test Tests/YourIntegrationTestsProject.csproj --no-build --verbosity normal
  env: # Sử dụng secrets như biến môi trường cho bước này
    ConnectionStrings__DefaultConnection: ${{ secrets.DATABASE_CONNECTION_STRING }}

Lưu ý: Secrets không hiển thị giá trị trong log của workflow, giúp bảo vệ thông tin của bạn.

Hoàn Thiện Quy Trình CI (Thêm Bước Publish)

Sau khi build và test thành công, bước tiếp theo trong quy trình CI thường là publish ứng dụng, tạo ra các file sẵn sàng để triển khai. Chúng ta sẽ thêm bước này vào workflow.

name: ASP.NET Core CI

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

env: # Định nghĩa biến môi trường dùng chung cho tất cả các steps trong job
  DOTNET_VERSION: '8.0.x' # Phiên bản .NET SDK
  BUILD_CONFIGURATION: 'Release' # Cấu hình build

jobs:
  build-test-publish: # Đổi tên job để phản ánh các bước thực hiện
    runs-on: ubuntu-latest

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

    - name: Setup .NET ${{ env.DOTNET_VERSION }}
      uses: actions/setup-dotnet@v4
      with:
        dotnet-version: ${{ env.DOTNET_VERSION }}

    - name: Restore dependencies
      run: dotnet restore

    - name: Build project
      run: dotnet build --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore

    - name: Run tests
      run: dotnet test --no-build --verbosity normal
      # env: # Có thể cần biến môi trường cho test tích hợp tại đây
      #   ConnectionStrings__DefaultConnection: ${{ secrets.DATABASE_CONNECTION_STRING }}

    - name: Publish application # Step 6: Publish ứng dụng
      run: dotnet publish --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --output ./publish

    - name: Upload Publish Artifact # Step 7: Lưu trữ kết quả publish dưới dạng artifact
      uses: actions/upload-artifact@v4
      with:
        name: web-app-${{ github.sha }} # Tên artifact (ví dụ: web-app-<commit-sha>)
        path: ./publish # Đường dẫn đến thư mục chứa kết quả publish
        # Lưu ý: Mặc định artifact sẽ tồn tại 90 ngày

Trong workflow cập nhật này:

  • Chúng ta đã thêm biến môi trường dùng chung (env) để dễ quản lý phiên bản .NET và cấu hình build.
  • Thêm bước Publish application sử dụng lệnh dotnet publish để tạo ra đầu ra cuối cùng của ứng dụng. --output ./publish chỉ định thư mục lưu trữ kết quả publish trên runner.
  • Thêm bước Upload Publish Artifact sử dụng Action actions/upload-artifact. Bước này cực kỳ quan trọng trong quy trình CI/CD, nó giúp lưu trữ file build/publish sau khi job hoàn thành. Các job CD sau này có thể tải artifact này xuống để triển khai thay vì phải build lại. github.sha là một biến mặc định của GitHub Actions, chứa SHA của commit hiện tại.

Bây giờ, mỗi khi push code hoặc tạo PR đến main, GitHub Actions sẽ tự động build, chạy tất cả kiểm thử, và nếu thành công, sẽ publish ứng dụng và lưu trữ kết quả dưới dạng artifact.

Bảng Tổng Kết Các Thành Phần Chính Của GitHub Actions Workflow

Để giúp bạn dễ hình dung lại các khái niệm, đây là bảng tóm tắt:

Thành Phần Mô Tả Cú Pháp YAML (Ví dụ)
Workflow Quy trình tự động hóa hoàn chỉnh Định nghĩa trong file .yml ở .github/workflows/
Event Sự kiện kích hoạt Workflow on:<br>  push:<br>    branches: [ main ]
Job Tập hợp các bước chạy trên một Runner jobs:<br>  my_job_name:
Runner Môi trường thực thi Job runs-on: ubuntu-latest
Step Tác vụ đơn lẻ trong Job Bắt đầu bằng - dưới mục steps:
Command Step Chạy một dòng lệnh run: dotnet build
Action Step Sử dụng một tác vụ đóng gói sẵn uses: actions/checkout@v4
Secrets Lưu trữ thông tin nhạy cảm an toàn Truy cập bằng ${{ secrets.MY_SECRET }}
Artifact Đầu ra của Job (file build, publish, test results) Sử dụng actions/upload-artifactactions/download-artifact

Các Trường Hợp Sử Dụng Phổ Biến Khác

Workflow trên chỉ là khởi đầu. Bạn có thể mở rộng GitHub Actions để tự động hóa nhiều khía cạnh khác của quy trình phát triển ASP.NET Core:

  • **Triển khai (CD):** Tạo các workflow riêng biệt (hoặc thêm job vào workflow hiện tại) để tự động triển khai ứng dụng lên các nền tảng như Azure App Services, AWS, Docker Hub (sau khi Docker hóa), Kubernetes, v.v. Bạn sẽ sử dụng các Action có sẵn hoặc tự tạo script triển khai.
  • **Kiểm tra chất lượng mã nguồn:** Tích hợp các công cụ phân tích tĩnh (static analysis) hoặc kiểm tra bảo mật.
  • **Gửi thông báo:** Gửi email, Slack messages khi workflow thành công hoặc thất bại.
  • **Chạy các tác vụ định kỳ:** Sử dụng trigger schedule để chạy workflow theo lịch trình (ví dụ: dọn dẹp dữ liệu cũ, tạo báo cáo).
  • **Tự động hóa Pull Request:** Chạy linter, formatter, kiểm tra commit message, v.v. trước khi cho phép merge PR.

Lợi Ích Khi Sử Dụng GitHub Actions cho .NET

Việc áp dụng GitHub Actions vào dự án ASP.NET Core mang lại nhiều lợi ích thiết thực:

  • **Tích hợp chặt chẽ:** Nằm ngay trong GitHub, không cần sử dụng dịch vụ CI/CD bên ngoài (trừ khi có yêu cầu đặc biệt).
  • **Miễn phí cho Public Repository:** Miễn phí thời gian chạy cho các public repository và có hạn mức miễn phí hàng tháng cho private repository.
  • **Dễ cấu hình:** Sử dụng YAML trực quan, dễ đọc và viết.
  • **Kho Actions phong phú:** Tiết kiệm thời gian với hàng ngàn Action có sẵn từ cộng đồng và GitHub Marketplace.
  • **Hỗ trợ đa nền tảng:** Chạy trên Ubuntu, Windows, macOS runners.
  • **Khả năng mở rộng:** Có thể tự host runner nếu cần môi trường tùy chỉnh hoặc hiệu năng cao hơn.
  • **Tăng cường sự hợp tác:** Mọi thành viên trong đội đều có thể thấy và hiểu quy trình CI/CD ngay trong repository.

Kết Luận

Tự động hóa quy trình build, test, và publish với GitHub Actions là một bước tiến quan trọng trong hành trình phát triển phần mềm hiện đại. Nó không chỉ giúp bạn tiết kiệm thời gian và công sức mà còn nâng cao đáng kể chất lượng và độ tin cậy của ứng dụng ASP.NET Core. Bằng việc tích hợp CI vào workflow hàng ngày, bạn và đội nhóm của mình sẽ phát hiện và sửa lỗi nhanh hơn, tự tin hơn khi tích hợp mã nguồn và sẵn sàng cho các bước triển khai tự động tiếp theo.

Bài viết này đã giới thiệu những kiến thức cơ bản nhất để bạn có thể bắt đầu. Hãy thử áp dụng vào dự án ASP.NET Core của riêng mình. Trong các bài viết tiếp theo của series Lộ trình .NET, chúng ta sẽ tìm hiểu sâu hơn về các chiến lược triển khai tự động (CD) cho ứng dụng ASP.NET Core trên các nền tảng khác nhau, tiếp tục hoàn thiện bức tranh về quy trình DevOps.

Nếu có bất kỳ câu hỏi nào, đừng ngần ngại để lại bình luận nhé! Chúc các bạn thành công!

Hẹn gặp lại trong bài viết tiếp theo!

Chỉ mục