github action

最后发布时间:2026-09-26 22:52:27 浏览量:

Read

Read

GitHub Actions 里“节点连节点”的四种层级

GitHub Actions 本身没有显式的连线语法,所谓“节点”是三个层级,连接方式各不相同:

graph LR A["workflow_run<br/>事件触发"] --> B[workflow] B --> C["job A"] B --> D["job B"] C -->|needs| D C --> E["step1 → step2 → step3<br/>(同一 runner 顺序执行)"]

1. step → step:隐式顺序 + 输出变量

同一个 job 里的 steps 天然串行(同一 runner、同一文件系统),连线靠顺序,传值靠三个内置文件:

机制作用域下游引用方式
$GITHUB_OUTPUT本 job,步骤级${{ steps.<id>.outputs.x }}
$GITHUB_ENV本 job,后续所有步骤${{ env.X }}
$GITHUB_PATH本 job,后续步骤的 PATH直接命令

你仓库的 release-cli-archive.yml 就是这个模式:

- name: Configure pnpm store path
  id: pnpm-store                    # 给节点命名
  run: echo "path=$store_path" >> "$GITHUB_OUTPUT"

- uses: actions/cache/restore@v4    # 下游节点引用上游输出
  with:
    path: ${{ steps.pnpm-store.outputs.path }}

PNPM_CONFIG_STORE_DIR 走 $GITHUB_ENV,则是对之后所有步骤生效的连线。

2. job → job:needs 构成 DAG

jobs:
  build: { ... }
  test:
    needs: build        # 边:build 成功后才跑 test

规则要点:

  • 多个 needs = 扇入(等全部完成);多个下游 = 扇出(并行)。
  • 上游失败/取消 → 下游默认跳过;用 if: always() 强制连边,或 if: needs.build.result == 'success' 做条件边。
  • 数据传递只有 needs.<job>.outputs.<name>(job 级 output),文件系统不共享,产物要经 artifact / cache / release asset 传递。
  • 没有 needs 的 job 并行执行,连线完全由图决定,不按书写顺序。

3. workflow → workflow:两种语义完全不同的连法

(a)workflow_run——事件级、异步、弱连接。 这正是你的 release-docker-image.yml:

on:
  workflow_run:
    workflows: ['Release CLI archive (dsh)']   # 上游 workflow 的 name
    types: [completed]
  • 上游 release-cli-archive.yml 是 on: push: tags: ['dsh-v*'],它跑完才唤醒这里的 image job。
  • 上游结论要用 if 自己判断,因为 completed 包含失败:
    if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
    
  • 上下文通过 github.event.workflow_run.* 传入:head_branch(即释放 tag)、head_repository.full_name、conclusion。
  • 真正的数据连线是 release asset:archive job 用 gh release upload 把 dsh-v<version>.zip 挂到 Release,docker job 的 docker build --build-arg DSH_VERSION=... 再去下载它。也就是说,payload 走的是 GitHub Release 而不是 workflow 输出。
  • 注意 workflow_run 只在默认分支上的 workflow 定义存在时才触发,且只连同一仓库。

(b)workflow_call——可复用工作流、同步、强连接。 如果想让上游 uses: ./.github/workflows/x.yml 直接调用,就能传 inputs / secrets / outputs,是真正的“函数调用”式连线。你的两个文件没用这种,而是用了 workflow_run + release asset,因为发布产物本身需要作为 tag 的公开资产存在。

4. 横切约束:concurrency

它不是连线,但决定同一 tag 上的节点是否互相打断:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false

两个文件都设了 cancel-in-progress: false,含义是:同一 group 内新 run 排队而非取消旧 run,保证已开始的发布不被腰斩——这相当于给连线加了互斥锁。

小结

想连的对象手段数据载体
step → step书写顺序$GITHUB_OUTPUT / $GITHUB_ENV
job → jobneeds + ifneeds.<job>.outputs
workflow → workflow(同 run 内复用)workflow_callinputs / outputs / secrets
workflow → workflow(跨 run 事件)workflow_runRelease asset / artifact / github.event.workflow_run.*
抑制并行concurrency.group—