如何使用 GitHub Actions 为 CI 创建工作流?

已完成

在这里,你将了解适用于 CI 的 GitHub Actions 和工作流。

你将学会如何:

  • 从模板创建工作流。
  • 了解 GitHub Actions 日志。
  • 针对多个目标进行测试。
  • 单独的构建和测试作业。
  • 保存和访问构建工件。
  • 审阅时自动标记 PR。

从模板创建工作流

若要创建工作流,首先使用模板。 模板具有为要实现的特定类型的自动化预先配置的常见作业和步骤。 如果不熟悉工作流、作业和步骤,请使用 GitHub Actions 模块查看“自动执行开发任务 ”。

在存储库的主页上,选择 “作 ”选项卡,然后选择“ 新建工作流”。

“选择工作流 ”页上,可以从许多不同的模板中进行选择。 一个示例是 Node.js 模板,该模板对节点依赖项进行干净安装、生成源代码,并针对不同版本的 Node 运行测试。 另一个示例是 Python 包 模板,它安装 Python 依赖项,并跨不同版本的 Python 运行测试(包括 lint)。

在搜索框中,输入 Node.js

显示 GitHub Actions 选项卡的屏幕截图,其中突出显示了搜索框,并包含文本“Node.js”。

在搜索结果中,在 Node.js 窗格中,选择“ 配置”。

显示 GitHub Actions 选项卡的屏幕截图,其中突出显示了“Node.js”窗格,并选择了 Node.js 模板。

在新创建的文件 node.js.yml 中看到此默认 Node.js 模板工作流。

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 run build --if-present
    - run: npm test

请注意 on: 属性。 此工作流会在向存储库推送以及对主分支发出拉取请求时触发。

此工作流中有一个 job 。 让我们回顾一下它的作用。

runs-on: 属性指定,对于操作系统,工作流在 ubuntu-latest 上运行。 该 node-version: 属性指定有三个版本,每个版本分别用于 Node 版本 14.x、16.x 和 18.x。 稍后在自定义工作流时,我们将深入描述 matrix 部分。

作业中的 steps 使用 GitHub Actions actions/checkout@v3 操作将代码从存储库引入到 VM,并使用 actions/setup-node@v3 操作来设置正确版本的 Node.js。 我们指定我们将使用 ${{ matrix.node-version }} 属性测试三个版本的 Node.js。 此属性引用我们之前定义的矩阵。 该 cache 属性指定用于在默认目录中缓存的包管理器。

此步骤的最后一部分执行 Node.js 项目使用的命令。 该 npm ci 命令从 package-lock.json 文件安装依赖项, npm run build --if-present 运行生成脚本(如果存在)并 npm test 运行测试框架。 请注意,此模板包含同一作业中的生成和测试步骤。

若要了解有关 npm 的详细信息,请查看 npm 文档:

除了单独的 npm 命令之外,团队还可以从可重用的工作流中受益,从而简化和标准化重复的自动化步骤。 利用可重用工作流,可以减少冗余,提高可维护性,并确保 CI/CD 管道之间的一致性。

如何利用可重用工作流来避免重复

随着团队的规模和项目的增长,通常会看到相同的步骤,例如代码签出、依赖项安装、测试和部署,跨多个工作流文件重复。 此类重复不仅会混乱代码库,还增加了需要更改时的维护时间。 可重用工作流通过允许定义自动化逻辑一次并从其他工作流调用它来解决此问题。 可重用工作流是可由其他工作流调用的特殊 GitHub Actions 工作流,与编程中的函数类似。 创建它们以共享重复的逻辑,例如生成步骤、测试过程或部署策略。 创建后,可以从同一存储库中的其他任何工作流,甚至跨不同的存储库引用它们。

说明 GitHub Actions 中可重用工作流概念的图示,展示了中心工作流如何可以被多个存储库或工作流引用。

为什么要使用它们?

  • 一致性:团队可以在所有项目中遵循相同的自动化标准。
  • 效率:无需复制和粘贴步骤,只需指向可重用的工作流。
  • 轻松更新:当进程更改(例如新的测试步骤)时,可以在一个位置更新它,并使用它的所有工作流都会自动受益。
  • 可伸缩性:非常适合管理多个服务的平台或 DevOps 团队。

让我们探讨如何使用可重用工作流来改进项目。

如何实现可重用工作流

要利用可重用工作流,请执行以下操作:

  • 在存储库的文件夹中创建可重用工作流。 此文件将包括要共享的自动化步骤,例如测试、生成或部署。
  • 必须使用 workflow_call 事件配置工作流,以显式启用可重用工作流。
  • 在您的主工作流(调用者工作流)中,您需要引用这个可重用的文件,同时提供任何必要的输入或机密信息。

为了说明可重用工作流的优点,请考虑以下实际方案。

实际示例

假设组织有 10 个微服务,所有这些微服务都需要相同的步骤才能:

  • 运行测试
  • Lint 代码
  • 部署到特定环境

如果没有可重用的工作流,每个存储库都包含重复的逻辑。 使用可重用工作流,可以:

  • 在中心文件中定义一次进程(例如,ci-standard.yml)
  • 从每个服务自己的工作流调用此文件,传入环境变量或应用名称等变量

现在,如果添加了新的安全步骤或工具(例如扫描漏洞),只需在可重用工作流中添加一次。 所有这 10 个服务将立即使用更新的流程,而无需修改每个服务。

通过了解可重用工作流的功能及其优势,可以采用最佳做法来最大程度地提高其有效性,并确保无缝集成到 CI/CD 管道中。

最佳做法

  • 如果计划跨团队共享可重用工作流,请将可重用工作流集中到一个存储库中。
  • 使用分支或标记对工作流进行版本控制(例如,使用 @v1),因此更改不会意外中断所有内容)。
  • 清楚地记录输入和机密 - 可重用工作流通常依赖于输入和机密,团队需要知道要提供的内容。
  • 如果只需要重复使用几个步骤,而不是完整的工作流,请与复合操作结合使用。

概要

可重用工作流是在任何工程团队中强制实施一致性、减少重复和缩放 DevOps 实践的强大方法。 无论是管理 monorepo、微服务还是开源库,可重用工作流都可以简化自动化,使 CI/CD 更快、更简洁、更易于管理。

根据效果识别触发工作流的事件

了解是什么原因触发了 GitHub Actions 工作流(不论是分支推送、拉取请求、定时任务还是手动触发)对于调试、审核和改进 CI/CD 管道至关重要。 可以通过检查工作流运行、存储库更改或所涉及的问题/拉取请求来确定触发事件。

展示 GitHub Actions 中各种工作流触发器的示意图,例如推送、拉请求、计划和手动调度。

什么是工作流触发器?

工作流触发器是导致工作流启动的事件。 GitHub 支持各种类型的触发器,包括:

  • pushpull_request (基于代码更改)
  • workflow_dispatch (手动触发器)
  • 计划(cron 任务)
  • repository_dispatch (外部系统)
  • 问题、讨论和 PR 事件(例如,issues.opened、pull_request.closed)

在何处识别触发事件?

可以通过多种方式标识触发器事件:

  1. 来自 GitHub Actions UI
  • 导航到存储库中的“操作”选项卡。
  • 单击工作流运行。
  • 事件类型(例如 push,, pull_request,) workflow_dispatch显示在工作流运行摘要的顶部。
  1. 在日志或工作流中使用 github.event_name
  • GitHub 在工作流运行期间公开上下文数据。 github.event_name变量告知触发工作流的事件。
  • 可以在调试步骤中将其打印:
-name: Show event trigger
  run: echo "Triggered by ${{ github.event_name }}"
  1. 使用工作流运行详细信息
  • 如果要以编程方式检查工作流运行(例如,通过 API),则运行对象包括一个指定触发器的事件属性。
  • 你还可以找到提交的 SHA、操作者和时间戳,以便追踪触发原因。

从存储库效果推断触发器

有时,你可能无法直接访问工作流运行,但想要根据存储库活动推断出触发原因。 操作方法如下:

观察到的行为 触发器事件
推送到 main 并且工作流已运行的新提交 push 事件
打开或更新的新拉取请求 pull_request 事件
贡献者手动运行工作流 workflow_dispatch
工作流每晚在特定时间运行 schedule (cron)
工作流在外部服务调用后运行 repository_dispatch
当一个问题被标记或评论时,工作流被触发运行。 issues.* 事件

通过查看时间戳、拉取请求活动或提交历史记录,通常可以确定导致工作流运行的操作。

概要

若要确定触发工作流的原因,请执行以下步骤:

  • 在“操作”选项卡中检查工作流运行摘要。
  • 打印或记录工作流中的github.event_name以获取可见性。
  • 比较时间戳和存储库活动(提交、PR、问题)来推断触发器。
  • 使用完整的事件上下文进行更深入的调查。

这些做法有助于在整个开发和部署管道中调试、审核和提高工作流可靠性。

通过读取配置文件来描述工作流的效果

若要描述工作流从读取配置文件的效果,需要分析存储在 .github/workflows/中的“.yml”文件的结构和内容。 此文件概述了工作流运行时、其用途以及它在不同条件下的行为方式。

解释工作流的效果:

  1. 确定触发器(on:)此部分会告知工作流何时启动。 例如:
on:
  push:
    branches: [main]
  pull_request:
    types: [opened, synchronize]
  workflow_dispatch:

影响:

  • 将代码推送到主分支时自动运行。
  • 创建或更新拉取请求时运行。
  • 也可以由用户手动触发
  1. 了解作业和步骤(作业:)作业描述工作流将执行的内容。 例如:
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test

影响:

  • 使用 Linux 虚拟环境(ubuntu-latest)。
  • 签出存储库的代码。
  • 安装项目依赖项。
  • 运行自动测试。
  1. 评估目的和结果
  • 通过读取配置,可以描述工作流的预期结果:“此工作流是持续集成(CI)管道。 它可确保自动测试推送到存储库或通过拉取请求提交的任何新代码。 如果测试失败,工作流将在 GitHub UI 中指明这一点,帮助维护代码质量。
  1. 影响行为的可选功能
  • env:设置环境变量。
  • 如果:仅当满足条件时,才添加条件逻辑以运行某些步骤。
  • timeout-minutes:或 continue-on-error:影响执行行为和错误处理。

概要

通过读取工作流的配置文件,可以通过辨识来描述其效果:

  • 运行时间 (on: section),
  • 它的作用(作业和步骤),
  • 运行位置 (runs-on),
  • 运行原因(其用途:测试、部署、Lint 分析等),
  • 它在某些条件下的行为方式(环境、筛选器、逻辑)。

诊断失败的工作流运行

1. 转到“操作”选项卡

导航到存储库的“操作”选项卡,然后:

  • 查找失败的运行(通常标记为红色)
  • 单击失败的工作流以打开运行摘要。

2. 查看日志中的错误

在运行摘要中:

  • 展开每个作业和步骤,直到找到标记为失败的作业。
  • 单击可查看其日志。

查找:

  • 错误消息
  • 堆栈跟踪
  • 退出代码

例如,失败的测试可能显示 npm ERR! 测试失败。 或退出代码 1。

3.检查工作流配置文件

使用.yml文件来确定:

  • 每个步骤都试图做什么?
  • 如果存在环境变量(env:)或影响执行的条件(if:)。
  • 如果失败是由于缺少依赖项、语法错误或配置错误步骤导致的。

如果此步骤失败,请检查:

  • 依赖项是否已在上一步中成功安装?
  • 测试文件是否存在并在本地传递?

4. 常见故障方案

症状 可能的原因
步骤失败并出现 command not found 缺少依赖项或错误的设置
npm install 失败 损坏 package-lock.json,网络问题
测试步骤失败 单元测试问题、缺少配置或无效的测试语法
Permission denied 文件权限不正确或机密缺失

确定从用户界面访问工作流日志的方法

1.转到存储库

导航到包含工作流的存储库。

2. 单击“操作”选项卡

导航到位于存储库顶部导航栏中的“操作”选项卡。 此选项卡显示该存储库的所有工作流运行的历史记录。

3.选择工作流名称

  • 从列表中选择相关的工作流。 例如,如果.yml文件具有:
name: CI Workflow

列表中会显示一个名为 CI 工作流的链接。

4.选择特定运行

  • 你将看到包含状态指示器的运行列表
  • 单击要检查的特定运行的时间戳或提交消息。

5.展开每个作业和步骤

  • 运行摘要页显示工作流文件中定义的作业(例如生成、测试)。
  • 单击某个作业将其展开。
  • 在作业中,展开各个步骤(例如“安装依赖项”、“运行测试”)。

6.查看日志输出

  • 单击步骤会显示完整的日志输出(例如控制台日志、错误消息、调试信息)。
  • 可以复制、搜索或下载这些日志。

概要

行动 目的
动作选项卡 查看所有工作流执行情况
选择工作流名称 按工作流筛选运行
单击运行 查看特定的作业/步骤结果
展开步骤 查看详细日志
下载日志 针对脱机或团队故障排除

生成的操作日志

工作流运行时,它会生成一个日志,其中包含所发生事件的详细信息以及任何错误或测试失败。

如果出现错误或测试失败,则日志中会显示红色而不是绿色复选标记。 可以检查错误或失败的详细信息来调查发生了什么情况。

GitHub Actions 日志的屏幕截图,其中包含有关失败的测试的详细信息。

自定义工作流模板

在本模块开始时,我们描述了一个需要为团队设置 CI 的场景。 Node.js 模板是一个很好的开端,但你想要对其进行自定义,以更好地满足自己的团队的要求。 你想要以不同版本的 Node 和不同的作系统为目标。 你还希望生成和测试步骤是单独的作业。

让我们看看如何自定义工作流。

strategy:
  matrix:
    os: [ubuntu-latest, windows-latest]
    node-version: [16.x, 18.x]

在这里,我们配置了一个 生成矩阵 ,用于跨多个作系统和语言版本进行测试。 此矩阵会产生四个生成,每个生成对应于与每个版本的节点配对的每个操作系统。

四个版本及其所有测试都会生成相当多的日志信息。 可能很难整理所有问题。 在以下示例中,我们将演示如何将测试步骤移动到专用测试作业。 此作业针对多个目标进行测试。 分离生成和测试步骤可以更轻松地理解日志。

test:
  runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      os: [ubuntu-latest, windows-latest]
      node-version: [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 }}
  - name: npm install, and test
    run: |
      npm install
      npm test
    env:
      CI: true

在存储库中找到工作流

什么是工件?

当工作流生成日志条目以外的内容时,产品称为 项目。 例如,Node.js 构建产生一个可以部署的 Docker 容器。 此工件(容器)可以使用actions/upload-artifact上传到存储中,并稍后通过使用actions/download-artifact从存储中下载。

存储工件会在作业之间保留工件。 每个作业都使用虚拟机(VM)的新实例,因此不能通过在 VM 上保存项目来重复使用该项目。 如果需要在其他作业中使用工件,可以在一个作业中将工件上传到存储,并将其下载到另一个作业中。

工件存储

工件存储在 GitHub 的存储空间中。 对于公共存储库,空间是免费的;对于专用存储库,根据具体帐户,一定量的空间免费提供。 GitHub 可将工件存储 90 天。

在以下工作流代码片段中,actions/upload-artifact@main 操作中有一个 path: 属性。 此属性的值是存储项目的路径。 在这里,我们指定 公共/ 将一切上传到目录。 如果只想上传单个文件,请使用 公共/mytext.txt等内容。

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: npm install and build webpack
        run: |
          npm install
          npm run build
      - uses: actions/upload-artifact@main
        with:
          name: webpack artifacts
          path: public/

若要下载用于测试的工件,构建必须成功完成并上传工件。 在以下代码中,我们指定测试作业依赖于生成作业。

test:
    needs: build
    runs-on: ubuntu-latest

在以下工作流代码片段中,我们将下载该工件。 现在,测试作业可以使用产物进行测试。

steps:
    - uses: actions/checkout@v3
    - uses: actions/download-artifact@main
      with:
        name: webpack artifacts
        path: public

有关在工作流中使用工件的详细信息,请查看 GitHub 文档中的将工作流数据存储为工件

在 GitHub 中使用工作流自动化审阅

到目前为止,我们介绍了使用 GitHub 事件(如推送或 拉取请求)启动工作流。 我们可以按计划运行工作流,也可以根据 GitHub 外部的某些事件来运行工作流。

有时,我们希望仅在某个人员执行动作后运行工作流。 例如,我们可能只想在审核者批准拉取请求后再运行工作流。 对于此方案,我们可以在 pull-request-review 上触发。

我们可以采取的另一个措施是向拉取请求添加标签。 在本例中,我们将使用 pullreminders/label-when-approved-action 操作。

    steps:
     - name: Label when approved
       uses: pullreminders/label-when-approved-action@main
       env:
         APPROVALS: "1"
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         ADD_LABEL: "approved"

请注意被称为 env: 的块。 此块用于设置此作的环境变量。 例如,可以设置所需的审批者数。 这里有一个。 身份验证 secrets.GITHUB_TOKEN 变量是必需的,因为该作必须通过添加标签对存储库进行更改。 最后,提供要添加的标签的名称。

添加标签可能是启动另一个工作流的事件,例如合并。 我们将在下一模块中介绍使用 GitHub Actions 持续交付的此事件。