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

已完成

在这里,你将了解如何使用默认和自定义环境变量、自定义脚本、缓存依赖项,以及如何在作业之间传递项目数据。 你还将了解如何从 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 来引用分支。 请注意,默认环境变量均采用大写形式,而上下文变量均采用小写形式。

工作流中可用的上下文信息

上下文允许访问有关工作流运行、变量、运行程序环境、作业和步骤的信息。 每个上下文都是一个对象,其中包含可以是其他对象或字符串的属性。 可用的上下文包括:githubenvvarsjobjobsstepsrunnersecretsstrategymatrixneedsinputs。 下表显示了这些上下文及其说明。

上下文 步骤
GitHub 有关工作流运行的信息。 有关详细信息,请参阅 github 上下文
env 包含工作流、作业或步骤中设置的变量。 有关详细信息,请参阅 env 上下文
vars 包含存储库、组织或环境级别设置的变量。 有关详细信息,请参阅 vars 上下文
作业 有关当前正在运行的作业的信息。 有关详细信息,请参阅 作业上下文
jobs 仅适用于可重用工作流,包含可重用工作流中的作业输出。 有关详细信息,请参阅 作业上下文
步骤 有关当前作业中运行的步骤的信息。 有关详细信息,请参阅 步骤上下文
跑步者 有关运行当前作业的运行器的信息。 有关详细信息,请参阅 运行程序上下文
机密 包含可供工作流运行使用的机密名称和值。 有关详细信息,请参阅 机密上下文
策略 有关当前作业的矩阵执行策略的信息。 有关详细信息,请参阅 策略上下文
矩形图 包含在工作流中定义的应用于当前作业的矩阵属性。 有关详细信息,请参阅 矩阵上下文
needs 包含定义为当前作业依赖项的所有作业的输出。 有关详细信息,请参阅 needs context
输入 包含可重用或手动触发的工作流的输入。 有关详细信息,请参阅 输入上下文

工作流运行中可以使用不同的上下文。 例如,机密上下文只能在作业中的某些位置使用。 此外,你只能在某些位置使用某些函数。 例如,函数 hashFiles 在任何地方都不可用。

下表列出了工作流中各个上下文和特殊函数的使用限制。 列出的上下文仅适用于给定的工作流密钥,不能在其他任何位置使用它们。 除非此处的表中列出,否则可以在任意位置使用函数。

工作流密钥 上下文 特殊函数
运行名称 github, inputs, vars 没有
并发 github, inputs, vars 没有
env github,机密信息,输入,变量 没有
jobs.<job_id>.concurrency github, 需求, 策略, 矩阵, 输入, vars 没有
jobs.<job_id>.container github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.container.credentials github, 需求, 策略, 矩阵, env, vars, 机密, 输入 没有
jobs.<job_id>.container.env.<env_id> github, needs, strategy, matrix, job, runner, env, vars, secrets, inputs 没有
jobs.<job_id>.container.image github, 需求, 策略, 矩阵, 变量, 输入 没有
jobs.<job_id>.continue-on-error github,需求,策略,变量,矩阵,输入 没有
jobs.<job_id>.defaults.run github, needs, strategy, matrix, env, vars, inputs 没有
jobs.<job_id>.env github,需求,策略,矩阵,变量,机密,输入 没有
jobs.<job_id>.environment github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.environment.url github, needs, strategy, matrix, job, runner, env, vars, steps, inputs 没有
jobs.<job_id>.if GitHub,需求,变量,输入 always, canceled, success, failure
jobs.<job_id>.name github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.outputs.<output_id> github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs 没有
jobs.<job_id>.runs-on github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.secrets.<secrets_id> github, 需求, 策略, 矩阵, 机密, 输入, vars 没有
jobs.<job_id>.services github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.services.<service_id>.credentials github, 需求, 策略, 矩阵, env, vars, 机密, 输入 没有
jobs.<job_id>.services.<service_id>.env.<env_id> github, needs, strategy, matrix, job, runner, env, vars, secrets, inputs 没有
jobs.<job_id>.steps.continue-on-error github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.env github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.if github, needs, strategy, matrix, job, runner, env, vars, steps, inputs always, canceled, success, failure, hashFiles
jobs.<job_id>.steps.name github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.run github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.timeout-minutes github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.with github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs hashFiles
jobs.<job_id>.steps.working-directory github,需求,策略,矩阵,任务,运行器,环境,变量,密钥,步骤,输入 hashFiles
jobs.<job_id>.strategy github,需求,变量,输入 没有
jobs.<job_id>.timeout-minutes github,需求,策略,矩阵,变量,输入 没有
jobs.<job_id>.with.<with_id> github, 需求, 策略, 矩阵, 输入, vars 没有
on.workflow_call.inputs.<inputs_id>.default github, inputs, vars 没有
on.workflow_call.outputs.<output_id>.value github, jobs, vars, inputs 没有

在工作流中设置自定义环境变量

可以在工作流文件的顶层利用 env 定义整个工作流范围内的环境变量。 使用 jobs.<job_id>.env 确定工作流中作业的内容的范围。 此外,您可以在作业进行的某个特定步骤中,通过利用jobs.<job_id>.steps[*].env为环境变量设定范围。

下一个示例显示工作流文件中的所有三种方案:

name: Greeting on variable day

on:
  workflow_dispatch

env:
  DAY_OF_WEEK: Monday

jobs:
  greeting_job:
    runs-on: ubuntu-latest
    env:
      Greeting: Hello
    steps:
      - name: "Say Hello Mona it's Monday"
        run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
        env:
          First_Name: Mona

在工作流中使用默认上下文

默认环境变量由 GitHub 设置,未在工作流中定义。 它们可用于相应上下文中的工作流。 除了CI,大多数变量都以GITHUB_*RUNNER_*开头。 无法覆盖后两种类型。 此外,这些默认变量还有一个对应的上下文属性,并且名称类似。 例如,一 RUNNER_* 系列默认变量具有匹配的 runner.*上下文属性。 可在此处查看应用这些方法的工作流中访问默认变量的示例:

on: workflow_dispatch

jobs:
  if-Windows-else:
    runs-on: macos-latest
    steps:
      - name: condition 1
        if: runner.os == 'Windows'
        run: echo "The operating system on the runner is $env:RUNNER_OS."
      - name: condition 2
        if: runner.os != 'Windows'
        run: echo "The operating system on the runner is not Windows, it's $RUNNER_OS."

有关详细信息,请参阅 GitHub 用户文档中 的默认环境变量

将自定义环境变量传递到工作流

可以将客户环境变量从工作流作业的一个步骤传递到作业中的后续步骤。 在作业的一个步骤中生成值,并将该值分配给现有或新的环境变量。 接下来,将变量/值对写入GITHUB_ENV环境文件。 环境文件可以通过动作使用,或者在工作流作业中通过 shell 命令使用 run 关键字。

创建或更新环境变量的步骤无权访问新值,但作业中的所有后续步骤都具有访问权限。

可在此处查看示例:

steps:
  - name: Set the value
    id: step_one
    run: |
      echo "action_state=yellow" >> "$GITHUB_ENV"
  - name: Use the value
    id: step_two
    run: |
      printf '%s\n' "$action_state" # This will output 'yellow'

增加环境保护措施

可以为为 GitHub 存储库定义的环境添加保护规则。 若要添加环境,请在存储库中:

  1. 单击 Web 界面的 “设置”导航栏,其中包含“代码”、“问题和 Wiki”等选项卡;突出显示了“设置”。

  2. 单击左侧面板中的环境

“常规”下的设置菜单的屏幕截图,其中包含访问、代码和自动化、安全性和集成部分。“环境”选项以红色突出显示。

  1. 使用 “新建环境 ”按钮添加和配置环境和添加保护。 GitHub 存储库设置页,其中显示了“环境”部分,其中显示一条消息,指示不存在环境,并突出显示了“新建环境”按钮。

关于环境

环境用于描述常规部署目标,例如生产、过渡或开发。 当 GitHub Actions 工作流部署到环境时,环境将显示在存储库的主页上。 可以使用环境来要求审批作业以继续,限制可以触发工作流的分支,使用自定义部署保护规则控制部署,或限制对机密的访问权限。

工作流程中的每个作业都可以引用单个环境。 在将引用环境的作业发送到运行器之前,必须通过为环境配置的任何保护规则。 只有在将作业发送给运行器后,作业才能访问环境的机密。

当工作流引用环境时,环境将显示在存储库的部署中。

环境保护规则

环境部署保护规则要求在涉及环境的作业继续之前必须满足特定条件。 可以使用部署保护规则来要求人工审批、延迟作业或将环境限制于某些分支。 您还可以创建和实施由 GitHub 应用提供支持的自定义保护规则,以使用第三方系统来控制引用在 GitHub 上配置的环境的部署。 下面是这些保护规则的说明:

  1. 必需审阅者保护规则:使用必需审阅者规则来要求特定人员或团队批准引用环境的工作流作业。 您最多可以列出六个用户或团队作为审查者。 审查者必须至少具有对仓库的读取访问权限。 只需指定一名审查者即可批准该作业,使其可继续进行。

    也可以选择阻止对受保护环境中的部署进行自评审。 如果启用此设置,则启动部署的用户无法批准部署作业,即使他们是所需的审阅者也是如此。 通过启用自我评审,可确保对受保护环境的部署始终由多个人员审查。

    有关审阅引用了具有必需审阅者的环境的作业的详细信息,请参阅审阅部署

  2. 等待计时器投影规则: 可以使用等待计时器保护规则在最初触发作业后将作业延迟特定时间,然后才允许环境部署继续。 时间(以分钟为单位)必须是介于 1 和 43,200(30 天)之间的整数。等待时间不会计入计费时间。

  3. 分支和标记保护规则: 可以使用部署分支和标记保护规则来限制将哪些分支和标记用于部署到环境。 对于环境,有多个选项可用于部署分支和标记保护规则。

  • 没有限制 意味着可以将任何分支或标签部署到环境中。 “仅限受保护的分支”只允许将启用了分支保护规则的分支部署到环境。 如果没有为仓库中的任何分支定义分支保护规则,那么所有分支都可以部署。 “所选分支和标记”设置可确保只有与指定名称模式匹配的分支和标记才能部署到环境。

  • 例如,如果指定 releases/* 为部署分支或标记规则,则只有名称以 releases/ 开头的分支或标记才能部署到环境。 (通配符不匹配 /。若要匹配以 release/ 开头并额外包含单斜杠的分支或标记,请使用 release/*/*。)如果将 main 添加为分支规则,则名为 main 的分支也可以部署到环境。

  1. 自定义部署保护规则: 可以启用自己的自定义保护规则来限制第三方服务的部署。 例如,可以使用可观测性系统、更改管理系统、代码质量系统或其他手动配置来评估就绪情况,并为部署到 GitHub 的部署提供自动审批。

    在存储库上创建和安装自定义部署保护规则后,可以为存储库中的任何环境启用自定义部署保护规则。

    用于配置“Environment1”的设置页,其中包含审阅者、等待计时器、自定义规则和分支限制的选项。

注释

如果使用的是 GitHub Free、GitHub Pro 或 GitHub Team 计划,则环境部署投影规则仅适用于公共存储库;分支和标记保护规则除外。 对于 GitHub Pro 或 GitHub Team 计划的用户,分支和标记保护规则也可用于专用存储库。

工作流中的脚本

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

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

在本例中,您使用 npm 通过试用 bats 关键字来安装 run 软件测试包。 还可以将脚本作为操作运行。 你可以将该脚本存储在存储库中(通常在 .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 哈希。 在使用 npm-cache 回退并有多重缓存时,以 ID 作为密钥前缀(在此示例中 restore-keys)非常有用。

在作业间传递项目数据

与在工作流中缓存依赖项的想法类似,可以在同一工作流内的作业之间传递数据。 可以通过使用 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 要求使用 job_1 语法完成 needs: 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

确定何时使用 GitHub App 中的安装令牌

在帐户上安装 GitHub 应用后,可以使用“安装访问令牌”将其作为应用安装进行身份验证,以便发起 REST 和 GraphQL API 请求。 这允许应用访问安装拥有的资源,前提是应用被授予了必要的存储库访问权限和权限。 应用安装发出的 REST 或 GraphQL API 请求归因于应用。 在以下示例中,将 INSTALLATION_ACCESS_TOKEN 替换为安装访问令牌:

curl --request GET \
--url "https://api.github.com/meta" \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer INSTALLATION_ACCESS_TOKEN" \
--header "X-GitHub-Api-Version: 2022-11-28"

还可以使用安装访问令牌对基于 HTTP 的 Git 访问进行身份验证。 应用必须具有“内容”存储库权限。 然后可以使用安装访问令牌作为 HTTP 密码。 将示例中的 TOKEN 替换为安装访问令牌:

git clone https://x-access-token:TOKEN@github.com/owner/repo.git