
用 GitHub Actions 的 workflow_dispatch 配合 environment 字段,蓝绿部署、灰度发布都能搭。但跑起来有两个容易踩的坑:inputs 的默认值在特定触发方式下不生效,以及 environment secrets 在保护规则审批前读不到空值。本文说清楚,给出能直接抄的解法。
inputs 默认值:被其他 workflow 触发时变成 null
看这个配置:
on:
workflow_dispatch:
inputs:
deploy_target:
type: choice
default: staging
options:
- staging
- production
直觉上"不填就走 staging"。在 GitHub Web UI 上确实如此。但换一种触发方式就不一样了:
| 触发方式 | 不传 input 时,默认值生效? |
|---|---|
| Web UI 手动触发 | ✅ 生效 |
| REST API 触发,不传 inputs 字段 | ✅ 生效 |
| 另一个 workflow 触发,不传这个 input | ❌ 值为 null,不是 default |
第三种情况最容易被忽略。触发方如果没有显式传某个 input,接收方 workflow 的 github.event.inputs.<name> 为 null,而不是 YAML 里写的 default。
场景:workflow A 触发 workflow B:
curl -X POST "https://api.github.com/repos/owner/repo/actions/workflows/deploy.yml/dispatches" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-d '{"ref":"main"}'
workflow B 跑起来后,github.event.inputs.deploy_target 是 null。踩到这个坑的代码:
- name: Deploy
run: |
TARGET="${{ github.event.inputs.deploy_target }}"
if [ "$TARGET" = "production" ]; then
echo "Going to production!"
fi
$TARGET 是空字符串,条件判断为 false,部署目标静默变成了空——不是 staging,不是 production,而是完全没部署到预期环境。
正确做法:永远给默认值留后路。
- name: Deploy
run: |
TARGET="${{ github.event.inputs.deploy_target || 'staging' }}"
echo "Deploying to $TARGET"
触发方也要显式传 input,不依赖接收方的默认值:
jobs:
trigger-deploy:
runs-on: ubuntu-latest
steps:
- name: Trigger deploy
run: |
curl -X POST "https://api.github.com/repos/owner/repo/actions/workflows/deploy.yml/dispatches" \
-H "Authorization: Bearer ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
-d '{
"ref": "main",
"inputs": {"deploy_target": "staging"}
}'
environment secrets:保护规则审批前读不到值
jobs:
deploy:
environment:
name: production
steps:
- run: echo "${{ secrets.PROD_DEPLOY_KEY }}"
绑定了 production environment,environment 里配了 PROD_DEPLOY_KEY。实际跑的时候,这个 secret 有时是空字符串。
流程是这样的:job 开始初始化时,GitHub Actions 注入 environment secrets。此时如果 required reviewers 保护规则还没审批,secrets 拿到的是空值。只有审批者点通过后,job 才真正开始执行,secrets 才正确注入。
如果保护规则要求 2 人审批,只通过了 1 人,job 一直等到第 2 人点下去,之前 secrets 都是空的。
实测场景:设置了 2 人审批的 production environment:
jobs:
deploy:
environment:
name: production
steps:
- name: Read secret
run: |
KEY="${{ secrets.PROD_DEPLOY_KEY }}"
if [ ${#KEY} -eq 0 ]; then
echo "ERROR: PROD_DEPLOY_KEY is empty"
exit 1
fi
./deploy.sh
Web UI 手动触发后,workflow 状态是 Waiting(等审批)。用 API 触发返回 202 Accepted,但 workflow run 同样在等审批。必须等 2 人全部审批后,job 才真正启动,secrets 才正常。
解法:把触发审批和实际部署拆成两个 job。审批 job 专门触发保护规则审批,deploy job 依赖它完成后再读取 secrets。
jobs:
request-approval:
runs-on: ubuntu-latest
environment: production
steps:
- run: echo "Approval requested for production deployment"
deploy:
needs: request-approval
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
KEY: ${{ secrets.PROD_DEPLOY_KEY }}
run: |
echo "Key length: ${#KEY}"
./deploy.sh
request-approval job 触发保护规则审批流程(Web UI 显示 Waiting)。审批通过后,deploy job 才启动,environment secrets 正确注入。
用 curl 快速验证 workflow 状态
诊断 workflow 状态:
# 查看 recent runs
curl -s "https://api.github.com/repos/{owner}/{repo}/actions/workflows/deploy.yml/runs" \
-H "Authorization: Bearer $GITHUB_TOKEN" | \
jq '.workflow_runs[] | {id, status, event, environment}'
# 查看某个 run 的 jobs
curl -s "https://api.github.com/repos/{owner}/{repo}/actions/runs/{run_id}/jobs" \
-H "Authorization: Bearer $GITHUB_TOKEN" | \
jq '.jobs[] | {name, status, conclusion}'
# 手动触发
curl -X POST "https://api.github.com/repos/{owner}/{repo}/actions/workflows/deploy.yml/dispatches" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-d '{"ref":"main","inputs":{"env":"production"}}'
正常情况下,手动触发后 job 状态在几秒内从 queued 变成 in_progress。如果长时间卡在 in_progress 或跳到 waiting,说明 environment 保护规则在起作用。
完整配置模板
name: Deploy with Environment Selection
on:
workflow_dispatch:
inputs:
env:
description: 'Target environment'
required: true
type: choice
options:
- staging
- production
- production-manual
jobs:
request-approval:
if: github.event.inputs.env == 'production'
runs-on: ubuntu-latest
environment: production
steps:
- run: echo "Production approval requested"
deploy:
needs: request-approval
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.env }}
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
DEPLOY_ENV: ${{ github.event.inputs.env }}
run: |
KEY="${{ secrets.DEPLOY_KEY }}"
if [ ${#KEY} -eq 0 ]; then
echo "ERROR: DEPLOY_KEY is empty"
exit 1
fi
echo "Deploying to $DEPLOY_ENV"
./deploy.sh "$DEPLOY_ENV"
关键点:
needs: request-approval:staging 和 production-manual 没有 request-approval job,GitHub Actions 视为立即满足,不会卡住if: github.event.inputs.env == 'production':只有选 production 时才触发审批- secrets 读取前有长度检查,避免空值静默失败
现在你可以做什么
- 搜索你的 workflow 文件,找出所有
workflow_dispatch配合environment的配置。在 Web UI 上手动触发一次,观察 workflow 状态是Running还是Waiting。卡在Waiting说明触发了保护规则审批。 - 检查所有读取 environment secrets 的 job,如果它们直接跑而没有前置审批 job,在它们前面加一个
needs依赖的 approval job,确保审批完成后才读取 secrets。 - 搜索所有
workflow_dispatch触发其他 workflow 的地方,确认触发方是否显式传了所有 input。缺少的 input 不会使用default,值为null。给每个 input 引用加|| '默认值'后缀。 - 用上面的 curl 命令验证 workflow 行为。触发一次后轮询 jobs 状态,确认 staging 不需要审批(直接进
in_progress),production 需要等审批。
更多交流点击入群






