首页
/ act 怎么通过 --env-file 加载本地环境:.env 与 YAML 文件的识别规则和参数优先级

act 怎么通过 --env-file 加载本地环境:.env 与 YAML 文件的识别规则和参数优先级

2026-09-08 16:48:58作者:齐冠琰

用 act 在本地运行 GitHub Actions 工作流时,常需要把本地环境里的变量(数据库地址、API 密钥所在的中间变量等)注入到 job 容器中。act 提供了 --env-file 参数完成这件事:它把指定文件读成键值对,作为容器内的环境变量使用。这个参数的默认值是 .env,文件既可以是 dotenv 格式(如 .env),也可以是 YAML(扩展名为 .yml/.yaml)。本文说明它的文件识别规则、路径解析方式,以及当同一变量在 --env 参数、.actrc 和 env-file 中同时出现时谁生效,并给出验证加载结果的方法。

--env-file 的定义与路径解析

cmd/root.go 中,该参数被注册为全局持久参数:

rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env",
    "environment file to read and use as env in the containers")

即默认读取工作目录下的 .env,读取结果"作为容器内的环境变量使用"。不显式传参时就是走 .env 这个默认路径。

路径解析逻辑在 cmd/input.goInput.resolve 中:相对路径会拼接到 --directory(短选项 -C)指定的工作目录(默认 .)之后,绝对路径则原样使用。也就是说:

# 在仓库根目录下运行 push 事件的工作流,env 文件取默认的 ./.env
act push

# 显式指定 env 文件;相对路径相对于当前目录(-C 未指定时)
act push --env-file env/local.yml

# 用 -C 把工作目录切到别的目录,--env-file 的相对路径也相对该目录解析
act -C /home/user/myrepo push --env-file .env

运行入口在 cmd/root.gonewRunCommand 中,加载顺序是:

log.Debugf("Loading environment from %s", input.Envfile())
envs := parseEnvs(input.envs)          // 先放入命令行 --env 的键值对
_ = readEnvs(input.Envfile(), envs)    // 再读 env-file 文件

.env 与 YAML 文件的识别规则

格式识别只看文件扩展名。readEnvsExcmd/root.go)先检查文件是否存在,然后:

  • 扩展名为 .yml.yaml:按 YAML 解析成 map[string]string,即 键: 值 的映射;
  • 其他扩展名(包括无扩展名、.env 等):交给 godotenv.Read 解析,即 KEY=value 每行一个键值对。

dotenv 风格文件的最小例子(与仓库测试数据 pkg/container/testdata/valid.env 相同):

ENV1=value1

YAML 文件支持多行值。仓库的 cmd/testdata/secrets.yml 就是这样一份测试数据,cmd/root_test.go 中的 TestReadEnv 验证了它被读成 mysecret 键、值为三行 line1/line2/line3(块量级 | 保留换行):

mysecret: |
  line1
  line2
  line3

两个边界行为要注意:

  1. 文件不存在时不报错readEnvsExos.Stat 失败静默返回 false,act 继续运行,只是没有从该文件注入任何变量。拼错 --env-file 路径时不会出现任何提示,这是排查"变量没生效"时首先要确认的点。
  2. 文件存在但解析失败时会直接终止。代码路径是 log.Fatalf("Error loading from %s: %v", path, err),即 YAML 写错缩进或格式非法时 act 会报错退出,错误信息包含出问题的文件路径。

另外,env-file 的键名按原样使用,不会做大小写转换:readEnvs 调用的是 readEnvsEx(path, envs, false)cmd/root.go),caseInsensitivefalse。测试数据中的小写键 mysecret 就以小写键名被写入环境(见 cmd/root_test.go)。而 --secret-file 走的是大小写不敏感分支,两者不要混为一谈。

参数优先级:同一变量多处定义时谁生效

优先级规则同样来自 cmd/root.go 的代码。

--env 参数优先于 env-file。 newRunCommand 先用 parseEnvs(input.envs) 把命令行 --env KEY=value 的键值对放进 envs,随后 readEnvsEx 写入文件内容时有显式判断:

if _, ok := envs[k]; !ok {
    envs[k] = v
}

也就是说,env-file 只会补齐 --env 里不存在的键;同名键以 --env 的值为准。parseEnvs 按第一个 = 拆分,--env FOO=prefix/foo/suffix 这种带 = 的值是安全的(只拆一次)。仓库测试数据 cmd/testdata/env.actrc 中就有一条 --env FOO=prefix/${FOO}/suffix,测试 cmd/root_test.go 确认它最终生成了 --env FOO=prefix/foo/suffix

--env-file 参数本身的取值,命令行优先于 .actrc act 支持 .actrc 配置文件,查找顺序(见 cmd/root.goconfigLocations 注释与实现):

  1. XDG 规范路径(xdg.ConfigFile("act/actrc"));
  2. 主目录下的 ~/.actrc
  3. 当前调用目录下的 ./.actrc

args() 把三个文件中读到的参数按上述顺序依次追加,最后再追加 os.Args[1:](命令行实参):

for _, f := range actrc {
    args = append(args, readArgsFile(f, true)...)
}
args = append(args, os.Args[1:]...)

同一参数名出现多次时,后面的值覆盖前面的,因此最终优先级为:命令行 > ./.actrc > ~/.actrc > XDG 配置路径.actrc 每行写一个选项(可带参数),并且支持 ${VAR} 形式的环境变量展开,例如 cmd/testdata/env.actrc 的内容:

--artifact-server-path $FAKEPWD/.artifacts
--env FOO=prefix/${FOO}/suffix

测试 cmd/root_test.goTestReadArgsFile 表明:当宿主环境中设置了 FAKEPWDFOO 时,上面两行会被展开为 --artifact-server-path /fake/test/pwd/.artifacts--env FOO=prefix/foo/suffix。所以你也可以把 --env-file env/local.yml 写进 .actrc,省去每次敲参数。

验证加载是否生效

看调试日志。-v(verbose,把日志级别调到 Debug)后,newRunCommand 会打印加载的文件路径:

act -v push --env-file env/local.yml

输出中的 Loading environment from <路径> 一行会给出解析后的完整路径,可以先确认文件是否指向你以为的那个文件。

--dryrun 校验组合是否正确。 --dryrun(短选项 -n)的说明是 "disable container creation, validates only workflow correctness",即不创建容器、只校验工作流正确性。在不打算真正跑容器时,可以用它配合 --env-file 快速确认参数组合没有报错(注意 --dryrun 下不会真正在容器里验证变量值)。

用测试用例作为参照。 pkg/container/docker_cli_test.goTestParseEnvfileVariables 展示了预期行为(文档示例,非运行时固定输出):

  • --env-file=testdata/valid.env 解析出的容器环境为 ENV1=value1
  • 同时给出 --env=ENV2=value2 时,容器环境包含 ENV1=value1ENV2=value2 两项;
  • 文件不存在时返回 open nonexistent: no such file or directory(该用例针对 docker 参数层,与前述"act 层文件缺失静默跳过"是两个不同层次,排查时注意区分报错来自哪一层)。

工作流内部的步骤读取的是注入到容器中的环境变量(参数说明原文为 "use as env in the containers"),变量是否可用以步骤内的实际行为为准。

限制与注意点

  • 文件不存在是静默行为:--env-file 指到不存在的路径时 act 不会报错,只是没有注入任何变量。变量"没生效"时,先用 -vLoading environment from 的路径是否是你预期的文件。
  • 文件存在但内容非法(如 YAML 缩进错误)会直接终止 act,错误信息为 Error loading from <路径>: <原因>
  • 识别规则完全由扩展名决定:内容写成 dotenv 但扩展名是 .yaml 会被按 YAML 解析而失败;反之 .env 扩展名的 YAML 内容也走 dotenv 解析。想使用 YAML 的多行值等能力,文件必须命名为 .yml.yaml
  • env-file 的键区分大小写且不自动大写;需要大小写不敏感读取的是 --secret-file 路径,不要靠改 env-file 的键名大小写去对齐 secret。
  • --env-file 注入的是容器环境变量,不会改变宿主 shell 的环境;.actrc 里的 ${VAR} 展开读取的是运行 act 的宿主环境。

排查与扩展的入口文件:cmd/root.go(参数定义与加载顺序)、cmd/input.go(路径解析)、cmd/root_test.go(actrc 与 YAML 读取的测试用例)。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391