Tự động hóa quy trình triển khai ứng dụng Web tĩnh với GitHub Actions
Trong kỷ nguyên DevOps hiện đại, việc tự động hóa quy trình xây dựng và triển khai (CI/CD) không còn là điều xa xỉ mà là yêu cầu bắt buộc để đảm bảo tốc độ và sự ổn định của sản phẩm. GitHub Actions cung cấp một nền tảng mạnh mẽ giúp các kỹ sư phần mềm biến kho lưu trữ mã nguồn thành một nhà máy tự động, nơi mỗi lần bạn đẩy code lên sẽ kích hoạt một chuỗi công việc kiểm tra và đưa sản phẩm lên môi trường thực tế mà không cần can thiệp thủ công. Bài viết này sẽ đi sâu vào việc thiết lập một quy trình CI/CD chuyên nghiệp cho các dự án Web tĩnh (Static Website) như React, Vue hoặc Next.js, tự động build và deploy lên GitHub Pages. Đây là một giải pháp miễn phí, an toàn và cực kỳ hiệu quả cho các dự án cá nhân cũng như doanh nghiệp nhỏ.
Giới thiệu về quy trình và lợi ích
Khi làm việc với các framework hiện đại, quy trình phát triển thường bao gồm nhiều bước phức tạp: cài đặt phụ thuộc, chạy bộ kiểm thử (unit test, e2e test), biên dịch mã nguồn sang JavaScript tối ưu và cuối cùng là xuất ra các file HTML, CSS, JS để máy khách có thể truy cập. Nếu thực hiện thủ công, bạn dễ mắc lỗi do con người, bỏ sót bước hoặc làm chậm tiến độ giao hàng. GitHub Actions giải quyết vấn đề này bằng cách cung cấp các runner (máy ảo) để thực thi kịch bản đã định nghĩa trước trong file cấu hình YAML. Mỗi khi một sự kiện xảy ra như commit mới vào branch master, hệ thống sẽ tự động kích hoạt workflow. Kết quả là quy trình này đảm bảo tính nhất quán, giúp phát hiện lỗi sớm ngay trước khi deploy và rút ngắn đáng kể thời gian từ khi lập trình viên viết code đến khi người dùng sử dụng được tính năng đó.
Chuẩn bị môi trường dự án trước khi cấu hình
Trước khi viết kịch bản CI/CD, bạn cần đảm bảo dự án của mình đã được đặt trên GitHub với một cấu trúc chuẩn. Dự án phải có file package.json để quản lý các thư viện và script build. Đặc biệt, nếu dự án sử dụng Next.js hoặc các framework cần server để serve, bạn cần cấu hình build xuất ra folder tĩnh (thường là build hoặc dist) thay vì server code. Bước quan trọng nhất là bạn cần kích hoạt tính năng GitHub Pages trong phần Settings của repository. Truy cập vào Settings, chọn mục Pages và thiết lập source là Deploy from a branch, chọn branch là main hoặc master, và folder là root. Lưu ý rằng khi sử dụng Actions để deploy, chúng ta thường sẽ chỉ định folder output là folder chứa kết quả build, ví dụ như build hoặc dist, để tránh xung đột với file cấu hình.
Thực hiện từng bước thiết lập GitHub Actions
Bước 1: Tạo thư mục workflows
Để GitHub Actions nhận diện workflow, bạn cần tạo một thư mục đặc biệt trong root của repository. Thư mục này bắt buộc phải có tên workflows. Nếu dự án của bạn chưa có thư mục này, hãy tạo nó ra ngay lập tức. Đây là nơi chứa tất cả các file định nghĩa logic hoạt động của pipeline của bạn. Bạn có thể tạo thư mục này trực tiếp trên giao diện GitHub bằng cách click vào biểu tượng New file và nhập tên thư mục, hoặc nếu làm việc trên máy tính, hãy sử dụng lệnh terminal để tạo.
mkdir -p .github/workflows
Sau khi tạo xong thư mục, bạn có thể di chuyển vào thư mục này để bắt đầu tạo file cấu hình. Việc tổ chức file cấu hình nằm trong thư mục .github/workflows giúp hệ thống tự động quét và hiển thị các workflow trên tab Actions của repository mà không cần cấu hình gì thêm.
Bước 2: Viết file cấu hình workflow YAML
Đây là bước quan trọng nhất trong toàn bộ quy trình. Bạn sẽ tạo một file có đuôi .yml, ví dụ là deploy.yml. File này sẽ chứa các định nghĩa về sự kiện kích hoạt (on), các job cần thực thi, và các bước (steps) cụ thể. Logic của workflow này bao gồm: kích hoạt khi code được đẩy vào branch main, sử dụng runner Ubuntu, cài đặt Node.js, pull mã nguồn, cài đặt phụ thuộc, chạy quá trình build và cuối cùng là deploy kết quả build lên GitHub Pages. Bạn cần định nghĩa token cá nhân hoặc token tự động để có quyền ghi vào Pages.
Dưới đây là một mẫu cấu hình đầy đủ dành cho các dự án React hoặc Vue, nơi output build nằm trong folder build hoặc dist:
name: Deploy Static Site to GitHub Pages
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
env:
CI: false
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
publish_branch: gh-pages
keep_files: true
Trong đoạn mã trên, bạn cần chú ý một số điểm then chốt. Biến publish_dir được đặt là ./build, tương ứng với thư mục đầu ra của quá trình build trên React. Nếu bạn dùng Vue hoặc Next.js (mode static), thư mục này thường là ./dist. Bạn có thể thay đổi biến này tùy theo cấu hình framework của mình. Ngoài ra, việc thiết lập env: CI: false trong bước build là một mẹo nhỏ nhưng rất quan trọng để ngăn chặn các lỗi cảnh báo không cần thiết hoặc các quy tắc kiểm duyệt nghiêm ngặt trong môi trường CI có thể làm gián đoạn quá trình build.
Bước 3: Xử lý các trường hợp đặc biệt và cấu hình nâng cao
Không phải lúc nào việc build cũng thành công ngay lập tức. Một vấn đề phổ biến xảy ra khi deploy lên GitHub Pages là các đường dẫn trong file HTML hoặc JavaScript không được tương thích với cấu trúc thư mục của Pages. Nếu bạn đang host site ở một sub-path (ví dụ: example.com/my-site), bạn cần cấu hình biến BASE_PATH trong file config của dự án (như package.json hoặc react-app-env.js) để trỏ đúng vào tên repository hoặc sub-folder. Khi đó, trong file workflow, bạn cần truyền biến này vào môi trường build để quá trình tạo link tương đối chính xác. Ngoài ra, nếu dự án có sử dụng biến môi trường nhạy cảm như API Key, bạn tuyệt đối không được hardcode trong file yaml mà phải đi vào Settings > Secrets and variables > Actions của repository để thêm secret, sau đó gọi trong workflow bằng cú pháp ${{ secrets.TEN_BIEN }}.
Để tăng tốc độ pipeline, bạn nên tận dụng tính năng cache của npm hoặc yarn như đã định nghĩa trong bước Setup Node.js. Dòng cache: 'npm' sẽ tự động lưu trữ thư mục node_modules vào cache của GitHub Action. Ở các lần build tiếp theo, nếu hash của file package-lock.json không thay đổi, hệ thống sẽ khôi phục node_modules từ cache thay vì cài đặt lại từ đầu, giúp giảm thời gian build xuống chỉ còn vài giây thay vì vài phút.
Lưu ý quan trọng khi vận hành
Việc thiết lập CI/CD thành công không chỉ nằm ở file yaml mà còn ở cách bạn xử lý các sự cố. Đầu tiên, luôn luôn kiểm tra tab Actions trên giao diện GitHub để xem trạng thái của pipeline. Nếu thấy chữ màu đỏ (Failed), hãy click vào để xem log chi tiết. Log thường sẽ chỉ ra lỗi ở bước nào, từ đó bạn có thể đoán biết nguyên nhân: lỗi package.json, lỗi build do code sai, hoặc lỗi do cấu hình publish_dir không đúng. Thứ hai, hãy cẩn trọng với việc commit file .env chứa thông tin nhạy cảm vào repository. GitHub Pages sẽ public toàn bộ code, nếu bạn để lộ secret trong file config, kẻ xấu có thể truy cập ngay lập tức. Luôn sử dụng .gitignore để loại bỏ file .env và dùng Secrets trong GitHub Actions để quản lý.
Thứ ba, hãy chú ý đến vấn đề "Race condition" khi có nhiều commit liên tiếp. GitHub Actions có thể chạy song song nhiều job nếu bạn đẩy nhiều lần trong thời gian ngắn, dẫn đến việc một job deploy đè lên job khác chưa chạy xong. Để tránh điều này, bạn có thể cấu hình concurrency trong file workflow để hủy các job đang chạy nếu có job mới khởi động, đảm bảo chỉ có phiên bản mới nhất được deploy. Cuối cùng, nếu dự án sử dụng Next.js hoặc các framework SSR (Server-Side Rendering), GitHub Pages không phải là lựa chọn tối ưu vì nó chỉ hỗ trợ Static Hosting. Trong trường hợp đó, bạn nên cân nhắc sử dụng Vercel hoặc Netlify để tích hợp sẵn serverless function.
Kết luận
Việc tích hợp GitHub Actions vào quy trình phát triển của bạn là một bước nhảy vọt về chất lượng và hiệu suất công việc. Bằng cách tự động hóa quy trình build và deploy cho các dự án Web tĩnh, bạn không chỉ tiết kiệm được hàng giờ làm việc thủ công mỗi tuần mà còn loại bỏ được rủi ro con người trong việc triển khai. Quy trình này mang lại sự tin tưởng cho cả đội ngũ phát triển và khách hàng khi mọi thay đổi đều được kiểm thử và đưa lên môi trường thực tế một cách liền mạch. Với kiến thức về việc tạo file workflows, cấu hình steps và xử lý các trường hợp đặc biệt, bạn hoàn toàn có thể mở rộng quy trình này cho các dự án phức tạp hơn, bao gồm cả các ứng dụng dynamic hoặc microservices. Hãy bắt đầu thử nghiệm ngay hôm nay với một dự án nhỏ để trải nghiệm sức mạnh của tự động hóa trong kỷ nguyên DevOps.