← 返回资讯
苏晴
资深编辑
已审核

CI/CD 流水线设计:从 GitHub Actions 到自托管 Runner 的完整实践

title: "CI/CD 流水线设计:从 GitHub Actions 到自托管 Runner 的完整实践"

CI/CD 流水线设计:从 GitHub Actions 到自托管 Runner 的完整实践

title: "CI/CD 流水线设计:从 GitHub Actions 到自托管 Runner 的完整实践"

date: "2026-07-10"

tags: ["CI/CD", "GitHub Actions", "DevOps", "自动化"]


CI/CD 流水线设计:从 GitHub Actions 到自托管 Runner 的完整实践

持续集成和持续部署是现代软件开发的标配。但很多团队的 CI/CD 流水线要么太简单(只是跑个测试),要么太复杂(维护成本比收益还高)。

基础流水线

一个典型的 Node.js 项目流水线:

YAML
# .github/workflows/ci.yml
name: CI/CD Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
      
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
      
      - name: Lint
        run: pnpm lint
      
      - name: Type check
        run: pnpm type-check
      
      - name: Unit tests
        run: pnpm test:unit --coverage
      
      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Build
        run: pnpm build
      
      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/

多环境部署

YAML
  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: build-output
      
      - name: Deploy to staging
        run: |
          rsync -avz dist/ user@staging-server:/var/www/app/
          ssh user@staging-server 'systemctl restart app'

  deploy-production:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: build-output
      
      - name: Deploy to production
        run: |
          kubectl apply -f k8s/
          kubectl rollout status deployment/app

自托管 Runner

GitHub Actions 的云端 Runner 有并发限制和超时限制。对于大型项目,自托管 Runner 更合适。

安装 Runner

BASH
# 下载 Runner
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.317.0.tar.gz -L \
  https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz

# 解压
tar xzf actions-runner-linux-x64-2.317.0.tar.gz

# 配置
./config.sh --url https://github.com/your-org/your-repo \
  --token YOUR_REGISTRATION_TOKEN

# 安装为服务
sudo ./svc.sh install
sudo ./svc.sh start

Docker 化 Runner

DOCKERFILE
FROM ubuntu:22.04

RUN apt-get update && apt-get install -y \
    curl git docker.io nodejs npm \
    && rm -rf /var/lib/apt/lists/*

RUN useradd -m runner
USER runner
WORKDIR /home/runner

RUN curl -o actions-runner.tar.gz -L \
    https://github.com/actions/runner/releases/download/v2.317.0/actions-runner-linux-x64-2.317.0.tar.gz \
    && tar xzf actions-runner.tar.gz \
    && rm actions-runner.tar.gz

COPY start.sh /home/runner/
ENTRYPOINT ["/home/runner/start.sh"]
BASH
#!/bin/bash
# start.sh
./config.sh --url $REPO_URL --token $RUNNER_TOKEN --unattended
./run.sh

缓存优化

依赖缓存

YAML
- name: Cache pnpm dependencies
  uses: actions/cache@v4
  with:
    path: ~/.pnpm-store
    key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
    restore-keys: |
      ${{ runner.os }}-pnpm-

- name: Cache node_modules
  uses: actions/cache@v4
  with:
    path: node_modules
    key: ${{ runner.os }}-modules-${{ hashFiles('**/pnpm-lock.yaml') }}

Docker 层缓存

YAML
- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

- name: Build and push
  uses: docker/build-push-action@v5
  with:
    push: true
    tags: registry.example.com/app:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

并行执行

YAML
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - run: pnpm lint

  type-check:
    runs-on: ubuntu-latest
    steps:
      - run: pnpm type-check

  test-unit:
    runs-on: ubuntu-latest
    steps:
      - run: pnpm test:unit

  test-e2e:
    runs-on: ubuntu-latest
    steps:
      - run: pnpm test:e2e

  build:
    needs: [lint, type-check, test-unit, test-e2e]
    runs-on: ubuntu-latest
    steps:
      - run: pnpm build

矩阵测试

YAML
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, macos-latest]
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: pnpm test

安全实践

密钥管理

YAML
- name: Deploy
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  run: aws s3 sync dist/ s3://my-bucket/

依赖扫描

YAML
- name: Run Snyk to check for vulnerabilities
  uses: snyk/actions/node@master
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

OIDC 认证(替代长期密钥)

YAML
permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/GitHubActions
      aws-region: us-east-1

监控与告警

YAML
- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

性能优化清单

| 优化项 | 效果 | 实施难度 |

|--------|------|----------|

| 依赖缓存 | 减少 50%+ 安装时间 | 低 |

| 并行执行 | 减少 60%+ 总时间 | 中 |

| 自托管 Runner | 无并发限制 | 中 |

| Docker 层缓存 | 减少 70%+ 构建时间 | 中 |

| 增量构建 | 减少 80%+ 构建时间 | 高 |

CI/CD 流水线的目标是让开发者专注于写代码,而不是等待构建和部署。持续优化流水线,是提升团队效率的高杠杆投入。

441
7366 阅读
4 评论
分享
链接已复制
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年07月11日 08:49

苏晴

资深编辑

科技媒体从业 8 年,曾就职于多家科技媒体。关注 AI 创业和投资赛道,采访过 50+ 位行业从业者。

读者评论 4

数据分析师 1周前
数据引用很扎实,建议补充一下近三个月的最新数据。
回复 点赞 (9)
产品经理阿杰 2天前
从产品角度看,这个方向确实有机会,但商业化路径还需要验证。
回复 点赞 (15)
张工 5天前
写得很实在,特别是实测对比那部分,跟我自己的使用感受一致。
回复 点赞 (12)
前端工程师 1周前
代码示例很清晰,直接用到项目里了。
回复 点赞 (6)