症状
错误“GitHub Actions 密钥未找到 — 环境变量为空”指向一个明确的失效模式。下面依次给出症状、定位该原因的检查命令、根本原因、修复方案,以及证明修复有效的验证步骤。
可观察到的症状包括:
- 某步骤因 ${{ secrets.TOKEN }} 展开为空字符串而失败
- 工作流在 push 时可用,来自 fork 的 PR 不可用
- 密钥已配置却认证 401
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
gh secret list --repo <owner>/<repo> && gh secret list --env production
按作用域列出密钥,可看出名称是否存在于任务所用的层级。
步骤 2
if [ -z "${{ secrets.TOKEN }}" ]; then echo 'TOKEN is empty'; fi
这样可在不把值泄露到日志的前提下检测空展开。
常见诱因(按出现频率排序):
- 工作流中的密钥名与配置名不同(区分大小写)
- 密钥限定在任务未声明的 environment
- fork PR 与 Dependabot 默认不接收仓库密钥
根因
GitHub 在运行时按作用域解析密钥。名称不匹配、使用了 environment 作用域密钥而任务未声明该 environment,或 fork/Dependabot 上下文,都会得到空值而非报错,导致下游认证失败。
修复
精确匹配密钥名,在使用 environment 密钥的任务上声明 environment: production,向可复用工作流显式传密钥,并对 fork PR 谨慎使用 pull_request_target 或采用独立令牌流程。
注意:pull_request_target 配合密钥会把密钥暴露给不可信代码;切勿在同一任务中以密钥运行 fork 代码。
jobs:
deploy:
environment: production # required to see environment secrets
steps:
- name: Guard against empty secret
run: |
if [ -z "${{ secrets.API_TOKEN }}" ]; then
echo '::error::API_TOKEN is empty'
exit 1
fi
# never echo the secret value itself
验证
重跑任务并确认使用点处密钥非空;检查认证成功且日志中无密钥值。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。