CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
GitHub Actions CI/CD/课时/Steps 与 Actions
RawBlame
课时目录12 节

GitHub Actions CI/CD

  1. 01CI/CD 与 GitHub Actions
  2. 02Workflow 文件结构
  3. 03Jobs 与运行器
  4. 04Steps 与 Actions
  5. 05Secrets 与环境
  6. 06依赖缓存
  7. 07构建 Spring Boot
  8. 08构建 Next.js platform
  9. 09构建推送镜像
  10. 10部署策略
  11. 11PR 检查与分支保护
  12. 12综合练习

Steps 与 Actions

uses vs run、Marketplace 常用 action、版本 pin。

30 分钟

Steps 与 Actions

这一课你将能做到

  1. 区分 step 的两种形态:run(shell 命令)与 uses(复用 Marketplace / 仓库内 action),并说清各自的适用场景
  2. 写出「checkout → setup 工具链 → 在子目录执行命令」的标准三段,并用 working-directory 在 backend/ 或 platform/ 下跑命令
  3. 用 $GITHUB_OUTPUT 在同 job 的 step 之间传递一个简单输出(如生成的镜像 tag)

为什么要学

Job 只是容器;真正干活的是 step。几乎所有 CI 都长同一个骨架:先把代码拉到 runner,再装 JDK/Node,再执行项目自己的脚本。

不会用 uses 时,人会手写很长的安装脚本且难维护;乱用 @main 浮动引用时,又会踩供应链风险——上游一改,你的 CI 行为跟着变,而且你毫不知情。

本课把「最小执行单元」钉清楚,并为后面 Java/Node 实战课铺路。

先建立图像

job(一台 ubuntu runner)
  step1  uses: actions/checkout@v4     ← 把仓库克隆进来
  step2  uses: actions/setup-java@v4   ← 装 Temurin 21
  step3  run: ./mvnw -B verify         ← 你自己的命令
           working-directory: backend

人话:uses 像请一位熟手工具人(checkout、setup-node);run 像你自己敲终端。先请人把工位摆好,再敲项目命令。

写法做什么典型用途
uses: owner/repo@ref运行一个 actioncheckout、cache、docker login
run: …在 shell 里执行npm ci、./mvnw verify
with:传给 action 的输入java-version: "21"
env: / working-directory管环境与目录monorepo 子项目
id: + outputs给 step 命名并暴露输出step 间传值

跟着做

步骤 1:checkout 后看目录

jobs:
  inspect:
    runs-on: ubuntu-latest
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4

      - name: 列出仓库根目录
        run: ls -la

日志里应能看到 backend、platform、.github 等。没有 checkout 就 ls,看到的是空工位——这是初学者最常见的「文件找不到」。

步骤 2:setup 工具链 + 子目录命令

以 Java 为例(Node 课会对称写 npm):

      - name: 安装 JDK 21
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "21"

      - name: 查看 Maven Wrapper
        working-directory: backend
        run: |
          chmod +x mvnw
          ./mvnw -v

应看到 Java / Maven 版本输出。working-directory 避免每条命令都写 cd backend &&。

步骤 3:对照 run 与 uses

同一意图两种写法(理解用):

      # 方式 A:用官方 action 装 Node(推荐)
      - uses: actions/setup-node@v4
        with:
          node-version: "20"

      # 方式 B:自己 run 下载安装(脆弱、难维护,仅作对比)
      # - run: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - && sudo apt-get install -y nodejs

笔记写:能官方 setup 就不要手搓安装。

步骤 4:Pin 版本,拒绝浮动 main

# 推荐:大版本 tag(生产可进一步收紧到 commit SHA)
- uses: actions/checkout@v4

# 不推荐:跟踪默认分支,行为可能突变
# - uses: actions/checkout@main

生产加固可读官方「Security hardening」:对关键 action 钉 commit SHA,并配合 Dependabot 更新。本课最低要求:不要 @main。

步骤 5:step 输出传递

      - name: 生成临时 tag
        id: meta
        run: |
          # 写入 GITHUB_OUTPUT,供后续 step 读取
          echo "tag=1.0.${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT"

      - name: 打印 tag
        run: echo "tag=${{ steps.meta.outputs.tag }}"

应看到带 run number 的 tag。要点:id 给 step 命名,输出写进 $GITHUB_OUTPUT,引用格式是 steps.<id>.outputs.<name>。跨 job 传递要用 job outputs 或 artifact(进阶);本课先掌握同 job 内传递。

想给后续所有 step 设置环境变量,用 $GITHUB_ENV:

      - run: echo "BUILD_VERSION=1.0.${GITHUB_RUN_NUMBER}" >> "$GITHUB_ENV"
      - run: echo "版本是 $BUILD_VERSION"

步骤 6:默认定目录(可选整理)

若一个 job 几乎全在 platform/:

jobs:
  platform:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: platform
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          cache: npm
          cache-dependency-path: platform/package-lock.json
      - run: npm ci

注意:defaults.run.working-directory 只影响 run,不影响 uses 的默认路径;cache-dependency-path 仍常写相对仓库根的路径。

讲清楚要点

  1. 因为 runner 初始没有你的代码,所以几乎每个构建 job 第一步都是 checkout——找不到文件时先查是否漏了这一步。
  2. 因为 uses 复用社区/官方逻辑,所以装 Node/Java/Docker login 优先用维护中的 action——少维护安装脚本,还自带跨平台兼容。
  3. 因为 action 也是代码,所以引用要 pin 版本(tag 或 SHA),避免 @main——降低供应链突发变更风险。
  4. 因为 monorepo 有多项目根,所以用 working-directory 或 defaults.run——命令与本地 cd 习惯对齐,日志也更可读。
  5. 因为 Linux runner 的 run 默认用 bash 执行,所以多行脚本注意失败即停与引号——复杂脚本可抽成 backend/scripts/ci.sh 再 run: ./scripts/ci.sh,可本地调试。
  6. 因为后续 step 常依赖前面的产物路径与输出,所以 name/id 要起得可读——排错时日志标题就是地图。

你可能会懵的地方

  1. 「uses 的代码在哪执行?信任谁?」 Action 来自 GitHub 上的仓库(或 Docker 镜像)。它以你 workflow 的权限运行,所以只引入你信任的发布方;组织可限制允许的 action 白名单。

  2. 「为什么 setup-java 之后还要 ./mvnw?」 setup 提供的是 JDK(及可选缓存);构建生命周期仍由项目的 Maven Wrapper / pom 管理,与本地一致。工具版本与构建配置是两回事。

  3. 「Windows 上 run 一样吗?」 runs-on: windows-latest 时默认 shell 是 PowerShell,命令不通用。本站主路径用 ubuntu-latest,与多数 Linux 生产环境一致。

  4. 「GITHUB_OUTPUT 和旧的 ::set-output?」 旧命令语法已废弃移除。统一用写入 $GITHUB_OUTPUT 文件的方式。

  5. 「一个 step 失败了,后面的 step 还跑吗?」 默认停止。想无论成败都跑(如清理),给该 step 加 if: always();想仅失败时跑(如通知),加 if: failure()。

错法对照

错法问题正解
不做 checkout 直接 npm ci工作区无 package.json先 actions/checkout
uses: actions/setup-node@main行为不可预期@v4 或 commit SHA
所有命令写在仓库根且路径混乱backend/pom.xml 找不到working-directory: backend
依赖「上一步手工 cd」影响下一步每个 run 都回到约定目录显式 working-directory 或 defaults
用旧 ::set-output 传值静默失效echo "k=v" >> $GITHUB_OUTPUT

卡点急救

  1. step 报 No such file or directory:先确认 checkout 是否存在且成功;再确认 working-directory 指向的目录在仓库里真实存在;monorepo 场景重点检查是「仓库根相对路径」还是「项目内相对路径」搞混了。
  2. ${{ steps.meta.outputs.tag }} 读出来是空:检查写入方 step 是否有 id: meta(名字必须一致)、是否真的写进了 $GITHUB_OUTPUT(注意 >> 追加且一行一条 key=value);写作失败常见于把输出写到了普通 stdout。
  3. action 版本浮动导致昨天绿今天红:排查是否引用了 @main 或浮动 tag;改为固定大版本 tag(@v4),生产流水线对关键 action 进一步钉 commit SHA,用 Dependabot 定期升级并走 PR 验证。

面试常问

  • run 和 uses 有什么区别?什么时候自己写 shell、什么时候用 action? run 在 runner 的 shell 里执行任意命令,适合项目自身的构建命令(npm ci、./mvnw verify);uses 执行一个封装好的 action,适合跨项目通用的环境准备(checkout、装 JDK/Node、docker login)。判断标准:逻辑通用且社区有维护良好的实现就用 action;项目特定逻辑用 run,复杂脚本抽成仓库脚本文件。

  • step 之间如何传递数据?job 之间呢? 同 job 内:step 用 $GITHUB_OUTPUT 暴露输出,后续用 ${{ steps.id.outputs.name }} 读;环境变量用 $GITHUB_ENV。跨 job:磁盘不共享,小数据用 job 级 outputs(底层仍走 GITHUB_OUTPUT),文件用 upload-artifact/download-artifact。

  • 如何降低使用第三方 action 的供应链风险? 三层做法:① 引用固定版本 tag 而非 @main;② 关键 action 钉 commit SHA,保证内容不可变;③ 用 Dependabot 自动开 PR 升级、经 CI 验证后再合。再配合仓库/组织层的 action 白名单与最小 permissions。

自测三问

  1. run 与 uses 各适合什么?举本站一步例子。
  2. 为什么不建议 uses: …@main?
  3. monorepo 里如何让 ./mvnw 在 backend/ 下执行?

小结一句话

checkout → setup 工具链 → 在子目录 run 项目命令,是 CI step 的最常见三步;输出用 GITHUB_OUTPUT 传。

延伸

  • Workflow syntax — jobs.<job_id>.steps
  • Finding and customizing actions
  • 下一课:Secrets 与环境——CI 迟早要碰真实凭据,先学会安全存放。
加载本节练习…
← 上一课Jobs 与运行器下一课 →Secrets 与环境