关于表达式
您可以使用表达式以编程方式在工作流文件中设置环境变量并访问上下文。表达式可以是字面值、上下文引用或函数的任意组合。您可以使用运算符组合字面量、上下文引用和函数。有关上下文的更多信息,请参阅“访问有关工作流运行的上下文信息”。
表达式通常与工作流文件中的条件if
关键字一起使用,以确定是否应运行步骤。当if
条件为true
时,将运行该步骤。
您需要使用特定语法来告诉 GitHub 评估表达式,而不是将其视为字符串。
${{ <expression> }}
注意
此规则的例外情况是当您在if
子句中使用表达式时,您可以选择省略${{
和}}
。有关if
条件的更多信息,请参阅“GitHub Actions 的工作流语法”。
警告
创建工作流和操作时,应始终考虑您的代码是否可能会执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可能会插入他们自己的恶意内容。有关更多信息,请参阅“GitHub Actions 的安全加固”。
设置环境变量的示例
env:
MY_ENV_VAR: ${{ <expression> }}
字面量
作为表达式的一部分,您可以使用boolean
、null
、number
或string
数据类型。
数据类型 | 字面值 |
---|---|
boolean | true 或 false |
null | null |
number | JSON 支持的任何数字格式。 |
string | 您不需要将字符串括在${{ 和}} 中。但是,如果您这样做,则必须使用单引号 (' ) 括起字符串。要使用字面单引号,请使用另一个单引号 ('' ) 转义字面单引号。用双引号 (" ) 括起来会引发错误。 |
请注意,在条件语句中,虚假值 (false
、0
、-0
、""
、''
、null
) 会强制转换为false
,而真值 (true
和其他非虚假值) 会强制转换为true
。
字面量的示例
env:
myNull: ${{ null }}
myBoolean: ${{ false }}
myIntegerNumber: ${{ 711 }}
myFloatNumber: ${{ -9.2 }}
myHexNumber: ${{ 0xff }}
myExponentialNumber: ${{ -2.99e-2 }}
myString: Mona the Octocat
myStringInBraces: ${{ 'It''s open source!' }}
运算符
运算符 | 描述 |
---|---|
( ) | 逻辑分组 |
[ ] | 索引 |
. | 属性取消引用 |
! | 非 |
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于或等于 |
== | 等于 |
!= | 不等于 |
&& | 与 |
|| | 或 |
注意
- 比较字符串时,GitHub 会忽略大小写。
steps.<step_id>.outputs.<output_name>
会被评估为字符串。您需要使用特定的语法来告诉 GitHub 评估表达式而不是将其视为字符串。更多信息,请参见“访问有关工作流运行的上下文信息”。- 对于数值比较,可以使用
fromJSON()
函数将字符串转换为数字。有关fromJSON()
函数的更多信息,请参见“fromJSON”。
GitHub 执行宽松的相等性比较。
-
如果类型不匹配,GitHub 会将类型强制转换为数字。GitHub 使用以下转换将数据类型转换为数字:
类型 结果 Null 0
布尔值 true
返回1
false
返回0
字符串 从任何合法的 JSON 数字格式解析,否则返回 NaN
。
注意:空字符串返回0
。数组 NaN
对象 NaN
-
当
NaN
是任何关系比较运算符 (>
,<
,>=
,<=
) 的操作数之一时,结果始终为false
。更多信息,请参见“NaN Mozilla 文档”。 -
比较字符串时,GitHub 会忽略大小写。
-
只有当对象和数组是同一个实例时,它们才被认为是相等的。
GitHub 提供类似三元运算符的行为,您可以在表达式中使用它。通过这种方式使用三元运算符,您可以根据条件动态设置环境变量的值,而无需为每个可能的选项编写单独的 if-else 块。
示例
env:
MY_ENV_VAR: ${{ github.ref == 'refs/heads/main' && 'value_for_main_branch' || 'value_for_other_branches' }}
在此示例中,我们使用三元运算符根据 GitHub 引用是否设置为 refs/heads/main
来设置 MY_ENV_VAR
环境变量的值。如果设置为 refs/heads/main
,则变量设置为 value_for_main_branch
。否则,它将设置为 value_for_other_branches
。需要注意的是,&&
后的第一个值必须为真值。否则,||
后的值将始终被返回。
函数
GitHub 提供了一组内置函数,您可以在表达式中使用它们。某些函数会将值转换为字符串以执行比较。GitHub 使用以下转换将数据类型转换为字符串:
类型 | 结果 |
---|---|
Null | '' |
布尔值 | 'true' 或 'false' |
数字 | 十进制格式,大数字用指数表示 |
数组 | 数组不会转换为字符串 |
对象 | 对象不会转换为字符串 |
contains
contains( search, item )
如果 search
包含 item
,则返回 true
。如果 search
是一个数组,则如果 item
是数组中的一个元素,此函数返回 true
。如果 search
是一个字符串,则如果 item
是 search
的子字符串,此函数返回 true
。此函数不区分大小写。将值转换为字符串。
使用字符串的示例
contains('Hello world', 'llo')
返回 true
。
使用对象过滤器的示例
如果与事件相关的 issue 具有标签“bug”,则 contains(github.event.issue.labels.*.name, 'bug')
返回 true
。
更多信息,请参见“对象过滤器”。
匹配字符串数组的示例
无需编写 github.event_name == "push" || github.event_name == "pull_request"
,您可以使用带有 fromJSON()
的 contains()
来检查字符串数组是否包含 item
。
例如,如果 github.event_name
是“push”或“pull_request”,则 contains(fromJSON('["push", "pull_request"]'), github.event_name)
返回 true
。
startsWith
startsWith( searchString, searchValue )
当 searchString
以 searchValue
开头时返回 true
。此函数不区分大小写。将值转换为字符串。
startsWith
的示例
startsWith('Hello world', 'He')
返回 true
。
endsWith
endsWith( searchString, searchValue )
如果 searchString
以 searchValue
结尾,则返回 true
。此函数不区分大小写。将值转换为字符串。
endsWith
的示例
endsWith('Hello world', 'ld')
返回 true
。
format
format( string, replaceValue0, replaceValue1, ..., replaceValueN)
使用变量 replaceValueN
替换 string
中的值。string
中的变量使用 {N}
语法指定,其中 N
是一个整数。您必须至少指定一个 replaceValue
和 string
。您可以使用的变量 (replaceValueN
) 数量没有上限。使用双花括号转义花括号。
format
的示例
format('Hello {0} {1} {2}', 'Mona', 'the', 'Octocat')
返回 'Hello Mona the Octocat'。
转义花括号的示例
format('{{Hello {0} {1} {2}!}}', 'Mona', 'the', 'Octocat')
返回 '{Hello Mona the Octocat!}’。
join
join( array, optionalSeparator )
array
的值可以是数组或字符串。array
中的所有值都连接到一个字符串中。如果您提供 optionalSeparator
,它将插入到连接的值之间。否则,将使用默认分隔符 ,
。将值转换为字符串。
join
的示例
join(github.event.issue.labels.*.name, ', ')
可能返回 'bug, help wanted'
toJSON
toJSON(value)
返回 value
的漂亮打印 JSON 表示形式。您可以使用此函数调试上下文中提供的信息。
toJSON
的示例
toJSON(job)
可能返回 { "status": "success" }
fromJSON
fromJSON(value)
返回 value
的 JSON 对象或 JSON 数据类型。您可以使用此函数提供 JSON 对象作为已评估的表达式,或转换任何可以用 JSON 或 JavaScript 表示的数据类型,例如字符串、布尔值、null 值、数组和对象。
返回 JSON 对象的示例
此工作流在一个作业中设置 JSON 矩阵,并使用输出和 fromJSON
将其传递给下一个作业。
name: build on: push jobs: job1: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - id: set-matrix run: echo "matrix={\"include\":[{\"project\":\"foo\",\"config\":\"Debug\"},{\"project\":\"bar\",\"config\":\"Release\"}]}" >> $GITHUB_OUTPUT job2: needs: job1 runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.job1.outputs.matrix) }} steps: - run: echo "Matrix - Project ${{ matrix.project }}, Config ${{ matrix.config }}"
name: build
on: push
jobs:
job1:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- id: set-matrix
run: echo "matrix={\"include\":[{\"project\":\"foo\",\"config\":\"Debug\"},{\"project\":\"bar\",\"config\":\"Release\"}]}" >> $GITHUB_OUTPUT
job2:
needs: job1
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJSON(needs.job1.outputs.matrix) }}
steps:
- run: echo "Matrix - Project ${{ matrix.project }}, Config ${{ matrix.config }}"
返回 JSON 数据类型的示例
此工作流使用 fromJSON
将环境变量从字符串转换为布尔值或整数。
name: print on: push env: continue: true time: 3 jobs: job1: runs-on: ubuntu-latest steps: - continue-on-error: ${{ fromJSON(env.continue) }} timeout-minutes: ${{ fromJSON(env.time) }} run: echo ...
name: print
on: push
env:
continue: true
time: 3
jobs:
job1:
runs-on: ubuntu-latest
steps:
- continue-on-error: ${{ fromJSON(env.continue) }}
timeout-minutes: ${{ fromJSON(env.time) }}
run: echo ...
此工作流使用 fromJSON()
函数将环境变量 continue
从字符串转换为布尔值,从而确定是否继续执行错误或不继续执行错误。类似地,它将环境变量 time
从字符串转换为整数,以分钟为单位设置作业的超时时间。
hashFiles
hashFiles(path)
返回与 path
模式匹配的文件集的单个哈希值。您可以提供单个 path
模式或多个用逗号分隔的 path
模式。path
相对于 GITHUB_WORKSPACE
目录,并且只能包含 GITHUB_WORKSPACE
内的文件。此函数为每个匹配的文件计算单个 SHA-256 哈希值,然后使用这些哈希值来计算文件集的最终 SHA-256 哈希值。如果 path
模式与任何文件都不匹配,则返回空字符串。有关 SHA-256 的更多信息,请参见“SHA-2”。
您可以使用模式匹配字符来匹配文件名。hashFiles
的模式匹配遵循 glob 模式匹配,在 Windows 上不区分大小写。有关支持的模式匹配字符的更多信息,请参见 @actions/glob
文档中的模式部分。
使用单个模式的示例
匹配存储库中的任何 package-lock.json
文件。
hashFiles('**/package-lock.json')
使用多个模式的示例
为存储库中的任何 package-lock.json
和 Gemfile.lock
文件创建哈希值。
hashFiles('**/package-lock.json', '**/Gemfile.lock')
状态检查函数
您可以将以下状态检查函数用作 if
条件中的表达式。除非您包含这些函数之一,否则将应用 success()
的默认状态检查。有关 if
条件的更多信息,请参见“GitHub Actions 的工作流语法”和“GitHub Actions 的元数据语法”。
success
当所有先前步骤都成功时返回 true
。
success
的示例
steps:
...
- name: The job has succeeded
if: ${{ success() }}
always
导致步骤始终执行并返回 true
,即使被取消也是如此。always
表达式最好用于步骤级别或您期望即使作业被取消也要运行的任务。例如,即使作业被取消,您也可以使用 always
发送日志。
警告
避免将 always
用于任何可能遭受严重故障的任务,例如:获取源代码,否则工作流可能会挂起直到超时。如果您想运行作业或步骤而不管其成功或失败,请使用推荐的替代方法:if: ${{ !cancelled() }}
always
的示例
if: ${{ always() }}
cancelled
如果工作流被取消,则返回 true
。
cancelled
的示例
if: ${{ cancelled() }}
failure
当作业的任何先前步骤失败时返回 true
。如果您有一系列依赖作业,则如果任何祖先作业失败,failure()
将返回 true
。
failure
的示例
steps:
...
- name: The job has failed
if: ${{ failure() }}
带条件的 failure
您可以为步骤在失败后运行包含额外的条件,但是您仍然必须包含 failure()
来覆盖自动应用于不包含状态检查函数的 if
条件的默认状态检查 success()
。
带条件的 failure
的示例
steps:
...
- name: Failing step
id: demo
run: exit 1
- name: The demo step has failed
if: ${{ failure() && steps.demo.conclusion == 'failure' }}
对象过滤器
您可以使用*
语法应用过滤器并选择集合中匹配的项。
例如,考虑一个名为fruits
的对象数组。
[
{ "name": "apple", "quantity": 1 },
{ "name": "orange", "quantity": 2 },
{ "name": "pear", "quantity": 1 }
]
过滤器fruits.*.name
将返回数组[ "apple", "orange", "pear" ]
。
您也可以在对象上使用*
语法。例如,假设您有一个名为vegetables
的对象。
{
"scallions":
{
"colors": ["green", "white", "red"],
"ediblePortions": ["roots", "stalks"],
},
"beets":
{
"colors": ["purple", "red", "gold", "white", "pink"],
"ediblePortions": ["roots", "stems", "leaves"],
},
"artichokes":
{
"colors": ["green", "purple", "red", "black"],
"ediblePortions": ["hearts", "stems", "leaves"],
},
}
过滤器vegetables.*.ediblePortions
可能评估为
[
["roots", "stalks"],
["hearts", "stems", "leaves"],
["roots", "stems", "leaves"],
]
由于对象不保留顺序,因此无法保证输出的顺序。