前端工程化:Github Action 实现 CI/CD

227 阅读6分钟

面试导航 是一个专注于前、后端技术学习和面试准备的 免费 学习平台,提供系统化的技术栈学习,深入讲解每个知识点的核心原理,帮助开发者构建全面的技术体系。平台还收录了大量真实的校招与社招面经,帮助你快速掌握面试技巧,提升求职竞争力。如果你想加入我们的交流群,欢迎通过微信联系:yunmz777

20250310220634

GitHub Actions 是 GitHub 提供的持续集成和持续部署(CI/CD)平台,允许开发者自动化软件开发工作流程。通过简单的配置,可实现代码的自动构建、测试和部署,无需额外的服务器或复杂基础设施。

1. GitHub Actions 核心概念

1.1 工作流程 (Workflow)

工作流程是由一系列作业组成的自动化过程,通过在仓库的 .github/workflows 目录下创建 YAML 文件来定义。

name: CI Pipeline
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

1.2 事件 (Event)

事件是触发工作流程的活动,常见的包括:

  • 代码推送 (push)
  • 拉取请求 (pull_request)
  • 定时计划 (schedule)
  • 手动触发 (workflow_dispatch)
  • 外部触发 (repository_dispatch)
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 0 * * *" # 每天午夜运行

1.3 作业 (Job)

作业是工作流程的执行单元,由一系列步骤组成。默认情况下,多个作业并行执行,但可配置依赖关系实现顺序执行。

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      # 测试步骤

  build:
    needs: test # 依赖于test作业完成
    runs-on: ubuntu-latest
    steps:
      # 构建步骤

1.4 运行器 (Runner)

运行器是执行工作流程的服务器环境。GitHub 提供多种托管环境:

  • Ubuntu Linux
  • Windows
  • macOS

也支持自托管运行器,用于特殊需求场景。

jobs:
  build:
    runs-on: ubuntu-latest # 使用GitHub托管的Ubuntu运行器

1.5 步骤 (Step)

步骤是作业中的最小执行单元,可以是命令或操作。

steps:
  - name: Install dependencies
    run: npm install

  - name: Run tests
    run: npm test

1.6 操作 (Action)

操作是工作流程的可重用构建块,可以是:

  • 公共仓库中的预构建操作
  • 本地仓库中的自定义操作
  • Docker 容器操作
  • JavaScript 操作
steps:
  - name: Checkout code
    uses: actions/checkout@v3

  - name: Setup Node.js
    uses: actions/setup-node@v3
    with:
      node-version: "16"

2. 工作流程配置实践

2.1 基本工作流程结构

name: Node.js CI # 工作流程名称

on: # 触发条件
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs: # 作业定义
  build:
    runs-on: ubuntu-latest

    strategy: # 矩阵策略
      matrix:
        node-version: [14.x, 16.x, 18.x]

    steps: # 步骤定义
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: "npm"
      - run: npm ci
      - run: npm test

2.2 环境变量与敏感信息

环境变量可在工作流程、作业或步骤级别定义:

jobs:
  build:
    runs-on: ubuntu-latest
    env: # 作业级环境变量
      NODE_ENV: production
      API_KEY: ${{ secrets.API_KEY }} # 使用仓库密钥

    steps:
      - name: Use environment variables
        run: echo $NODE_ENV

      - name: Deploy with sensitive data
        env: # 步骤级环境变量
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
        run: ./deploy.sh

2.3 矩阵构建与并行测试

矩阵策略允许在多种配置下并行测试代码:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [14.x, 16.x, 18.x]
        # 可选:排除特定组合
        exclude:
          - os: windows-latest
            node-version: 14.x

    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

2.4 依赖缓存优化

缓存可显著加速工作流程执行:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Cache node modules
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install Dependencies
        run: npm install

3. 实用工作流程示例

3.1 前端应用部署到 GitHub Pages

name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "16"
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

3.2 Node.js 包发布到 npm

name: Publish to npm

on:
  release:
    types: [created]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: "16"
          cache: "npm"
      - run: npm ci
      - run: npm test

  publish:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: "16"
          registry-url: "https://registry.npmjs.org"
      - run: npm ci
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

3.3 Docker 镜像构建与推送

name: Docker CI/CD

on:
  push:
    branches: [main]
    tags: ["v*"]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

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

      - name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: username/app-name
          tags: |
            type=semver,pattern={{version}}
            type=ref,event=branch

      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

4. 高级功能与最佳实践

4.1 作业间数据共享

使用工件 (Artifacts) 可在不同作业之间传递数据:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build
        run: npm run build
      - name: Upload build artifact
        uses: actions/upload-artifact@v3
        with:
          name: build-files
          path: dist/
          retention-days: 1 # 设置保留期限

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download build artifact
        uses: actions/download-artifact@v3
        with:
          name: build-files
          path: dist/
      - name: Deploy
        run: ./deploy.sh

4.2 条件执行与环境分支

使用条件表达式控制工作流程执行流程:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm test

  deploy-staging:
    needs: test
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to staging
        run: ./deploy-staging.sh

  deploy-production:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to production
        run: ./deploy-production.sh

4.3 可重用工作流程

将常用配置提取为可重用工作流程:

# .github/workflows/reusable-build.yml
name: Reusable build workflow

on:
  workflow_call:
    inputs:
      node-version:
        required: false
        default: "16"
        type: string

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci
      - run: npm run build

在其他工作流程中调用:

# .github/workflows/main.yml
name: Main workflow

on: [push]

jobs:
  call-build:
    uses: ./.github/workflows/reusable-build.yml
    with:
      node-version: "18"

4.4 自定义操作开发

创建自定义 JavaScript 操作:

# action.yml
name: "Hello World"
description: "Greet someone"
inputs:
  who-to-greet:
    description: "Who to greet"
    required: true
    default: "World"
outputs:
  time:
    description: "The time we greeted you"
runs:
  using: "node16"
  main: "index.js"
// index.js
const core = require("@actions/core");

try {
  const nameToGreet = core.getInput("who-to-greet");
  console.log(`Hello ${nameToGreet}!`);
  const time = new Date().toTimeString();
  core.setOutput("time", time);
} catch (error) {
  core.setFailed(error.message);
}

5. 安全与性能优化

5.1 安全最佳实践

  • 使用最小权限原则:限制工作流程的权限范围
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      deployments: write
  • 敏感信息管理:使用仓库密钥和环境密钥存储敏感信息
  • 定期更新操作版本:使用特定版本的操作,并定期更新
  • 代码扫描与依赖分析:使用 CodeQL 和依赖扫描工具

5.2 性能优化技巧

  • 精简工作流程:拆分大型工作流程,避免不必要的步骤
  • 有效使用缓存:缓存依赖、构建产物和测试结果
  • 条件步骤执行:使用 if 条件控制步骤执行
steps:
  - name: Build only on main branch
    if: github.ref == 'refs/heads/main'
    run: npm run build
  • 并行作业执行:使用矩阵策略并行执行任务
  • 自托管运行器优化:为高负载任务配置高性能自托管运行器

6. GitHub Actions 与其他 CI/CD 工具对比

特性GitHub ActionsJenkinsGitLab CICircleCI
托管方式云托管/自托管自托管云托管/自托管云托管
配置语法YAMLJenkinsfile/UIYAMLYAML
代码库集成原生集成插件集成原生集成需配置
免费计划公开仓库免费
私有仓库有配额
开源免费公开仓库免费
私有仓库有配额
有限免费计划
生态系统GitHub Marketplace插件中心GitLab 集成Orbs
学习曲线相对平缓较陡峭中等中等

7. 最佳实践与经验总结

  1. 模块化组织工作流程:将功能划分为独立的工作流程文件,提高可维护性

  2. 版本化引用外部操作:总是使用具体版本号而非分支名

# 推荐
uses: actions/checkout@v3

# 不推荐
uses: actions/checkout@main
  1. 明确的命名规范:为工作流程、作业和步骤使用清晰描述性的名称

  2. 充分利用内置功能:使用矩阵策略、条件执行和缓存等内置功能

  3. 自动化监控:设置工作流程失败通知和性能监控

  4. 文档化与知识共享:为自定义操作和工作流程撰写清晰文档

  5. 定期审查与优化:随着项目发展,定期评估和改进工作流程

结语

GitHub Actions 提供了强大而灵活的自动化能力,能够满足从简单的个人项目到复杂的企业应用的各种需求。通过本指南介绍的概念和最佳实践,你可以构建高效、可靠的 CI/CD 流水线,提升开发效率,保障代码质量。

无论你是初次接触自动化工作流程,还是寻求优化现有流程,GitHub Actions 都能为你提供简洁而强大的解决方案。开始尝试这些配置示例,探索更多可能性,让你的开发流程更加智能、高效!