跳到正文
Hacker News· petersunde·· 7 天前AI 评分62

localci 发布:在本地运行 GitHub Actions 作业再推送

Show HN: localci, run your GitHub Actions jobs locally before you push

AI 导读

localci 是一个在本地运行现有 .github/workflows 的工具,无需新配置,只跑与当前机器 OS 匹配的作业,跳过 actions/checkout 等 setup 步骤。

正文 · AI 翻译

localci

CI Release MIT

localci lists Horizon's CI jobs, catches a formatting slip in 4 seconds, passes after the fix, and reuses the passed steps on a rerun

等待 GitHub 接收你的推送、排队一个 runner 并从冷缓存重新构建一切,这很慢。有时 GitHub 干脆宕机了。localci 在你自己的机器上运行你现有的 .github/workflows/ci.yml,只需几秒钟,而且你的构建缓存仍然是热的。

  • 无需新配置。它读取你已经拥有的工作流。
  • 你的操作系统,你的任务。它运行那些 runs-on 与你机器(Linux、macOS 或 Windows)匹配的任务,并告诉你哪些任务需要其他操作系统。
  • 真实的步骤。Shell 步骤、矩阵、needs、输出、GITHUB_ENV、if: 条件和 services:(作为 Docker 容器)的行为与在 GitHub 上一致。诸如 actions/checkout 之类的 setup 操作会被跳过,因为你的机器已经有 checkout 和这些工具了。
  • 为 agent 而打造。一条命令就能教会 Claude Code、Codex 和其他 agent 在推送前运行你 CI 中正确的子集。
  • 极小。一个静态二进制文件,下载不到 800 KB,安装不到 2 秒。

数字

在 Horizon 上测量,这是一个公开的 Rust 工作区,带有 Linux、macOS 和 Windows CI 矩阵,测量时间为 2026 年 10 月 10 日和 11 日。

等待 GitHub 与本地检查对比

时间
一次 GitHub CI 运行,从推送到结果(18 次运行的中位数) 27 分钟
用 localci run 运行相同的 Linux 任务,一个接一个 15 到 23 分钟
用 localci run --fast 运行相同的改动 2 分 16 秒
再次运行 localci run --fast,没有任何改动 0 秒
一个失败的 CI 测试,在推送前被 localci run repo-checks 发现 4 秒
在 PR 上用 Copilot 进行一轮代码审查,外加一次推送 约 5 分钟
一轮本地审查(该 skill 的 Copilot CLI 提示),不推送 1 到 4 分钟

它在一个 pull request 上节省了什么。没有 localci 时,每次推送都会启动一次约 62 runner-minutes 的完整 CI 运行,而一轮修复要等它完成。在最近 40 个已合并的 Horizon PR 中:

审查轮数 CI 运行次数 Runner 时间
小型 PR(5 个文件或更少),中位数 1 1 63 分钟
大型 PR(超过 10 个文件),中位数 5 5 307 分钟
使用 localci 和该 skill 的 PR 循环的大型 PR(估算) 1 到 2 1 到 2 60 到 125 分钟

有了 PR 循环,你在本地审查和测试,直到两者都干净,GitHub 上的审查就变成了最终检查,而不是你反复迭代的地方。对于一个大型 PR,这大约意味着少等 1½ 小时,以及少用 3 到 4 小时的 runner 时间。大型 PR 那一行是估算;下面的行是实测的。

真实的 PR,随着循环的改进

PR 新增内容 GitHub 上的审查轮数 CI 运行次数 从打开到就绪
#1461 每次推送前运行 localci,修复直接推送而不运行 CI 4(1 次有发现) 4 次推送运行 2 次 9 分钟后首次批准
#1466 PR 前进行一次通用本地审查 5 5 次推送启动了 4 次 42 分钟
#1471 一次要求具体失败输入的本地审查,并将 GitHub 的审查作为最终检查 1 1 12 分钟

作为对比,在 localci 之前,Horizon 小型 PR 的中位数从打开到合并需要 24 分钟,包含一轮审查和一次 63 runner-minutes 的 CI 运行。

快速开始

macOS 和 Linux

curl -fsSL https://raw.githubusercontent.com/peters/localci/main/install.sh | sh

Windows (PowerShell)

irm https://raw.githubusercontent.com/peters/localci/main/install.ps1 | iex

不想把脚本直接管道进你的 shell?从 Releases 下载二进制文件:Linux x64 和 arm64(静态)、macOS Apple silicon 和 Intel,以及 Windows x64。安装了 Rust 的话,你也可以在约 10 秒内自行构建:cargo install --locked --git https://github.com/peters/localci。

然后,在任何带有 GitHub Actions 的仓库中:

localci list     # every job and matrix leg, and which run here
localci run      # run them

为你的 agent 做引导

localci skill install

这会把一个 skill 放入 ~/.claude/skills、~/.codex/skills 和 ~/.agents/skills(针对你拥有的每个 agent)。从那时起,只需问:

在推送前本地运行 CI。

智能体会查看计划和你的 diff,建议哪些作业和步骤值得运行,只询问你一次,然后运行它们,并且只读取失败步骤的日志。它知道本地运行只是快速的预检查,并非真正的 GitHub 结果。

日常使用

localci plan                          # what would run, step by step, without running it
localci run clippy                    # one job, by id
localci run "linux x64 libs"          # one matrix leg, by name
localci run --matrix shard=libs       # legs with that matrix value
localci run --skip-setup              # leave out apt-get, brew and installer steps
localci run --skip "slow tests"       # leave out steps by name or command
localci run --only lint               # run only matching steps
localci run -k                        # keep going after a failing job
localci run -w release                # another workflow file
localci check                         # can localci handle every workflow here?

添加 --json -q 以获得机器可读的报告。每个步骤的日志都会被保留,并在最后打印路径。

快速模式(0.1.0 新增)

localci run --fast

--fast 同时是三件事:

  • --affected:当某个步骤的输入自你的分支离开默认分支以来没有变化时,跳过构建和测试步骤(Cargo、npm、dotnet、Go、Gradle、Swift)。localci 无法读取其命令的步骤始终会运行。
  • --cache:在相同输入上复用已经通过的步骤,包括其输出。
  • --parallel 0:同时运行相互独立的作业(2 到 4 个,取决于 CPU 数量)。

在 Horizon 上,一次文档和 CI 变更从 23 分钟的完整 Linux 运行缩短到使用 --fast 的 136 秒,而在没有变更的第二次运行中缩短到 0 秒。localci plan --affected 展示了每个步骤为何运行或不运行。在推送以供审查之前,先在不带 --fast 的情况下运行一次。

在本地跳过,在 GitHub 上保留

有些步骤永远不应该在你的笔记本电脑上运行,比如 sudo apt-get install 或部署作业。用普通的 GitHub 条件标记它们。localci 会设置 LOCALCI,而在 GitHub 上它是空的,因此 GitHub 会继续运行它们:

jobs:
  deploy:
    if: ${{ !vars.LOCALCI }}          # jobs: use vars
    ...
  test:
    steps:
      - name: Install system packages
        if: ${{ !env.LOCALCI }}       # steps: env or vars
        run: sudo apt-get install -y libssl-dev

服务

带有 services: 的作业(PostgreSQL、Redis 等)会获得真实的 Docker 容器,包括其健康检查和端口映射,并在作业结束时移除。如果你自己已经运行了这些服务,请添加 --no-services。设置 LOCALCI_DOCKER=podman 以使用 Podman。

对比

act 是这方面知名的工具,wrkflw 则是一个较新的工具。两者都试图复现 GitHub runner:默认情况下,它们在容器中运行每个作业,并运行 uses: actions。当你想测试工作流本身时,这是正确的选择。

localci 回答的是另一个问题:“我的变更能通过 CI 吗?”因此它做出相反的选择:

act / wrkflw(默认) localci
步骤在哪里运行 一个模仿 runner 镜像的容器 你的机器,在你的检出目录中
构建缓存 通常是冷的:被忽略的构建输出留在容器之外 你温暖的 target/、node_modules/ 等
uses: actions 运行它们 跳过它们;你的机器已经有这些工具
未变更的步骤 再次运行 --fast 将它们排除或复用结果
智能体 不是重点 以 JSON 表示的计划、一个 skill,以及仅失败步骤的日志

act 也可以直接在宿主机上运行(-P ubuntu-latest=-self-hosted)。剩下的区别在于 localci 省略了什么,以及它被设计为由智能体驱动。

当 localci 不适合时

  • 你的 CI 主要是市场 actions。如果真正的工作发生在 uses: 步骤中(例如 docker/build-push-action 或部署 action),localci 会跳过它。请使用 act 或 GitHub。
  • 你需要精确的 runner 镜像。localci 使用你的工具和版本。某个步骤可能在这里通过,却在 GitHub 上失败,因为工具不同。
  • 针对其他操作系统的作业。它只运行与你的机器匹配的作业。请改在那种机器上运行。
  • 可复用工作流和 container: 作业。它不会运行它们。
  • GitHub 上的结果。它不会发布检查或状态。GitHub CI 仍是最终依据。

兼容性表列出了每项功能,决策记录解释了原因。

发现了与 GitHub 的差异?

每个 bug 都会变成 tests/cases/ 中的一个小文件夹:一个工作流及其应给出的结果。无需 Rust 代码。参见该流程,并请提交 issue 或 pull request。

许可证

MIT

来源:Hacker News · github.com