使用环境变量和项目数据自定义工作流

已完成

你将在本单元了解如何使用默认的自定义环境变量、自定义脚本、缓存依赖项,以及如何在作业之间传递项目数据。 你还将了解如何从 GitHub 网站和 REST API 终结点访问工作流日志。

默认环境变量和上下文

GitHub Actions 工作流中有多个默认的环境变量可供使用,但只能在执行作业的运行器中使用。 这些默认变量区分大小写,它们指的是系统和当前用户的配置值。 建议使用这些默认环境变量(而非使用硬编码文件路径)来引用文件系统。 若要使用默认环境变量,请指定 $,后跟环境变量的名称。

jobs:
  prod-check:
    steps:
      - run: echo "Deploying to production server on branch $GITHUB_REF"

除默认环境变量外,还可以使用已定义的变量作为上下文。 上下文与默认变量的相似之处在于它们均可提供环境信息的访问权限,但两者之间仍然存在一些重要差异。 虽然默认环境变量只能在运行器中使用,但上下文变量可在工作流内的任何位置使用。 例如,上下文变量让你可以运行 if 语句,以便在执行运行器之前评估表达式。

name: CI
on: push
jobs:
  prod-check:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to production server on branch $GITHUB_REF"

此示例使用 github.ref 上下文来检查触发工作流的分支。 如果分支为 main,则运行器将执行并输出“Deploying to production server on branch $GITHUB_REF”。 运行器中使用默认环境变量 $GITHUB_REF 来引用分支。 请注意,默认环境变量均采用大写形式,而上下文变量均采用小写形式。

自定义环境变量

与使用默认环境变量类似,可以在工作流文件中使用自定义环境变量。 若要创建自定义变量,需要使用 env 上下文在工作流文件中对其进行定义。 如果要在运行器内使用环境变量的值,则可以使用运行器操作系统的常规方法来读取环境变量。

name: CI
on: push
jobs:
  prod-check:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Nice work, $First_Name. Deploying to production server on branch $GITHUB_REF"
        env:
          First_Name: Mona

工作流中的脚本

在上述工作流代码段示例中,run 关键字仅用于输出文本字符串。 由于 run 关键字会告诉作业在运行器上执行命令,因此请使用 run 关键字来运行操作或脚本。

jobs:
  example-job:
    steps:
      - run: npm install -g bats

在本例中,您使用 npm 通过试用 run 关键字来安装 bats 软件测试包。 还可以将脚本作为操作运行。 你可以将该脚本存储在存储库中(通常在 .github/scripts/ 目录中完成),然后使用 run 关键字提供路径和 shell 类型。

jobs:
  example-job:
    steps:
      - name: Run build script
        run: ./.github/scripts/build.sh
        shell: bash

使用缓存操作缓存依赖项

构建工作流时,你常常会发现需要重复使用相同输出或需要将依赖项从一个运行下载到另一个运行。 你可以缓存这些依赖项,以便更快、更高效地运行工作流,而不是反复下载这些依赖项。 这样做可以显著缩短在工作流中运行某些步骤所需的时间,因为 GitHub 托管运行器上的作业每次都会在干净的虚拟环境中开始。 缓存依赖项有助于加快重新创建这些依赖项文件的速度。

要缓存作业的依赖项,请使用 GitHub 的 cache 操作。 此操作会检索你提供的唯一密钥发现的缓存。 该操作会在查找缓存后,将缓存的文件检索到你配置的路径。 要使用 cache 操作,需要设置一些特定参数:

参数 步骤 必选
密钥 指保存和搜索缓存时创建的密钥标识符。
路径 指运行器上用于缓存或搜索的文件路径。
还原-密钥 包含缓存的替代现有密钥(如果找不到所需的缓存密钥)。
steps:
  - uses: actions/checkout@v2

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

在以上示例中,path 被设置为 ~/.npm,且 key 包含运行器的操作系统和 package-lock.json 文件的 SHA-256 哈希。 在使用 restore-keys 回退并有多重缓存时,以 ID 作为密钥前缀(在此示例中 npm-cache)非常有用。

在作业间传递项目数据

与在工作流中缓存依赖项的想法类似,可以在同一工作流内的作业之间传递数据。 可以通过使用 upload-artifactdownload-artifact 操作来实现此目的。 依赖于前一作业的项目的作业必须等待前一作业成功完成才能运行。 如果有一系列作业需要根据上一作业所上传的项目来按顺序运行,这样做会很有用。 例如,job_2 需要 job_1,方法是使用 needs: job_1 语法。

name: Share data between jobs
on: push
jobs:
  job_1:
    name: Upload File
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello World" > file.txt
      - uses: actions/upload-artifact@v2
        with:
          name: file
          path: file.txt

  job_2:
    name: Download File
    runs-on: ubuntu-latest
    needs: job_1
    steps:
      - uses: actions/download-artifact@v2
        with:
          name: file
      - run: cat file.txt

上一示例有两个作业。 job_1 将一些文本写入文件 file.txt 中,然后使用 actions/upload-artifact@v2 操作上传此项目并存储数据,以便将来在工作流中使用。 job_2 需要通过使用 needs: job_1 语法完成 job_1,使用 actions/download-artifact@v2 操作下载该项目,然后输出 file.txt 的内容。

在工作流中启用步骤调试日志记录

在某些情况下,默认工作流日志无法提供足够的详细信息,来诊断特定工作流运行、作业或步骤失败的原因。 对于这些情况而言,可以针对“运行”和“步骤”两个选项启用其他调试日志记录。 通过将需要对存储库进行 admin 访问的两个存储库机密设置为 true,启用此诊断日志记录:

  • 若要启用运行器诊断日志记录,请将包含工作流的存储库中的 ACTIONS_RUNNER_DEBUG 密码设置为 true
  • 若要启用步骤诊断日志记录,请将包含工作流的存储库中的 ACTIONS_STEP_DEBUG 密码设置为 true

从用户界面访问工作流日志

考虑到成功自动化时,你的目标是花最少的时间了解实现自动化的操作,以便关注相关内容。 但有时事情不会如期发展,你需要了解发生了什么情况。 调试过程可能会令人沮丧不已,但你可以使用 GitHub 提供的清晰的布局结构,在维持当前调试步骤的上下文的同时,在作业之间快速导航。 若要查看 GitHub 中的工作流运行的日志,可以执行以下步骤:

  1. 导航到存储库中的“操作”选项卡。
  2. 在左侧边栏中,单击所需的工作流。
  3. 从工作流运行列表中,选择所需运行。
  4. 在“作业”下,选择所需的作业。
  5. 阅读日志输出。

如果工作流中有多个运行,还可以在选择工作流后选择“状态”筛选器并将其设置为“失败”,以仅显示该工作流中的失败的运行。

从 REST API 访问工作流日志

除使用 GitHub 查看日志以外,还可以使用 GitHub 的 REST API 查看工作流运行的日志、重新运行工作流,甚至取消工作流运行。 若要使用 API 查看工作流运行的日志,需要向日志终结点发送 GET 请求。 请记住,拥有存储库读取权限的任何人员均可使用此终结点。 如果存储库为专用,则必须使用具有 repo 作用域的访问令牌。

例如,用于查看特定工作流运行日志的 GET 请求将遵循以下路径:

GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs