12k
All articles

面向前端团队的 5 个 GitHub Actions 替代方案

比较适用于前端团队的五种 GitHub Actions 替代方案:CircleCI、Buildkite、Jenkins、Woodpecker CI 和 Dagger,并提供配置示例与选择建议。

OpenReplay Team
OpenReplay Team
面向前端团队的 5 个 GitHub Actions 替代方案

对前端团队而言,最值得考虑的 GitHub Actions 替代方案有以下几类:需要完全托管的 CI,选 CircleCI;需要托管控制平面、同时让作业运行在托管或自托管 agent 上,选 Buildkite;需要完全自托管的 CI,选 Jenkins 或 Woodpecker CI;需要以代码定义流水线,并让它在笔记本和任意 CI 中以相同方式运行,选 Dagger。

团队开始寻找替代方案,通常是因为以下几种情况:账单上的 runner 分钟数居高不下,Pull Request 在队列里迟迟等不到执行,或者某个工作流只在 GitHub 的 runner 上失败、在本地却从不复现。本文假设你已经熟悉 GitHub Actions 工作流模型,并从三个维度对比这五种方案:各自适合哪类团队、作业运行在哪里,以及 Node 前端项目的安装、lint、测试和构建作业分别怎么写。

核心要点

  • 如果每个 CI 作业都只调用 npm ci、npm run lint、npm test 和 npm run build,那么更换 CI 工具时只需改写几行 YAML,而无需改动流水线逻辑。
  • Buildkite 负责托管编排,作业则运行在 agent 上:可以是 Buildkite 托管的 Linux、Buildkite 托管的 macOS(仅限付费套餐),也可以是团队自己维护的机器。
  • CircleCI 是托管式 CI,通过 .circleci/config.yml 进行配置,所有套餐(包括免费版)都支持自托管 runner。
  • Jenkins 和 Woodpecker 都是自托管方案。你不再按分钟付费,转而需要承担服务器和运维成本。
  • Dagger 不是 CI 服务,而是一套流水线代码,既能在本地运行,也能在你现有的任何 CI 中运行。

前端团队为什么要寻找 GitHub Actions 的替代方案?

前端团队放弃 GitHub Actions,通常出于以下四个原因之一:托管 runner 的分钟数费用过高;托管 runner 需要排队;需要在自有硬件上运行 agent;无法在本地复现 CI/CD 流水线。迁移之前,先仔细评估第二个原因:如果托管 runner 排队是你唯一的问题,那么 GitHub Actions 自托管 runner 或许无需更换工具就能解决。至于 GitLab CI/CD,主要适合打算连同代码仓库一起迁移的团队,其配置方法可参阅 GitLab CI/CD 流水线。

为了保证对比公平,请将构建逻辑放在 package.json 中,让每个 CI 工具都调用同一组脚本:

{
  "scripts": {
    "lint": "eslint .",
    "test": "vitest run",
    "build": "vite build"
  }
}

请根据你所用框架替换为相应的命令。在下文的每个示例中,CI 配置只做一件事:先运行 npm ci,再依次运行这三个脚本。

Buildkite

Buildkite 适合希望使用托管编排、但又需要掌控作业运行机器的团队。Buildkite 同时支持两种模式:自行运行的 agent,以及由 Buildkite 托管的 agent。Buildkite 托管的 Linux agent 在所有套餐中均可使用,其中免费版仅限小规格机器;Buildkite 托管的 macOS agent 则需要 Pro 或 Enterprise 套餐。自托管 agent 会主动轮询 Buildkite 获取任务,因此无需开放任何入站端口。Buildkite 提供免费账户供你上手试用。

# .buildkite/pipeline.yml
steps:
  - label: "Install, lint, test, build"
    commands:
      - npm ci
      - npm run lint
      - npm test
      - npm run build
    plugins:
      - docker#v5.14.0:
          image: "node:<your-node-version>"

Docker 插件会在 Node 镜像中执行这些命令,因此 agent 上只需安装 Docker。如果 agent 上已经装好了 Node,可以去掉 plugins 配置块。

**结论:**如果你希望掌控计算资源,又不想自己运维 CI 服务器,Buildkite 是最合适的选择。代价是,除非使用托管 agent,否则你需要自行管理 agent 集群。

CircleCI

CircleCI 适合希望使用完全托管服务、尽量减少基础设施投入的团队。CircleCI 以托管服务为主,同时在所有套餐中都提供自托管 runner,包括免费版。默认情况下,你的代码运行在 CircleCI 的基础设施上。根据 CircleCI 的配置入门文档,2.1 是最新的配置版本。

# .circleci/config.yml
version: 2.1

jobs:
  build:
    docker:
      - image: cimg/node:<full.node.version>
    steps:
      - checkout
      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

workflows:
  ci:
    jobs:
      - build

请将 cimg/node 固定为项目所用的完整 Node 版本号。CircleCI 同样支持依赖缓存,但为了保持示例简洁,这里省略了相关配置。YAML 写错是首次推送到 CircleCI 失败的常见原因,因此建议在提交前先用 OpenReplay YAML 校验工具检查一遍,及早发现语法错误。

**结论:**CircleCI 是与 GitHub Actions 最接近的同类替代品。如果你的问题在于分钟数费用和排队,又不想自己运维服务器,CircleCI 是合理的选择。

Jenkins

Jenkins 适合有严格本地部署要求、并且有专人负责维护的团队。Jenkins 只能自托管。软件本身免费开源,但成本从按分钟计费转移到了团队需要维护的服务器、插件和版本升级上。流水线定义在 Jenkinsfile 中,采用声明式 Pipeline 语法编写:

pipeline {
    agent any
    stages {
        stage('Install') { steps { sh 'npm ci' } }
        stage('Lint')    { steps { sh 'npm run lint' } }
        stage('Test')    { steps { sh 'npm test' } }
        stage('Build')   { steps { sh 'npm run build' } }
    }
}

agent any 的前提是,无论哪个 agent 领取该作业,其上都已安装 Node。

**结论:**只有在自托管是硬性要求时才选择 Jenkins。对大多数前端团队而言,它带来的运维成本会超过节省下来的分钟数费用。

Woodpecker CI

Woodpecker CI 适合希望使用轻量级自托管 CI、并且偏好熟悉的 YAML 写法的小型团队。Woodpecker CI 采用自托管方式,按照其工作流语法的规定,每个步骤都会在该步骤指定的容器中执行命令。工作流可以放在 .woodpecker/ 目录下,每个文件对应一个工作流。

# .woodpecker/ci.yaml
steps:
  - name: install
    image: node:<your-node-version>
    commands:
      - npm ci
  - name: lint
    image: node:<your-node-version>
    commands:
      - npm run lint
  - name: test
    image: node:<your-node-version>
    commands:
      - npm test
  - name: build
    image: node:<your-node-version>
    commands:
      - npm run build

将工作拆分为四个步骤,并不意味着要安装四次依赖。步骤默认按顺序执行,检出的工作区会挂载到每个步骤中,因此 install 步骤生成的 node_modules 目录在 build 步骤中依然存在。只要安装了 woodpecker-cli 和受支持的后端,就可以在推送前通过 woodpecker-cli exec 在本地运行工作流。

**结论:**在自托管场景下,Woodpecker CI 比 Jenkins 更简单。缺点是服务器和 agent 都需要你自己运行和维护。

Dagger:以代码定义流水线,而非 CI 服务

Dagger 不是托管式 CI 服务,也无法取代 CI 服务。你使用 Dagger SDK 以代码形式编写流水线,同一份代码既能在笔记本上运行,也能在任何 CI 系统(包括 GitHub Actions)中运行。SDK 文档涵盖 Go、Python、TypeScript、Java、PHP 和 Elixir,以及 Dagger 自有的脚本语言 Dang。下面用 TypeScript 实现同样的作业,所用模块通过 dagger init --sdk=typescript --name=frontend-ci 创建:

import { dag, Directory, object, func } from "@dagger.io/dagger"

@object()
class FrontendCi {
  @func()
  async check(source: Directory, nodeVersion: string): Promise<string> {
    return await dag
      .container()
      .from(`node:${nodeVersion}`)
      .withMountedDirectory("/src", source)
      .withWorkdir("/src")
      .withExec(["npm", "ci"])
      .withExec(["npm", "run", "lint"])
      .withExec(["npm", "test"])
      .withExec(["npm", "run", "build"])
      .stdout()
  }
}

在本地使用 dagger call check --source=. --node-version=<your-node-version> 运行。现有 CI 作业只需执行这同一条命令即可,无需其他配置。只要本地运行通过,CI 中执行的就是完全相同的容器步骤。代价是团队需要额外学习一套 SDK 和引擎。

以上命令适用于 Dagger 0.x。2026 年 10 月以 beta 形式发布的 Dagger 1.0 对这些命令进行了重命名:改用 dagger module init 创建模块,dagger call 则变为 dagger api call。TypeScript 代码本身保持不变。

如何选择 GitHub Actions 替代方案?

选择哪种 GitHub Actions 替代方案,取决于你希望作业运行在哪里:

  • **如果你想要完全托管、无需任何运维的 CI,**选择 CircleCI。它的配置与你现有的配置高度对应。
  • **如果你想要托管编排,并让作业运行在自有机器或供应商托管的机器上,**选择 Buildkite,尤其是在需要 macOS 构建时。
  • **如果必须自托管,并且有人力负责维护,**选择 Jenkins。
  • **如果必须自托管,并且希望方案尽量轻量,**选择 Woodpecker CI。
  • **如果真正的问题是“本地能跑,CI 失败”,**引入 Dagger,并继续使用上述任一工具(或 GitHub Actions 本身)作为执行器。
  • **如果唯一的问题是排队时间,**优先尝试 GitHub Actions 自托管 runner。

Woodpecker 的 Docker 后端和 Dagger 都需要容器运行时。如果 Docker Desktop 不适合你的机器环境,Dagger 也可以运行在 Podman 和 nerdctl 上,Woodpecker 则可以运行在 Kubernetes 上,或通过其 local 后端直接运行在宿主机上。

无论选择哪种工具,第一步都是把所有构建逻辑迁移到 npm scripts 中。然后在单个分支上试用替代方案,让它与 GitHub Actions 并行运行,对比一周的结果后再正式切换。

常见问题

GitHub Actions 的自托管 runner 是否按分钟收费?

不收费。GitHub 不对自托管 runner 的使用按分钟计费,成本仅为运行这些 runner 的机器费用。2025 年 12 月,GitHub 宣布自 2026 年 3 月 1 日起对自托管 runner 收取每分钟 0.002 美元的平台费用,随后又推迟实施,以重新评估相关方案。在基于上述任一数字进行成本对比之前,请先查阅 GitHub Actions 的计费文档。

能否在推送前于本地运行 CircleCI 作业?

可以,但每次只能运行一个作业。CircleCI CLI 可以通过 circleci local execute 在本机的 Docker 中运行单个作业。工作流无法在本地运行,machine executor 也不受支持。对于 2.1 版本的配置,需要先使用 circleci config process 导出处理后的配置,再通过 -c 参数将该文件连同作业名称一起传给 circleci local execute。

Woodpecker CI 是否支持托管在 GitHub 上的仓库?

支持。Woodpecker 支持 GitHub(包括 GitHub Enterprise),以及 GitLab、Gitea、Forgejo 和 Bitbucket Cloud。你需要在代码托管平台上注册一个 OAuth 应用,并通过 WOODPECKER_GITHUB_CLIENT 和 WOODPECKER_GITHUB_SECRET 等环境变量将其 client ID 和 secret 传给 Woodpecker 服务器。仓库仍保留在 GitHub 上,Woodpecker 会将流水线状态回报给 GitHub,只有服务器和 agent 运行在你自己的基础设施上。

如何在现有的 GitHub Actions 工作流中运行 Dagger 函数?

在 actions/checkout 之后添加一个使用官方 dagger/dagger-for-github action 的步骤。该 action 会安装 Dagger CLI,在 runner 上启动 Dagger Engine 并调用你的函数。将 verb 设置为 call,并传入与本地相同的参数,例如 check 以及源代码目录和 Node 版本。流水线逻辑保留在模块中,因此日后迁出 GitHub Actions 时,只需修改这一层很薄的封装。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.