Không có gì giết chết năng suất của nhà phát triển như các bản dựng bị hỏng và các bài kiểm tra không ổn định. Bạn có thể đã trải qua cảm giác thất vọng về mã được xây dựng hoàn hảo trên máy của mình nhưng lại thất bại một cách bí ẩn trong production hoặc các thử nghiệm vượt qua cục bộ nhưng lại thất bại trong CI mà không có lý do rõ ràng. Những vấn đề này xuất phát từ sự khác biệt giữa môi trường phát triển và xây dựng - các phiên bản Node.js khác nhau, thiếu biến môi trường hoặc các phần phụ thuộc được lưu trong bộ nhớ đệm che giấu các vấn đề thực sự.
GitHub Actions giải quyết những vấn đề này bằng cách cung cấp môi trường sạch sẽ, nhất quán cho mọi bản dựng. Khi quy trình xây dựng của bạn hoạt động giống hệt nhau dù chạy cục bộ hay trong CI, bạn sẽ loại bỏ được vấn đề "hoạt động trên máy của tôi" và xây dựng sự tự tin trong quy trình triển khai của mình.
Tại sao xây dựng vấn đề nhất quán
Nguyên tắc cơ bản của CI/CD đáng tin cậy là quy trình xây dựng của bạn phải giống hệt nhau ở mọi nơi nó chạy. Điều này có nghĩa là các phần phụ thuộc giống nhau, các biến môi trường giống nhau, các phiên bản công cụ giống nhau và các bước xây dựng giống nhau cho dù bạn đang xây dựng trên máy tính xách tay, trong CI hay trên máy của đồng nghiệp.
Hầu hết các vấn đề về xây dựng đều xuất phát từ sự khác biệt về môi trường. Môi trường phát triển cục bộ của bạn tích lũy các thay đổi theo thời gian - gói chung, tệp cấu hình, biến môi trường - khiến các bản dựng hoạt động cục bộ nhưng không hoạt động ở nơi khác. Môi trường CI sạch sẽ bộc lộ những phần phụ thuộc ẩn này và buộc bạn phải làm cho quy trình xây dựng của mình thực sự có thể tái tạo được.
Khi các bản dựng của bạn nhất quán, bạn sẽ có được sự tự tin rằng những gì vượt qua CI sẽ hoạt động trong production. Sự tự tin này cho phép thực hiện các hoạt động như triển khai tự động và giảm bớt lo lắng khi phát hành.
Thiết lập bản dựng Node.js đúng cách
Hãy xây dựng một quy trình làm việc Node.js vững chắc thể hiện các phương pháp xây dựng tốt nhất. Quy trình công việc này xử lý việc quản lý phụ thuộc, bộ nhớ đệm, thử nghiệm và xây dựng quá trình tạo artifact theo cách vừa nhanh chóng vừa đáng tin cậy.
name: Node.js Application Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '18'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Get the code
uses: actions/checkout@v4
# Set up Node.js with automatic npm caching
# The cache speeds up builds by avoiding repeated downloads
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
# Use npm ci instead of npm install for CI environments
# npm ci is faster and more reliable for automated builds
- name: Install dependencies
run: npm ci
# Run linting before tests to catch style issues early
- name: Check code style
run: npm run lint
# Run tests with coverage reporting
- name: Run tests
run: npm test -- --coverage --watchAll=false
env:
CI: true
# Upload coverage results to track code quality over time
- name: Upload coverage reports
uses: codecov/codecov-action@v3
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
# Build the application for production
- name: Build application
run: npm run build
env:
NODE_ENV: production
# Store the build output for deployment jobs
- name: Save build artifacts
uses: actions/upload-artifact@v4
with:
name: build-files
path: dist/
retention-days: 30
Quy trình công việc này tách việc kiểm tra và xây dựng thành các công việc khác nhau có thể chạy song song cho đến khi bản dựng cần có kết quả kiểm tra. Các chi tiết chính làm cho nó đáng tin cậy:
- Sử dụng
npm cithay vìnpm installđảm bảo cài đặt phụ thuộc rõ ràng, có thể lặp lại - Tùy chọn
cache: 'npm'trong nút thiết lập tăng tốc các bản dựng bằng cách lưu vào bộ đệm các gói đã tải xuống - Đặt
NODE_ENV=productioncho các bản dựng đảm bảo áp dụng tối ưu hóa production - Tải lên artifact duy trì kết quả đầu ra của bản dựng cho các công việc triển khai
Kiểm tra nhiều phiên bản Node.js
Các ứng dụng thực cần hoạt động trên các phiên bản Node.js khác nhau mà người dùng của bạn có thể có. Bản dựng ma trận cho phép bạn kiểm tra nhiều phiên bản một cách hiệu quả:
test:
runs-on: ubuntu-latest
# Test against multiple Node.js versions
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
Chiến lược ma trận tạo ra các công việc riêng biệt cho từng phiên bản Node.js, chạy chúng song song. Điều này giúp phát hiện sớm các vấn đề về khả năng tương thích trong khi vẫn đảm bảo thời gian xây dựng hợp lý.
Các mẫu xây dựng Python
Các dự án Python có yêu cầu xây dựng riêng nhưng nguyên tắc vẫn giữ nguyên. Sau đây là quy trình làm việc xử lý môi trường ảo, bộ nhớ đệm phụ thuộc và kiểm tra:
name: Python Application
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11']
steps:
- uses: actions/checkout@v4
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run linting
run: |
flake8 src tests
black --check src tests
- name: Run tests
run: |
pytest tests/ --cov=src --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
Quy trình làm việc của Python tuân theo các mẫu tương tự - thiết lập môi trường ngôn ngữ, cài đặt các phần phụ thuộc bằng bộ nhớ đệm, chạy kiểm tra chất lượng và thực hiện kiểm tra. Tùy chọn cache: 'pip' tăng tốc độ xây dựng bằng cách lưu vào bộ đệm các gói đã tải xuống.
Bản dựng dựa trên Docker
Một số ứng dụng cần Docker container cho quá trình xây dựng của chúng. GitHub Actions có thể xây dựng và kiểm tra Docker image một cách hiệu quả:
name: Docker Build
on: [push, pull_request]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Build the Docker image
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
# Test the built image
- name: Test Docker image
run: |
docker run --rm myapp:${{ github.sha }} npm test
# Save the image for deployment (optional)
- name: Save Docker image
run: |
docker save myapp:${{ github.sha }} | gzip > myapp.tar.gz
- name: Upload Docker image
uses: actions/upload-artifact@v4
with:
name: docker-image
path: myapp.tar.gz
Quy trình công việc này xây dựng Docker image, chạy thử nghiệm bên trong container để xác minh rằng nó hoạt động chính xác và tùy chọn lưu image dưới dạng artifact để triển khai.
Xử lý lỗi kiểm thử một cách khéo léo
Các thử nghiệm đôi khi sẽ thất bại và quy trình làm việc của bạn sẽ xử lý các lỗi theo cách cung cấp thông tin hữu ích mà không khiến các nhà phát triển choáng ngợp. Đây là cách làm cho việc kiểm tra thất bại trở nên hữu ích:
- name: Run tests with detailed output
run: |
npm test -- --verbose --reporter=json --outputFile=test-results.json
continue-on-error: true
id: tests
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: test-results.json
- name: Comment on PR with test results
if: failure() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ Tests failed. Check the Actions tab for details.'
})
continue-on-error: true cho phép quy trình làm việc tiếp tục ngay cả khi kiểm tra thất bại, trong khi if: always() đảm bảo kết quả kiểm tra được tải lên bất kể kết quả kiểm tra như thế nào. Nhận xét PR có điều kiện sẽ thông báo cho nhà phát triển về lỗi mà không gửi spam các bản dựng thành công.
Tối ưu hóa hiệu suất xây dựng
Quá trình xây dựng chậm khiến các nhà phát triển nản lòng và lãng phí tài nguyên CI. Dưới đây là những tối ưu hóa thực tế tạo nên sự khác biệt thực sự:
Cache phụ thuộc mạnh mẽ:
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Chạy công việc trong Parallel:
jobs:
lint:
runs-on: ubuntu-latest
steps: [...]
test:
runs-on: ubuntu-latest
steps: [...]
build:
runs-on: ubuntu-latest
needs: [lint, test] # Only build if both pass
steps: [...]
Bỏ qua công việc không cần thiết:
on:
push:
paths-ignore:
- 'docs/**'
- '**.md'
pull_request:
paths:
- 'src/**'
- 'package.json'
Gỡ lỗi lỗi xây dựng
Khi quá trình xây dựng bị lỗi, bạn cần chẩn đoán vấn đề một cách nhanh chóng. Thêm thông tin gỡ lỗi vào quy trình làm việc của bạn:
- name: Debug environment
if: failure()
run: |
echo "Node version: $(node --version)"
echo "NPM version: $(npm --version)"
echo "Working directory: $(pwd)"
echo "Directory contents:"
ls -la
echo "Environment variables:"
env | sort
Điều kiện if: failure() đảm bảo thông tin gỡ lỗi chỉ xuất hiện khi có sự cố, giữ sạch nhật ký xây dựng thành công đồng thời cung cấp thông tin chi tiết để khắc phục sự cố.
Cân nhắc xây dựng trong thế giới thực
Các bản dựng production thường cần các bước bổ sung ngoài việc biên dịch cơ bản:
ECấu hình dành riêng cho môi trường:
- name: Build for production
run: npm run build
env:
NODE_ENV: production
API_URL: https://api.production.com
FEATURE_FLAGS: '{"newFeature": true}'
ATối ưu hóa tài sản:
- name: Optimize assets
run: |
npm run build
npm run optimize-images
npm run compress-assets
Xác thực Build:
- name: Validate build output
run: |
if [ ! -f "dist/index.html" ]; then
echo "Build failed: missing index.html"
exit 1
fi
# Check bundle size
BUNDLE_SIZE=$(stat -c%s dist/main.*.js)
if [ $BUNDLE_SIZE -gt 1048576 ]; then
echo "Warning: Bundle size exceeds 1MB"
fi
Những cân nhắc cụ thể về ngôn ngữ
Các ngôn ngữ lập trình khác nhau có yêu cầu xây dựng khác nhau nhưng các mẫu vẫn nhất quán:
- Java: Sử dụng
actions/setup-javavới bộ đệm ẩn Maven hoặc Gradle - Go: Sử dụng
actions/setup-govới bộ nhớ đệm mô-đun quago mod download - Ruby: Sử dụng
actions/setup-rubyvới bộ nhớ đệm Bundler - PHP: Sử dụng
shivammathur/setup-phpvới bộ nhớ đệm của Trình soạn thảo
Điều quan trọng là hiểu trình quản lý gói và hệ thống phân giải phần phụ thuộc trong ngôn ngữ của bạn, sau đó định cấu hình Tác vụ GitHub để lưu vào bộ đệm phù hợp và cài đặt các phần phụ thuộc một cách đáng tin cậy.
Trong phần tiếp theo, chúng ta sẽ khám phá cách xử lý bản dựng artifact và các phần phụ thuộc một cách hiệu quả, bao gồm chia sẻ dữ liệu giữa các công việc và tối ưu hóa hiệu suất quy trình làm việc thông qua các chiến lược bộ nhớ đệm thông minh.