AI 摘要
AI
正在生成摘要...

在开发项目时,很多开发者都会面临部署的麻烦,每次修改代码后,需要手动打包、上传文件、重启服务。这些步骤重复进行,不仅耗费时间,还容易出错,特别是项目需要频繁迭代时。

而优化这一问题,最直接有效的办法就是引入 CI/CD 流程,把这些重复操作交给自动化工具完成。其中,GitHub Actions 是当前最便捷的选择之一,它直接内置在 GitHub 仓库中,配置简单,免费额度充足,适合大多数个人和小型团队项目。

1 什么是 CI/CD?

CI/CD 可以理解为软件开发的“自动化流水线”。

想象一个工厂生产手机:以前是工人手工组装每个部件、一个个测试、最后手动包装发货。效率低,还容易出次品。现在换成流水线:零件一进工厂,机器自动组装、自动检测质量、检测通过后自动包装并送上货车。

CI/CD 就是这样的流水线:

  • CI(持续集成):代码改好推上去后,系统自动构建项目并运行测试,快速发现是否有问题。
  • CD(持续部署):测试通过后,系统自动把代码发布到服务器或托管平台,让最新版本直接上线。

这样做的好处是显而易见的:减少手动重复工作,避免人为失误,让开发过程更流畅可靠。

flowchart LR
  Code[计划/编码]

  subgraph CI[持续集成 CI]
    VC[版本控制]
    Build[构建&测试]
    Check{测试通过?}
  end

  subgraph CD[持续交付/部署 CD]
    Deploy[发布/部署]
    Pre[预发布环境]
    Online[生产环境]
  end

  Code --> VC --> Build --> Check
  Check -- 否 --> Code
  Check -- 是 --> Deploy
  Deploy --> Pre
  Deploy --> Online

常见的 CI/CD 工具包括 Jenkins、CircleCI、Travis CI、GitLab CI 和 GitHub Actions。这些工具都能实现自动化构建、测试和部署,但实现方式和使用体验有所不同。

在众多 CI/CD 工具中,GitHub Actions 尤其适合个人开发者和小团队。它与 GitHub 仓库天然集成,无需额外平台切换,运行环境由 Github 提供,省去自建和维护成本。再加上免费额度够用、YAML 配置简单且模板丰富,基本可以快速搭建起自动化部署流程。

2 GitHub Actions 核心概念

GitHub Actions 的大部分概念都是 CI/CD 通用概念,适用于任何自动化流程,在此基础上 GitHub Actions 增加了一些独有的术语和操作方式,让其变得实用性更强。

  • 工作流(Workflow)

工作流是整个自动化流程的“总蓝图”,定义了一系列自动化任务的执行顺序和规则。可以把它想象成工厂流水线:从原材料进来,到成品出去,整个过程的规划都写在这里。一个仓库可以有多个工作流,每个工作流都用一个 YAML 文件定义(通常放在 .github/workflows/ 目录下),这个文件里会包含触发器、动作等。

  • 触发器(Trigger / Event)

触发器就是“启动开关”,决定了工作流的条件或事件。常见的触发事件有:推送代码(push)、创建拉取请求(pull_request)、定时任务(schedule)、手动点击运行(workflow_dispatch)。比如一 push 代码,就相当于拉下开关,流水线立刻启动运转。

  • 作业(Job)

作业是流水线上的“独立工段”,它是工作流中的一个独立执行单元。一个工作流可以包含多个作业,可以把它们想象成不同的生产阶段:一个工段负责“组装”(构建项目),另一个工段负责“质检”(运行测试)。作业之间还可以设置依赖关系,比如只有“质检”通过了,才会执行后面的“发货”(部署)。

  • 步骤(Step)

步骤是工段里的“具体工序”,一个作业由多个步骤按顺序串联执行。每个步骤可以直接运行一条 shell 命令(比如 npm install),也可以调用一个动作(Action)。就像流水线上一个个紧挨的操作站:拉取代码 - 安装依赖 - 构建项目,环环相扣,缺一不可。

  • 动作(Action)

动作是流水线上的“装置设备”,能快速插入封装好的功能。它可以来自 GitHub Marketplace(官方市场),也可以是自己写的。就像流水线上某个位置:需要用机械臂进行操作,不需要自己去制造,直接“买”一个机械臂就可以立刻干活。常见动作有 actions/checkout(拉取代码)、actions/upload-artifact(上传构建产物)等,极大减少重复写命令的麻烦。

  • 运行器(Runner)

运行器是整个工段运转的“虚拟车间”,提供计算环境和资源让所有步骤和动作执行起来。GitHub 提供官方托管的车间(GitHub-hosted runner),支持 Ubuntu、Windows、macOS,免费额度内开箱即用,零维护。如果有特殊需求也可以自建车间(self-hosted runner),部署到自己的服务器或云主机上。

掌握了这几个核心概念,就已经能看懂大部分 GitHub Actions 的 YAML 配置了。下面是一个工作流文件示例,可以帮助更清晰里理解:

YAML
name: Hello Actions  # 工作流的名字,在 GitHub 上会显示这里
on:                  # 触发器
  push:              # 当推送代码时触发
    branches:        # 只针对这些分支
      - main

jobs:                        # 作业
  greet:                     # 作业的名字,叫 greet(随意取)
    runs-on: ubuntu-latest   # 运行器:用 GitHub 提供的 Ubuntu

    steps:                          # 步骤
      - name: Checkout code         # 步骤名字(可选,但建议写,便于看日志)
        uses: actions/checkout@v4   # 使用动作:自动拉取代码

      - name: Say Hello             # 另一个步骤
        run: echo "Hello"           # 直接运行 shell 命令,打印一句话

3 入门准备

在开始配置自己的自动化工作流之前,先来熟悉 GitHub Actions 的几个关键操作和设置,会让后续编写 YAML 文件时更得心应手。

在哪里创建和管理 Workflow 文件

Workflow 的配置文件必须放在仓库的 .github/workflows/ 目录下,一个仓库可以有多个 YAML 文件,每个文件就是一个独立的工作流。

创建 Workflow 文件操作步骤:

  1. 打开一个 GitHub 仓库,点击 Add file > Create new file
  2. 在文件名输入框中直接输入 .github/workflows/ci.yml(名字随意,后缀必须是 .yml 或 .yaml)
  3. 把 YAML 内容粘贴进去,提交更改到 main 分支

图片

怎么查看运行记录和日志

Workflow 的日志非常有用,绝大数的出错都能在这里找原因,且日志非常清晰,很容易定位到问题所在。

  • 仓库顶部导航栏有个 Actions 标签,点进去左边是工作流列表,右边是历史记录
  • 点入一条历史记录,左侧选择一个 job,就可以按照 Step 来查看详细日志了
图片
图片

Secrets 在哪里设置

Secrets(密钥) 通常用来存储需要加密的敏感数据,与之对应的还有不加密的 Variables(变量),它们以键值对的结构保存,组成了可重复使用的配置数据。

Secrets 设置路径:

  1. 打开一个 GitHub 仓库,点击顶部导航栏的 Settings 标签
  2. 在左侧侧边栏找到 Secrets and variables 并展开,随后点击 Actions
  3. 点击 New repository secret 创建密钥
  4. 在 YAML 中引用方式:${{ secrets.YOUR_SECRET_NAME }}

图片

在哪里找现成的 Action

大部分工作流都会用到写法类似 uses: xxx 的动作,这些动作大部分来自 官方市场

访问官方市场找到需要的 Actions,点进去你可以在右侧切换版本和查看使用示例,左侧文档里通常还提供更完整的使用方法。

图片

常用官方动作:

  • actions/checkout@v6 拉取仓库代码
  • actions/setup-node@v6 安装并配置 Node.js 运行环境
  • actions/cache@v5 缓存依赖与构建结果,加速 CI
  • actions/upload-artifact@v6 保存构建产物,用于跨 Job 传递文件
  • actions/download-artifact@v6 获取构建产物,用于跨 Job 传递文件

免费额度与运行器

GitHub Actions 对于公共仓库是完全免费的(无限分钟和存储),对于私人仓库,免费账户每月提供 2000 分钟的免费运行时间和 500MB 的Artifact 存储配额,对个人开发者和小团队的日常使用已经绰绰有余。

不同运行器存在消耗差异:

ubuntu-latest:消耗 1 倍分钟,默认选择
windows-latest:消耗 2 倍分钟
macos-latest:消耗 10 倍分钟

使用量可以在 用户设置 > * Billing and licensing* 查看

开始第一个 Workflow

在任意仓库 .github/workflows/hello.yml 中写入下面内容并提交:

YAML
name: Hello Test
on: push
jobs:
  hello:
    runs-on: ubuntu-latest
    steps:
      - run: echo "GitHub Actions 运行成功!"

在 Actions 页面看到日志里打印“GitHub Actions 运行成功!”,就说明成功了

图片

4 实战案例

有了前面的入门准备和核心概念,现在进入案例部分,从基础到进阶,逐步覆盖 GitHub Actions 的绝大多数常用功能和知识点。

案例1:Push 时自动运行测试

适用于几乎所有项目的最小化 CI 流程。在代码推送或提交 PR 时自动运行单元测试,尽早发现问题,避免坏代码进入主分支。

YAML
# .github/workflows/ci-tests.yml
name: Run Tests
on:
  # 代码推送事件(main 或 develop 分支时触发)
  push:
    branches: [main, develop]
  # Pull Request事件(main 分支时触发)
  pull_request:
    branches: [main]
jobs:
  test:
    # 指定运行器为 ubuntu-latest
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      # 配置 Node.js 环境(版本 24,启用 npm 缓存)
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
          cache: 'npm'
      - name: Install dependencies
        run: npm ci  # 执行命令
      - name: Run tests
        run: npm test

push 和 pull_request 触发器确保每次代码变更都会自动测试。如果测试失败,GitHub 会标记 commit 为失败并发送通知。非 Node 项目只需更换对应的 setup 动作和命令即可。

知识点总结

  • 触发器:pushpull_request 及其分支过滤
  • 官方动作:actions/checkout@v6actions/setup-node@v6
  • 基本步骤结构:nameusesrunwith
  • 运行器选择:runs-on

案例2:矩阵并行,多版本多平台测试

适用于需要同时兼容多个运行环境的项目,一次提交并行验证所有组合。

YAML
# .github/workflows/matrix-test.yml
name: Matrix Testing
on: [push, pull_request]  # 在代码推送或创建 PR 时触发
jobs:
  test:
    # 定义矩阵策略,生成多个并行任务
    strategy:
      matrix:
        node-version: [18, 20, 22, 24]  # 定义 Node.js 版本矩阵
        os: [ubuntu-latest, windows-latest, macos-latest]  # 定义操作系统矩阵
      fail-fast: false  # 一个组合失败不终止其他组合
    # 使用矩阵中的操作系统
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      # 使用矩阵中的 Node.js 版本
      - name: Setup Node ${{ matrix.node-version }}
        uses: actions/setup-node@v6
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

strategy.matrix 会自动生成所有组合的 Job 并并行执行。共 4 个 Node 版本 × 3 个操作系统 = 12 个并行测试任务,每个任务独立运行。

知识点总结

  • strategy.matrix 多维度组合测试
  • 矩阵变量引用(${{ matrix.xxx }}
  • fail-fast 控制并行失败行为
  • 跨平台/多版本并行执行加速

案例3:自定义缓存路径与键

适用于需要缓存任意目录或文件(如 node_modules、构建缓存、第三方工具)的项目。相比 setup-node 内置缓存,actions/cache@v4 更灵活,可精确控制缓存键、路径和恢复行为。

YAML
# .github/workflows/custom-cache.yml
name: Cache Dependencies
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      # 配置 Node.js 环境(不使用内置缓存)
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
      # 自定义缓存 node_modules 和 npm 全局缓存
      - name: Cache node_modules
        uses: actions/cache@v5
        with:
          path: |
            node_modules
            ~/.npm
          # 缓存键:基于 OS 和 package-lock.json 的哈希
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          # 恢复键:依赖变更时尝试匹配旧缓存
          restore-keys: |
            ${{ runner.os }}-node-
      - name: Install dependencies
        run: npm ci
      - name: Build project
        run: npm run build

使用 hashFiles 生成基于 lockfile 的缓存键,确保依赖变更时自动失效缓存。restore-keys 提供回退匹配。

知识点总结

  • 独立缓存动作 actions/cache@v5
  • 自定义缓存路径(path 多行支持)
  • 精确缓存键(keyhashFiles
  • 回退键(restore-keys)与缓存命中优化

案例4:上传与下载构建产物

适用于构建产物需要在后续 Job 传递或手动下载的场景,实现跨 Job 文件共享。

YAML
# .github/workflows/artifact.yml
name: Build & Artifact
on: [push]
jobs:
  # build Job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
      - name: Install & Build
        run: npm ci && npm run build
      # 上传构建产物(上传 dist/ 命名为 dist-files)
      - name: Upload artifact
        uses: actions/upload-artifact@v6
        with:
          name: dist-files
          path: dist/
  # deploy Job
  deploy:
    needs: build  # 依赖 build Job(必须等其完成后执行)
    runs-on: ubuntu-latest
    steps:
      # 下载构建产物(名称为 dist-files)
      - name: Download artifact
        uses: actions/download-artifact@v6
        with:
          name: dist-files
      - name: List files
        run: ls -R  # 递归列出当前目录下所有文件和子目录

Artifact 本质上是一个默认保留 90 天的临时文件存储服务,专门用于工作流中实现跨 Job、跨环境的文件传递。

知识点总结

  • 官方动作:actions/upload-artifact@v6actions/download-artifact@v6
  • Job 依赖关系(needs)
  • 跨 Job 文件传递与调试

案例5:跨 Job 传递输出数据

适用于需要将一个 Job 的计算结果(如版本号、commit 信息、动态值)传递给后续 Job 的场景,避免重复计算。

YAML
# .github/workflows/job-outputs.yml
name: Job Outputs
on: [push]
jobs:
  create-data:
    runs-on: ubuntu-latest
    # 声明要输出的变量 current_time
    outputs:
      current_time: ${{ steps.get-time.outputs.time }}  # 此处 time 对应 '当前时间是 $(date)'
    steps:
      - name: Get current time
        id: get-time  # 给这个步骤起个 ID,方便后面引用
        run: echo "time=当前时间是 $(date)" >> $GITHUB_OUTPUT  # >> $GITHUB_OUTPUT:把结果保存为这个步骤的输出
  use-data:
    needs: create-data
    runs-on: ubuntu-latest
    steps:
      - name: Print time
        run: echo "打印接收到的时间:${{ needs.create-data.outputs.current_time }}"

前一个 Job 生成一个动态时间戳字符串,后一个 Job 直接获取并使用。实际项目中,可将时间戳替换为版本号、commit 信息等轻量数据。

知识点总结

  • 步骤输出设置(id 与 $GITHUB_OUTPUT)
  • Job 输出声明(outputs)
  • 跨 Job 数据引用(needs.job.outputs.xxx

案例6:手动触发工作流并条件执行

适用于需要人工确认的敏感操作,提供交互式参数,手动选择或者输入后根据条件执行不同逻辑。

YAML
# .github/workflows/manual-deploy.yml
name: Manual Deploy
on:
  # 启用手动触发
  workflow_dispatch:
    # 自定义输入项
    inputs:
      # env(部署环境)选择器,可选 staging 和 production
      env:
        type: choice
        description: 部署环境
        options: [staging, production]
        default: staging
      # version(版本号)输入框
      version:
        type: string
        description: 版本号
        default: latest
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      # 部署测试环境
      - name: Deploy Staging
        if: github.event.inputs.env == 'staging'
        run: echo "Deploy staging ${{ github.event.inputs.version }}"
      # 部署生产环境
      - name: Deploy Production
        if: github.event.inputs.env == 'production'
        run: echo "Deploy production ${{ github.event.inputs.version }}"

图片

知识点总结

  • workflow_dispatch 手动触发
  • inputs 参数定义(choice、string、boolean 等类型)
  • 事件上下文引用(github.event.inputs.xxx
  • 步骤/Job 条件执行(if

案例7:定时任务(Schedule)

适用于定期自动执行的任务(如依赖更新检查、夜间构建、数据备份),无需代码变更即可定时运行。

YAML
# .github/workflows/schedule.yml
name: Scheduled Task
on:
  # 定时触发器,使用 cron 语法
  schedule:
    - cron: '0 3 * * *'  # UTC 每天 3:00(北京 11:00)
  workflow_dispatch:  # 方便手动测试
jobs:
  nightly:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
      - name: Install dependencies
        run: npm ci
      - name: Check outdated dependencies
        run: npm outdated || echo "所有依赖均为最新"
      - name: Run security audit
        run: npm audit || echo "安全检查完成"

cron 使用 UTC 时区,五个字段分别代表 分 时 日 月 周具体用法

知识点总结

  • schedule 触发器
  • cron 语法格式
  • 定时自动化任务场景

案例8:构建并推送 Docker 镜像

适用于将项目容器化并自动发布到镜像仓库,发布版本标签时自动构建镜像并推送。

YAML
# .github/workflows/docker-publish.yml
name: Docker Publish
on:
  push:
    tags: ['v*']  # v* 标签(如 v1.0.0)时触发
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      # 登录 Docker Hub
      - name: Login Docker
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}  # Docker Hub 用户名
          password: ${{ secrets.DOCKER_TOKEN }}     # Docker Hub 生成的 Access Token
      # 构建并推送镜像
      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          push: true  # 推送镜像
          tags: |     # 多标签推送
            ${{ secrets.DOCKER_USERNAME }}/myapp:latest
            ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.ref_name }}

镜像标签 latest 始终指向最新构建、${{ github.ref_name }} 指标签名(如 v1.2.3),实际项目中可根据需要调整标签策略(如预发布不打 latest)。

知识点总结

  • 社区动作:docker/login-action@v3docker/build-push-action@v6
  • Secrets 在部署中的使用
  • Docker 镜像多标签推送与版本管理

案例9:构建并上传到服务器

适用于需要将构建产物部署到自有服务器的项目,完成构建后自动上传到服务器,实现零手动部署。

在创建工作流之前,需要先生成密钥对并且在服务器上配置 SSH 无密码登录(具体操作

YAML
# .github/workflows/deploy-server.yml
name: Deploy Server
on: [push]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: '24'
      - name: Install dependencies
        run: npm ci
      - name: Build project
        run: npm run build
      # 通过 SSH 上传文件到服务器(使用 rsync 同步)
      - name: Deploy to server
        uses: easingthemes/ssh-deploy@v5
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}  # SSH 私钥
          REMOTE_HOST: ${{ secrets.SSH_HOST }}             # 服务器 IP 或域名
          REMOTE_USER: ${{ secrets.SSH_USERNAME }}         # 登录用户名(不建议 root)
          SOURCE: "dist/"                                  # 要上传的目录
          TARGET: ${{ secrets.TARGET_PATH }}               # 服务器目标目录
          ARGS: "-avzr --delete"                           # rsync 参数:压缩、递归、删除多余文件

部署成功后,服务器上的目标目录会同步最新构建产物。

知识点总结

  • 社区动作:easingthemes/ssh-deploy@v5
  • 远程服务器部署(rsync 同步)
  • 生产级传统部署链路

5 高级特性与优化

在实际生产环境中,尤其是团队协作或项目规模增大时,还需要一些高级特性来提升工作流的优雅度和稳定性。

5.1 可复用工作流(Reusable Workflows)

大型项目或多仓库组织中,常常有重复的流程(如测试、构建、部署)。手动复制 YAML 会导致维护困难。GitHub 支持可复用工作流,允许把通用流程抽成模板,跨仓库调用。

YAML
# 模板仓库:.github/workflows/reusable-test.yml
name: Reusable Test Workflow
on:
  workflow_call:  # 关键:表示这是可被调用的工作流
    inputs:       # 定义输入参数
      node-version:
        required: true
        type: string
      cache-enabled:
        type: boolean
        default: true
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: ${{ inputs.node-version }}
          cache: ${{ inputs.cache-enabled && 'npm' || '' }}
      - run: npm ci
      - run: npm test
YAML
# 项目仓库:.github/workflows/ci.yml
name: Call Reusable Test
on: [push, pull_request]
jobs:
  call-test:
    uses: [用户名、组织名]/[模板仓库]/.github/workflows/reusable-test.yml@main  # 调用路径
    with:  # 传入参数
      node-version: '24'
      cache-enabled: true

workflow_call 用于定义可复用工作流,支持传入参数(inputs)和密钥(secrets),调用只需要 uses 路径@分支

5.2 环境与部署保护(Environments)

生产环境部署往往需要人工审核、限制并发或特定 Secrets。可以配置比仓库 Secrets 更细粒度的环境级 Secrets,以及两个常用保护规则:

  • Required reviewers:必须指定人员审批
  • Wait timer:部署前等待一段时间(防止误操作)

图片

YAML
jobs:
  deploy-prod:
    environment: production  # 指定环境,触发保护规则
    runs-on: ubuntu-latest
    steps:
      # 环境专属 Secrets 自动可用
      - run: deploy-script --token ${{ secrets.PROD_TOKEN }}

5.3 自托管运行器(Self-hosted Runners)

GitHub 托管运行器免费但有额度限制,且不支持某些特定环境。自托管运行器可部署到自己的机器或云主机。

快速搭建

  1. 仓库 Settings > Actions > Runners > New self-hosted runner
  2. 按提示下载并运行 runner 应用(支持 Linux/Windows/macOS)
  3. 配置标签(labels)区分不同机器

图片

YAML
jobs:
  heavy-build:
    runs-on: self-hosted  # 自托管运行器
    steps:
      - run: ./heavy-computation

6 写在最后

GitHub Actions 只是 CI/CD 工具中的一员,选择它是因为足够简单且强大,随着项目成长,可能会用到其他工具,如 GitLab CI、Jenkins等,它们的核心思路是相通的:让重复工作自动化,让开发者专注创造价值。

如果你感兴趣,可以在下方深入学习:

评论

暂无评论,快来发表第一条评论吧!