菜单

表达式语法

相关源文件

此页面解释了 act 如何实现 GitHub Actions 的表达式语法和评估系统。它涵盖了表达式评估器的架构、可用上下文和函数以及表达式评估过程。有关使用这些表达式的步骤执行信息,请参阅步骤执行

什么是表达式?

GitHub Actions 工作流使用表达式在工作流文件中提供动态值。这些表达式,用 ${{ }} 语法括起来,可以包含变量、函数、运算符和上下文引用。例如

Act 提供了 GitHub Actions 表达式语法的完整实现,以确保工作流在本地运行时与在 GitHub 上运行时一致。

来源:pkg/runner/expression.go22-27 pkg/exprparser/interpreter.go22-28

表达式评估架构

Act 的表达式系统由几个相互关联的组件组成,用于解析、评估和插值表达式。

关键组件

  1. ExpressionEvaluator 接口:提供评估表达式和插值带有嵌入式表达式的字符串的方法。

  2. Interpreter:解析和评估表达式语法,处理不同的表达式类型。

  3. EvaluationEnvironment:包含表达式可以访问的所有上下文数据(github、env、steps 等)。

来源:pkg/runner/expression.go22-27 pkg/exprparser/interpreter.go14-28 pkg/exprparser/interpreter.go65-67

表达式处理流程

act 处理表达式时,遵循以下通用流程:

对于包含多个嵌入部分的表达式,act 会将其重写为格式化函数调用,以保持与 GitHub 行为的兼容性。

来源:pkg/runner/expression.go235-248 pkg/runner/expression.go380-398 pkg/runner/expression.go416-480

可用上下文

表达式可以访问以下上下文:

上下文描述示例
github工作流、事件、仓库信息github.actor, github.event_name
env环境变量env.PATH, env.DEBUG
inputs工作流输入inputs.version, inputs.deploy_target
steps前一个步骤的输出和状态steps.build.outputs.version, steps.test.conclusion
job当前作业的信息job.status
matrix当前作业的矩阵值matrix.os, matrix.node-version
needs依赖作业的输出needs.build.outputs.result
secrets仓库和组织秘密secrets.API_TOKEN
vars(变量)仓库和组织变量vars.DEPLOY_ENVIRONMENT
runner运行器环境信息runner.os, runner.temp

上下文访问不区分大小写,与 GitHub 的行为一致(例如,secrets.TOKENsecrets.token 访问相同的值)。

来源:pkg/exprparser/interpreter.go14-28 pkg/exprparser/interpreter.go153-187

函数和运算符

内置函数

Act 支持表达式中的以下函数:

功能描述示例
contains(search, item)检查 search 是否包含 itemcontains('Hello world', 'world')
startsWith(search, prefix)检查 search 是否以 prefix 开头startsWith(github.ref, 'refs/tags/')
endsWith(search, suffix)检查 search 是否以 suffix 结尾endsWith(github.ref, 'main')
format(string, values...)使用值格式化字符串format('Hello {0}!', github.actor)
join(array, separator)使用分隔符连接数组元素join(github.event.issue.labels.*.name, ', ')
toJSON(value)将值转换为 JSON 字符串toJSON(github.event)
fromJSON(value)将 JSON 字符串解析为对象fromJSON('{"foo":"bar"}').foo
hashFiles(patterns...)计算文件的 SHA-256 哈希hashFiles('**/*.js', '**/*.ts')

状态检查函数

功能描述
success()当前面的步骤都没有失败时返回 true
always()始终返回 true
failure()当前面任何步骤失败时返回 true
cancelled()如果工作流被取消,则返回 true

运算符

表达式语法支持这些运算符:

  • 比较==, !=, >, <, >=, <=
  • 逻辑&& (and), || (or), ! (not)

来源:pkg/exprparser/interpreter.go611-669 pkg/runner/expression_test.go85-145

布尔评估和真值

当表达式在布尔上下文中使用时(例如 if 条件),act 的真值评估类似于 JavaScript:

值类型在以下情况下被认为是真值
布尔值true
字符串非空字符串
数字非零值
对象/数组 (Object/Array)始终为真值
Null/nil始终为假值
NaN始终为假值

此行为确保与 GitHub Actions 的表达式评估兼容。

来源:pkg/runner/expression.go401-410 pkg/exprparser/interpreter.go531-556

表达式插值

当表达式嵌入到字符串中时,act 会通过将其评估值替换表达式来执行插值。

对于一个字符串中的多个表达式,act 内部使用格式化函数调用。

来源:pkg/runner/expression.go380-398 pkg/runner/expression.go416-480

YAML 节点评估

Act 对 YAML 节点中的表达式评估有特殊处理,允许复杂的动态配置。

  1. 标量节点评估:评估字符串值中的表达式。
  2. 映射节点评估:处理带有表达式的键值对。
  3. 序列节点评估:处理带有表达式的数组。
  4. 插入指令:支持 ${{ insert }} 指令用于合并对象。

这使得工作流作者能够创建高度动态的配置,这些配置可以根据上下文进行调整。

来源:pkg/runner/expression.go246-378

特殊函数:hashFiles

hashFiles 函数计算匹配 glob 模式的文件的 SHA-256 哈希值。在 act 中,这是通过一个专用的 JavaScript 模块实现的,该模块:

  1. 接收文件 glob 模式
  2. 使用 glob 算法查找匹配文件
  3. 计算每个文件的 SHA-256 哈希值
  4. 合并并返回单个哈希值

此函数对于缓存键和基于文件更改的条件执行非常有用。

来源:pkg/runner/expression.go170-229 pkg/runner/hashfiles/index.js

实现细节

act 中的表达式评估系统基于几个关键的实现选择:

  1. 解析器:使用 actionlint 解析表达式语法。
  2. 不区分大小写:上下文访问键不区分大小写。
  3. 错误处理:为无效表达式提供详细的错误消息。
  4. 上下文隔离:不同的表达式上下文(作业与步骤)具有独立的评估器。
  5. 默认状态检查:自动向作业条件添加状态函数(success())。

这些实现细节确保 act 在本地运行工作流时能够正确复制 GitHub Actions 的行为。

来源:pkg/exprparser/interpreter.go81-92 pkg/runner/expression.go109-168