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

已完成

回想一下,你的目标是自动执行代码生成和发布过程,以便每次开发人员向代码库添加更改时更新功能。

若要实现此过程,请了解如何:

  • 从模板创建工作流。
  • 使用可重用工作流避免重复。
  • 针对多个目标进行测试。
  • 单独的构建和测试作业。

从模板创建工作流

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

在 GitHub 存储库的主页上,选择 操作,然后选择 新建工作流

“选择工作流 ”页上,可以从许多类型的模板中进行选择。 一个示例是 Node.js 模板。 Node.js 模板安装 Node.js 和所有依赖项,生成源代码,并针对不同版本的 Node.js运行测试。 另一个示例是 Python 包 模板,它安装 Python 及其依赖项,然后在多个 Python 版本中运行测试(包括 lint)。

若要从 Node.js 工作流模板开始,请在搜索框中输入 Node.js

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

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

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

项目的 node.js.yml 文件是根据模板创建的:

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.js 版本 14.x、16.x 和 18.x。 该 matrix 属性将在模块的后面部分进行深入描述。

jobs 属性中,这些步骤使用 GitHub Actions actions/checkout@v3 动作将代码从存储库获取到虚拟机(VM),并使用 actions/setup-node@v3 来设置正确的 Node.js版本。 指定要使用属性 ${{ matrix.node-version }} 测试三个版本的 Node.js。 此属性引用前面定义的矩阵。 该 cache 属性指定用于在默认目录中缓存的包管理器。

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

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

开发人员团队可以从使用可重用工作流来简化和标准化重复的自动化步骤中获益。 通过使用可重用工作流,可以减少冗余,提高可维护性,并确保持续集成/持续部署(CI/CD)管道之间的一致性。

使用可重用工作流避免重复

随着团队的规模和项目的增长,在多个工作流文件中重复相同的步骤很常见。 这些步骤可能包括代码签出、依赖项安装、测试和部署。 此类重复不仅使代码库混乱,还增加了需要更改代码时的维护时间。 可重用工作流通过允许定义自动化逻辑一次,然后从其他工作流调用逻辑来解决此问题。

可重用工作流是其他工作流可以调用的特殊 GitHub Actions 工作流,类似于编程中的函数。 创建它们以共享重复的逻辑,例如生成步骤、测试过程或部署策略。 创建可重用工作流后,可以从同一存储库中的其他任何工作流,甚至在不同的存储库中引用它。

显示 GitHub Actions 中可重用工作流的概念的关系图。多个存储库或工作流可以引用中央工作流。

为何使用可重用工作流?

以下是使用可重用工作流的好处:

  • 一致性。 团队可以在所有项目中遵循相同的自动化标准。
  • 效率。 只需指向可重用的工作流,而不是复制和粘贴步骤。
  • 简化的更新。 当进程发生更改(例如通过添加测试步骤)时,可以在一个位置更新它。 然后,使用该工作流的所有工作流会自动获益。
  • 可伸缩性。 可重用工作流非常适合管理多个服务的平台或 DevOps 团队。

接下来,了解如何使用可重用工作流改进项目。

实现可重用工作流

若要使用可重用工作流,请使用:

  1. 在存储库文件夹中,创建可重用的工作流。 该文件包括要共享的自动化步骤,例如测试、生成和部署所涉及的常见步骤。
  2. 通过使用 workflow_call 事件配置,使工作流显式可重用。
  3. 在主工作流(调用方工作流)中,引用此可重用文件并提供任何必需的输入或机密。

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

示例:

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

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

如果没有可重用的工作流,每个存储库最终都会跨多个工作流文件复制相同的逻辑,从而导致重复的步骤和更难的维护。

如果使用可重用工作流:

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

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

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

最佳做法

  • 如果计划跨团队共享可重用工作流,请将可重用工作流集中到一个存储库中。
  • 使用分支或标记对工作流进行版本控制(例如,使用 @v1),以便在需要时可以轻松回滚更改。
  • 清楚地记录输入和机密。 可重用工作流通常依赖于输入和机密。 团队需要知道应该使用哪些信息。
  • 如果只需要重复使用几个步骤,请结合可重用工作流和复合操作,而不是创建完整的工作流。

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

自定义工作流模板

在本模块的开头,你已考虑了需要为开发人员团队设置 CI 的方案。 Node.js 模板是一个很好的开端,但你想要对其进行自定义,以便更好地满足团队的要求。 你需要面向 Node.js 的不同版本和不同的操作系统。 你还希望生成和测试步骤是单独的作业。

下面是自定义工作流的示例:

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

在此示例中,你将配置一个 生成矩阵 ,用于跨多个作系统和语言版本进行测试。 此矩阵会产生四个版本,每个操作系统的版本搭配每个 Node.js 版本。

四个构建及其测试会产生大量的日志数据。 可能很难整理所有问题。 在以下示例中,将测试步骤移动到专用测试作业。 此作业针对多个目标进行测试。 分离生成和测试步骤可以更轻松地处理日志数据。

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