LV02-GitHubActions-02-工作流程语法

GitHub Actions的工作流程怎么写?语法是怎样的?若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.2的64位版本
VMware® Workstation 17 Pro 17.6.0 build-24238078
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
Linux开发板环境 Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,使用的uboot版本为U-Boot 2019.04
linux内核 linux-4.19.71(NXP官方提供)
点击查看本文参考资料
分类 网址 说明
官方网站 GitHub Actions 工作流程语法 GitHub Actions 工作流程语法 - GitHub 文档 - GitHub 文档
YAML官网 在这里可以找到YAML的基本语法
点击查看相关文件下载
分类 网址 说明
--- --- ---

一、基本概念

1. 基本术语

GitHub Actions 有一些自己的术语。

(1)workflow (工作流程):持续集成一次运行的过程,就是一个 workflow。

(2)job (任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。

(3)step(步骤):每个 job 由多个 step 构成,一步步完成。

(4)action (动作):每个 step 可以依次执行一个或多个命令(action)。

(5)上下文:上下文是一种访问有关工作流运行、变量、运行器环境、作业和步骤的信息的方法。每个上下文都是一个包含属性的对象,这些属性可以是字符串或其他对象。

2. workflow 文件

GitHub Actions 的配置文件叫做 workflow 文件,存放在代码仓库的.github/workflows目录。workflow 文件采用 YAML 格式,文件名可以任意取,但是后缀名统一为.yml,比如foo.yml。一个库可以有多个 workflow 文件。GitHub 只要发现.github/workflows目录里面有.yml文件,就会自动运行该文件。

3. 上下文

具体的上下文相关内容可以查看文档:访问工作流运行的上下文信息 - GitHub Docs - GitHub 文档。里面的github 上下文secrets上下文 等,后面会经常用到。

二、工作流语法

1. name

工作流的名称。GitHub 会在我们的存储库的“Actions”选项卡下显示我们的工作流名称。如果我们省略 name,GitHub 将显示相对于存储库根目录的工作流文件路径。

2. run-name

工作流运行的名称,由工作流生成。GitHub 会在我们的仓库“Actions”选项卡的工作流运行列表中显示工作流运行名称。如果省略run-name或仅包含空格,则运行名称将设置为工作流运行的特定于事件的信息。例如,对于由pushpull_request事件触发的 workflow,它将设置为提交消息或拉取请求的标题。

此值可以包含表达式,并可以引用githubinputs上下文。

run-name示例:

1
run-name: Deploy to ${{ inputs.deploy_target }} by @${{ github.actor }}

3. on

要自动触发工作流,请使用on定义哪些事件可以导致工作流运行。有关可用事件的列表,请参阅“触发工作流的事件”。

我们可以定义可以触发工作流的单个或多个事件,或设置时间表。还可以将工作流的执行限制为仅针对特定文件、标签或分支更改发生。

3.1 使用单个事件

可以指定单个事件或多个事件。例如,具有以下on值的工作流将在向存储库中的任何分支推送时运行,或在有人分叉存储库时运行:

1
on: [push, fork]

如果指定多个事件,则只需要发生其中一个事件即可触发工作流。如果工作流的多个触发事件同时发生,则会触发多个工作流运行。

3.2 使用活动类型

某些事件具有活动类型,可以让我们更好地控制工作流何时运行。使用on..types定义将触发工作流运行的事件活动类型。

例如,issue_comment事件具有createdediteddeleted活动类型。如果我们的工作流触发label事件,则只要创建、编辑或删除标签,它就会运行。如果为label事件指定created活动类型,则在创建标签时我们的工作流将运行,但在编辑或删除标签时不会运行。

1
2
3
4
on:
label:
types:
- created

如果指定多个活动类型,则只需要发生其中一个事件活动类型即可触发工作流。如果我们的工作流的多个触发事件活动类型同时发生,则会触发多个工作流运行。例如,以下工作流在打开或标记问题时触发。如果打开了一个带有两个标签的问题,则将启动三个工作流运行:一个用于打开的问题事件,两个用于两个标记的问题事件。

1
2
3
4
5
on:
issues:
types:
- opened
- labeled

有关每个事件及其活动类型的更多信息,请参阅“触发工作流的事件”。

3.3 使用过滤器

某些事件具有过滤器,可以让我们更好地控制工作流何时运行。例如,push事件具有branches过滤器,该过滤器会导致我们的工作流仅在向与branches过滤器匹配的分支推送时运行,而不是在任何推送时运行。

1
2
3
4
5
on:
push:
branches:
- main
- 'releases/**'

3.4 结合使用活动类型和过滤器以及多个事件

如果为事件指定活动类型或过滤器,并且我们的工作流触发多个事件,则必须分别配置每个事件。必须为所有事件附加冒号(:),包括没有配置的事件。例如,具有以下on值的工作流将在以下情况下运行:

  • 创建标签
  • 向存储库中的main分支推送
  • 向启用了 GitHub Pages 的分支推送
1
2
3
4
5
6
7
8
on:
label:
types:
- created
push:
branches:
- main
page_build:

3.5 总结

on 还有很多可用的语法,这里就不再详细写了,都是文档里面的,直接看文档即可。

4. jobs

一个工作流运行由一个或多个jobs组成,默认情况下这些jobs并行运行。要顺序运行作业,我们可以使用jobs..needs关键字定义对其他作业的依赖关系。

每个作业都在由runs-on指定的运行器环境中运行。

只要我们在工作流使用限制范围内,就可以运行无限数量的作业。更多信息,请参见关于 GitHub 托管运行器的“使用限制、计费和管理”以及关于自托管运行器使用限制的“关于自托管运行器”。

如果我们需要查找工作流运行中运行的作业的唯一标识符,可以使用 GitHub API。更多信息,请参见“GitHub Actions 的 REST API 端点”。

4.1 jobs..needs

4.1.1 语法说明

使用jobs..needs标识在该作业运行之前必须成功完成的任何作业。它可以是字符串或字符串数组。如果作业失败或被跳过,则所有需要它的作业都将被跳过,除非作业使用导致作业继续的条件表达式。如果运行包含一系列相互依赖的作业,则从失败或跳过点开始,依赖链中的所有作业都将应用失败或跳过。如果我们希望即使依赖的作业没有成功也运行作业,请在jobs..if中使用always()条件表达式。

4.1.2 示例:需要成功的依赖作业

1
2
3
4
5
6
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]

在此示例中,job1必须成功完成才能开始job2,而job3等待job1job2都完成。

此示例中的作业顺序运行

(1)job1

(2)job2

(3)job3

4.1.3 示例:不需要成功的依赖作业

1
2
3
4
5
6
7
jobs:
job1:
job2:
needs: job1
job3:
if: ${{ always() }}
needs: [job1, job2]

在此示例中,job3使用always()条件表达式,以便在job1job2完成后始终运行,无论它们是否成功。更多信息,请参见“在工作流和操作中评估表达式”。

4.2 jobs..runs-on

4.2.1 语法说明

使用jobs..runs-on定义要在其上运行作业的机器类型。

  • 目标机器可以是GitHub 托管运行器更大运行器自托管运行器

  • 我们可以根据分配给运行器的标签、其组成员身份或两者的组合来定位运行器。

  • 我们可以将runs-on提供为

    • 单个字符串
    • 包含字符串的单个变量
    • 字符串数组、包含字符串的变量或两者的组合
    • 使用grouplabels键的key: value
  • 如果我们指定字符串或变量数组,我们的工作流将在与所有指定的runs-on值匹配的任何运行器上执行。例如,这里作业将只在具有标签linuxx64gpu的自托管运行器上运行

    1
    runs-on: [self-hosted, linux, x64, gpu]

    更多信息,请参见“选择自托管运行器”。

  • 我们可以在数组中混合字符串和变量。例如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    on:
    workflow_dispatch:
    inputs:
    chosen-os:
    required: true
    type: choice
    options:
    - Ubuntu
    - macOS

    jobs:
    test:
    runs-on: [self-hosted, "${{ inputs.chosen-os }}"]
    steps:
    - run: echo Hello world!
  • 如果我们想在多台机器上运行工作流,可以使用jobs..strategy

注意:

简单字符串(如self-hosted)不需要引号,但表达式(如"${{ inputs.chosen-os }}")需要引号。

4.2.2 选择 GitHub 托管运行器

如果我们使用 GitHub 托管运行器,则每个作业都在runs-on指定的运行器映像的新实例中运行。

当我们使用 GitHub 托管运行器时,runs-on的值是运行器标签或运行器组的名称。标准 GitHub 托管运行器的标签显示在下表中。

更多信息,请参见“关于 GitHub 托管运行器”。GitHub有一些公共存储库的标准 GitHub 托管运行器,对于公共存储库,使用下表中所示工作流标签的作业将在具有关联规格的虚拟机上运行。在公共存储库上使用这些运行器是免费且无限的。

虚拟机 处理器 (CPU) 内存 (RAM) 存储 (SSD) 工作流标签
Linux 4 16 GB 14 GB ubuntu-latestubuntu-24.04ubuntu-22.04ubuntu-20.04
Windows 4 16 GB 14 GB windows-latestwindows-2022windows-2019
macOS 3 14 GB 14 GB macos-12
macOS 4 14 GB 14 GB macos-13
macOS 3 (M1) 7 GB 14 GB macos-latestmacos-14macos-15 [公开预览]

GitHub还有一些私有存储库的标准 GitHub 托管运行器。对于私有存储库,使用下表中所示工作流标签的作业将在具有关联规格的虚拟机上运行。这些运行器使用我们的 GitHub 帐户分配的免费分钟数,然后按分钟费率收费。更多信息,请参见“关于 GitHub Actions 的计费”。

虚拟机 处理器 (CPU) 内存 (RAM) 存储 (SSD) 工作流标签
Linux 2 7 GB 14 GB ubuntu-latestubuntu-24.04ubuntu-22.04ubuntu-20.04
Windows 2 7 GB 14 GB windows-latestwindows-2022windows-2019
macOS 3 14 GB 14 GB macos-12
macOS 4 14 GB 14 GB macos-13
macOS 3 (M1) 7 GB 14 GB macos-latestmacos-14macos-15 [公开预览]

除了标准的 GitHub 托管运行器外,GitHub 还为使用 GitHub Team 和 GitHub Enterprise Cloud 计划的客户提供一系列具有高级功能的托管虚拟机——例如,更多核心和磁盘空间、GPU 加速的机器和 ARM 架构的机器。更多信息,请参阅“关于大型运行器”。

注意

-latest 运行器镜像是 GitHub 提供的最新稳定镜像,可能不是操作系统供应商提供的最新操作系统版本。

警告

Beta 版和已弃用的镜像按“现状”、“包含所有缺陷”和“按可用性”提供,不包含在服务等级协议和保修范围内。Beta 版镜像可能不包含在客户支持范围内。

下面代码指定虚拟机环境为ubuntu-20.04

1
runs-on: ubuntu-20.04

4.2.3 选择自托管运行器

要为我们的作业指定自托管运行器,可以在我们的工作流文件中使用自托管运行器标签配置runs-on

自托管运行器可能具有self-hosted标签。设置自托管运行器时,默认情况下GitHub Actions将包含标签self-hosted。我们可以传入--no-default-labels标志以防止应用自托管标签。标签可用于为运行器创建目标选项,例如操作系统或架构,GitHub Actions建议提供一个以self-hosted开头的标签数组(此标签必须列在首位),然后根据需要包含其他标签。当我们指定一个标签数组时,作业将排队到具有我们指定的所有标签的运行器上。

请注意,Actions 运行器控制器不支持多个标签,也不支持self-hosted标签。

示例:使用标签进行运行器选择

1
runs-on: [self-hosted, linux]

更多信息,请参阅“关于自托管运行器”和“在工作流中使用自托管运行器”。

4.3 jobs..if

4.3.1 语法说明

我们可以使用jobs..if条件来阻止作业运行,除非满足某个条件。我们可以使用任何受支持的上下文和表达式来创建条件。有关此键中支持哪些上下文的更多信息,请参见“访问有关工作流运行的上下文信息”。

注意

jobs..if条件在应用jobs..strategy.matrix之前进行评估。

当我们在if条件中使用表达式时,可以选择省略${{ }}表达式语法,因为 GitHub Actions 会自动将if条件评估为表达式。但是,此例外并非在所有地方都适用。

当表达式以!开头时,我们必须始终使用${{ }}表达式语法或使用''""()进行转义,因为!是 YAML 格式中的保留符号。例如

1
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}

更多信息,请参见“在工作流和操作中评估表达式”。

4.3.2 示例:仅为特定存储库运行作业

此示例使用if来控制production-deploy作业何时运行。它仅在存储库名为octo-repo-prod且位于octo-org组织内时运行。否则,该作业将标记为已跳过。

1
2
3
4
5
6
7
8
9
10
11
12
name: example-workflow
on: [push]
jobs:
production-deploy:
if: github.repository == 'octo-org/octo-repo-prod'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
- run: npm install -g bats

4.3.3 示例:仅为特定tag创建时运行作业

1
2
3
4
5
6
7
8
9
10
11
12
name: example-workflow
on: [push]
jobs:
production-deploy:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
- run: npm install -g bats

这个作业将会在本地执行git push origin tag_name的时候执行,git push的时候不会执行。

4.4 jobs..steps

4.4.1 语法说明

一个作业包含一系列称为steps的任务。步骤可以运行命令、运行设置任务或在我们的仓库、公共仓库或在 Docker 注册表中发布的动作中运行操作。并非所有步骤都运行操作,但所有操作都作为步骤运行。每个步骤在运行器环境中的自己的进程中运行,并可以访问工作区和文件系统。由于步骤在其自己的进程中运行,因此环境变量的更改不会在步骤之间保留。GitHub 提供内置步骤来设置和完成作业。

GitHub 仅显示前 1,000 个检查,但是,只要我们在工作流使用限制内,我们可以运行无限数量的步骤。有关更多信息,请参阅针对 GitHub 托管运行器的“使用限制、计费和管理”以及针对自托管运行器的“关于自托管运行器”以了解自托管运行器的使用限制。

4.4.2 jobs..steps示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
name: Greeting from Mona

on: push

jobs:
my-job:
name: My Job
runs-on: ubuntu-latest
steps:
- name: Print a greeting
env:
MY_VAR: Hi there! My name is
FIRST_NAME: Mona
MIDDLE_NAME: The
LAST_NAME: Octocat
run: |
echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.

4.5 jobs..steps..uses

4.5.1 语法说明

选择要作为作业中步骤的一部分运行的操作。操作是可重用的代码单元。我们可以使用与工作流相同的仓库中定义的操作、公共仓库中的操作或已发布的 Docker 容器映像中的操作。

Github Actions强烈建议我们通过指定 Git ref、SHA 或 Docker 标记来包含我们正在使用的操作的版本。如果我们没有指定版本,它可能会破坏我们的工作流,或者在操作所有者发布更新时导致意外行为。

  • 使用已发布操作版本的提交 SHA 对稳定性和安全性最安全。
  • 如果操作发布主要版本标记,则我们应该期望收到关键修复和安全补丁,同时仍保留兼容性。请注意,此行为取决于操作作者的决定。
  • 使用操作的默认分支可能很方便,但是,如果有人发布具有重大更改的新主要版本,我们的工作流可能会中断。

某些操作需要我们必须使用with关键字设置的输入。查看操作的自述文件以确定所需的输入。

操作是 JavaScript 文件或 Docker 容器。如果我们正在使用的操作是 Docker 容器,则必须在 Linux 环境中运行作业。有关更多详细信息,请参阅runs-on

4.5.2 示例:使用版本化的操作

1
2
3
4
5
6
7
8
9
steps:
# Reference a specific commit
- uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
# Reference the major version of a release
- uses: actions/checkout@v4
# Reference a specific version
- uses: actions/checkout@v4.2.0
# Reference a branch
- uses: actions/checkout@main

4.5.3 示例:使用公共操作

1
{owner}/{repo}@{ref}

您可以在公共 GitHub 仓库中指定分支、ref 或 SHA。

1
2
3
4
5
6
7
8
9
jobs:
my_first_job:
steps:
- name: My first step
# Uses the default branch of a public repository
uses: actions/heroku@main
- name: My second step
# Uses a specific version tag of a public repository
uses: actions/aws@v2.0.1

4.5.4 示例:在子目录中使用公共操作

1
{owner}/{repo}/{path}@{ref}

公共 GitHub 仓库中特定分支、ref 或 SHA 的子目录。

1
2
3
4
5
jobs:
my_first_job:
steps:
- name: My first step
uses: actions/aws/ec2@main

4.5.5 示例:在与工作流相同的仓库中使用操作

1
./path/to/dir

包含工作流仓库中操作的目录的路径。您必须在使用操作之前检出您的仓库。

示例仓库文件结构

1
2
3
4
5
6
7
|-- hello-world (repository)
| |__ .github
| └── workflows
| └── my-first-workflow.yml
| └── actions
| |__ hello-world-action
| └── action.yml

该路径相对于默认工作目录(github.workspace$GITHUB_WORKSPACE)。如果操作将仓库检出到与工作流不同的位置,则必须更新用于本地操作的相对路径。

示例工作流文件

1
2
3
4
5
6
7
8
9
10
jobs:
my_first_job:
runs-on: ubuntu-latest
steps:
# This step checks out a copy of your repository.
- name: My first step - check out repository
uses: actions/checkout@v4
# This step references the directory that contains the action.
- name: Use local hello-world-action
uses: ./.github/actions/hello-world-action

4.5.6 示例:使用 Docker Hub 操作

1
docker://{image}:{tag}

Docker Hub上发布的 Docker 映像。

1
2
3
4
5
jobs:
my_first_job:
steps:
- name: My first step
uses: docker://alpine:3.8

4.5.7 示例:使用 GitHub Packages 容器注册表

1
docker://{host}/{image}:{tag}

GitHub Packages 容器注册表中的公共 Docker 映像。

1
2
3
4
5
jobs:
my_first_job:
steps:
- name: My first step
uses: docker://ghcr.io/OWNER/IMAGE_NAME

4.5.8 示例:使用 Docker 公共注册表操作

1
docker://{host}/{image}:{tag}

公共注册表中的 Docker 映像。此示例使用 gcr.io 中的 Google Container Registry。

1
2
3
4
5
jobs:
my_first_job:
steps:
- name: My first step
uses: docker://gcr.io/cloud-builders/gradle

4.5.9 示例:在与工作流不同的私有仓库中使用操作

您的工作流必须检出私有仓库并本地引用操作。生成个人访问令牌并将令牌添加为密钥。有关更多信息,请参阅“管理您的个人访问令牌”和“在 GitHub Actions 中使用密钥”。

将示例中的PERSONAL_ACCESS_TOKEN替换为您密钥的名称。

1
2
3
4
5
6
7
8
9
10
11
12
jobs:
my_first_job:
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
repository: octocat/my-private-repo
ref: v1.0
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
path: ./.github/actions/my-private-repo
- name: Run my action
uses: ./.github/actions/my-private-repo/my-action

或者,使用 GitHub App 代替个人访问令牌,以确保即使个人访问令牌所有者离开,您的工作流也能继续运行。有关更多信息,请参阅“在 GitHub Actions 工作流中使用 GitHub App 进行身份验证的 API 请求”。

三、常用公共actions

1. actions/checkout

1
2
3
jobs:
steps:
- uses: actions/checkout@v4

checkout仓库地址在这里:GitHub - actions/checkout: Action for checking out a repo。Checkout V4 是 GitHub Actions 中的一个核心动作,旨在简化工作流程中对仓库的检出操作。通过 Checkout V4,用户可以轻松地将仓库检出到 $GITHUB_WORKSPACE 中,从而使工作流程能够访问仓库内容。该动作支持多种配置选项,包括检出特定分支、标签或 SHA,以及配置 SSH 密钥和令牌等,极大地增强了工作流程的灵活性和安全性。

说简单点,就是,现在我们在sumumm/linux-release这个仓库中启动了.github/workflows/release.yml中的工作流,这个时候,通过jobs..steps..uses就可以将sumumm/linux-release这个仓库检出到现在正在运行的ubuntu系统中,检出之后,我们就可以使用 github.workspace 来表示当前仓库sumumm/linux-release的路径,然后通过以下方式访问其中的文件:

1
2
3
4
5
6
7
8
jobs:
build:
runs-on: ubuntu-20.04 # ubuntu-latest ubuntu的最新版本
steps:
- uses: actions/checkout@v4
- name: 拷贝存储库中的文件
run: |
cp -pvf ${{ github.workspace }}/linux_app_demo/helloworld_demo.c ./

2.  softprops/action-gh-release

1
2
3
4
5
6
7
8
9
10
11
12
13
14
jobs:
build:
runs-on: ubuntu-20.04 # ubuntu-latest ubuntu的最新版本
steps:
- name: 发布 readme.md 文件
id: new_release
uses: softprops/action-gh-release@v2.0.8
with:
token: ${{ secrets.LINUX_RELEASE_PERSONAL_TOKEN }}
name: release-latest
make_latest: true
files: |
readme.md
helloworld_demo.out

这个action是在自动打tag的时候将文件发布,例如:

image-20241227161703506

这个action的仓库在GitHub - softprops/action-gh-release: 📦 GitHub Action for creating GitHub Releases。里面有对应的使用说明,这里就不再详细说了。

参考资料:

【1】GitHub Actions 入门教程 - 阮一峰的网络日志

【2】GitHub Actions 工作流程语法 - GitHub 文档 - GitHub 文档

【3】YAML 语言教程 - 阮一峰的网络日志

【4】YAML Ain’t Markup Language (YAML™) revision 1.2.2

【5】GitHub Actions 指南 - GitHub 文档 - GitHub 文档