惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
T
The Blog of Author Tim Ferriss
B
Blog
L
LangChain Blog
Y
Y Combinator Blog
美团技术团队
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
G
Google Developers Blog
量子位
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Check Point Blog
D
Docker
小众软件
小众软件
The Cloudflare Blog
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
IT之家
IT之家

Ray's Blog

从 GitHub Discussions 自动生成静态评论区 — Ray's Blog 给 2025 年的告别 — Ray's Blog Ray's Blog 可重用的工作流 — Ray's Blog 把博客用 Nuxt Content 重写及踩坑记录 — Ray's Blog Ray's Blog 你这个级别的 Devtools 无权哈我 — Ray's Blog 辞旧迎新:Ray 的 2024 年终总结 — Ray's Blog Ray's Blog 使用 ip6tables 在群晖 DiskStation 上开启 Docker Bridge 网络 IPV6 支持(不支持 SA6400) — Ray's Blog Ray's Blog 迟来了一个月的 2023 年度总结 + 2024 新年快乐! — Ray's Blog Vue Language Tools 深度解析 (1):Vue 编辑器插件发展历程及基本工作原理 — Ray's Blog Ray's Blog Ray's Blog TypeScript 小寄巧!如何在不使用 const 泛型修饰符的情况下推导出列表字面量? — Ray's Blog Ray's Blog 快使用 Dprint 换掉你的 Prettier 罢(迫切 — Ray's Blog Ray's Blog chi 的小红包冒险 v.e.r. 2023 — Ray's Blog Ray's Blog 打造一个强大的 PowerShell 终端 =) — Ray's Blog Ray's Blog 2023 新年快乐! + 年度总结 — Ray's Blog Ray's Blog Clerc:一个轻量但强大的命令行框架 — Ray's Blog Ray's Blog 无服务器动态博客系统 Dolan:从设想到现实 — Ray's Blog Ray's Blog 使用 Scoop + 版本管理器科学地管理你的开发环境! — Ray's Blog
Ray's Blog
i@mk1.io (Ra · 2025-12-15 · via Ray's Blog

可重用的工作流

在开发项目时,我们经常会遇到需要在多个仓库中使用相似的 CI/CD 工作流的情况。随着项目数量的增加,相同的工作流代码会不断增加,维护这些重复的工作流也会变得越来越繁琐,例如,更新某个步骤时需要在所有相关仓库中进行修改。为了解决这个问题,GitHub Actions 提供了重用工作流的功能,使我们能够将常用的工作流定义为独立的文件,并在其他工作流中引用它们,从而实现代码复用和集中管理。

在介绍如何重用工作流之前,我们先要区分两种不同的复用机制:Composite Actions 和 Reusable Workflows。简单来说:Composite Actions 是复用多个步骤,例如设置运行时、安装依赖等;而 Reusable Workflows 则是复用整个工作流,包括触发条件、作业定义等(例如构建、测试、部署等)。

方面Reusable WorkflowsComposite Actions
位置通常放置在 .github/workflows/ 目录中。通常放置在 .github/actions/ 目录中。
YAML 文件名工作流文件可以有任何名称,例如 reusable-workflow.yml操作文件必须命名为 action.yml
文件结构包含一个定义工作流的单一 YAML 文件,包含 jobssteps包含操作所在目录,包括一个 action.yml 文件,并可包含其他脚本或依赖项文件。
使用方法在其他工作流中使用 uses: <repo>/<path>@<branch>在作业步骤中使用 uses: <repo>/<action-path>@<branch>
组件可以包含多个 jobs,允许复杂的工作流。仅包含 steps;不定义 jobs
输入可以定义类型,默认值可以跟随类型变化不能定义类型,只能使用 string 作为默认值

更多区别可以参见这篇 Medium 文章 和这篇 Dev.to 文章

我们需要先进行准备工作。这里我创建一个新的 GitHub 仓库 so1ve/workflows 来存放可重用的工作流。

在常见的 CI/CD 工作流中,我们经常需要执行一些重复的任务。一个典型的例子是在执行实际的 CI/CD 任务前初始化环境,需要运行的操作包括例如检出代码库、设置 Node.js 环境、安装依赖。这里存在着明显的代码重复:

  • @actions/checkout 有不同的版本,需要在每个工作流中指定版本号,但是版本号可能会过时,而我们的检出逻辑实际上是相同的
  • @actions/setup-node 可以设置不同版本的 Node.js 环境,但是我的项目的支持目标通常是相同的,一旦 Node.js 发布了新版本,我们就需要在所有工作流中更新版本号,此外还有设置缓存等逻辑
  • 安装依赖的命令在不同项目中可能会有所不同(例如 npm installyarn installpnpm install),但是安装依赖的逻辑是相同的,区别只有包管理器

为了解决这些问题,我们可以将这些重复的步骤封装成 Composite Actions,从而实现代码复用。这样,我们只需要在需要初始化环境的地方引用这个 Composite Action 即可,此后如果需要更新逻辑只需要修改一个地方。

so1ve/workflows 仓库中创建一个新的目录 setup-js,并在该目录下创建一个 action.yml 文件。 setup-js 是一个 Composite Action,用于设置 JavaScript 项目的运行环境。action.yml 文件的内容如下:

其中:

  • inputs 定义了 Composite Action 接受的输入参数,例如 node-version 用于指定 Node.js 版本,package-manager 用于指定包管理器等。
  • runs 定义了 Composite Action 的执行逻辑,包含多个步骤,例如检出代码、安装 Node.js、安装依赖等。
    • using 必须为 composite,表示这是一个 Composite Action。
    • steps 定义了具体的执行步骤,每个步骤可以使用其他 Action,或者直接运行 shell 命令。如果是运行 shell 命令,则必须指定 shell 字段。

需要在其他工作流里使用这个 Composite Action 时,只需在作业的步骤中引用它,就像使用 @actions/checkout 那样:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Setup JS
        uses: so1ve/workflows/setup-js@main
        with:
          node-version: "22"
          package-manager: "pnpm"

接下来,我们创建一个 Reusable Workflow,用于执行常见的 CI/CD 任务,例如构建和测试项目。在 so1ve/workflows 仓库中创建一个新的工作流文件 .github/workflows/conventional-ci.yml,内容如下:

其中:

  • on.workflow_call 定义了工作流的触发方式,这里使用 workflow_call,表示这个工作流可以被其他工作流调用。我们还定义了一些输入参数,例如 node-versions 用于指定测试的 Node.js 版本,typechecklintbuildtest 分别用于指定类型检查、代码检查、构建和测试的命令。
  • jobs 定义了工作流的作业,这里包含三个作业: linttypechecktest

注意,这里我们使用了之前创建的 Composite Action so1ve/workflows/setup-js@v1 来初始化 JavaScript 环境。

要在其他工作流中使用这个 Reusable Workflow,也是只需使用 uses 关键字引用它,并传递必要的输入参数。例如,在一个新的工作流文件 .github/workflows/ci.yml 中,我们可以这样使用:

.github/workflows/ci.yml

name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  conventional-ci:
    uses: so1ve/workflows/.github/workflows/conventional-ci.yml@main
    with:
      node-versions: "22,24"
      skip-typecheck: true
      build-for-lint: true

在使用 Reusable Workflows 和 Composite Actions 时,建议使用版本标签(例如 v1.0.0)而不是分支名称(例如 main)。这样可以确保工作流的稳定性,避免因为主分支的变更导致工作流出现问题。

可以手动打标签,也可以使用其他工具。我使用的是 bumpp

同时还可以把代码推送到特定的分支上,例如 v1, v2,然后在工作流中引用这些分支。

git update-ref refs/heads/v1 refs/heads/main && git push origin v1 --force

然后在工作流中引用:

uses: so1ve/workflows/.github/workflows/conventional-ci.yml@v1