结论:可信且稳定的工作负载,可以在权限边界和主机清理均有证据的前提下评估常驻 Runner;执行不可信代码或高权限任务,应优先评估一次性 Runner,并自动清理或重建承载环境。一次性注册只限制 Runner 接收任务的生命周期,不能证明底层 Mac 已恢复干净。

本周建议动作:先抽查一条外部贡献代码工作流和一条签名发布工作流,逐项核对触发条件、令牌权限、Keychain 使用、节点网络范围与任务后的清理记录;有一项无法验证,就先不要让两类任务复用同一台常驻 Mac。

负责自托管 Mac Runner 机群、需要决定节点按任务复用还是持续在线的 IT 负责人,适合阅读本文。
管理 iOS/macOS CI 安全边界的平台工程师,以及正在评估 Mac 构建资源的技术总监,也能用下面的验收步骤厘清责任。

01

GitHub Actions 自托管 Mac Runner 的生命周期不是主机隔离

选型先分清四个状态:任务结束、Runner 注销、主机清理、干净环境重建。它们不是同一件事。GitHub 的文档说明,启用一次性运行后,Runner 处理一个任务便会自动注销;注销后由企业自行安排清理 Runner 承载环境。换句话说,自动注销解决的是调度注册问题,不能替代对磁盘、用户目录、Keychain 或系统状态的验收。官方自托管 Runner 参考文档也要求将一次性 Runner 的日志转发至外部存储,以便在运行环境删除后仍能诊断。

决策维度 常驻 Runner 一次性 Runner
任务接收 节点持续注册并可接收后续任务 单个任务完成后自动注销
工作区与缓存 可能保留并被后续任务复用,需验证残留 仍需检查任务后主机如何清理或重建
凭证风险 后续任务可能碰到前一任务留下的状态 降低跨任务复用机会,但不自动擦除主机
工具链与环境 可保留已安装工具与缓存,需防止漂移 可通过重建环境验证基线,需维护重建流程
诊断证据 可从节点本地日志排查,但需设置留存 日志须在节点销毁前外传并验证可读
适用判断 可信、稳定、可审计且清理责任明确的任务 不可信或高权限任务,且主机清理机制可验证

一次性 Runner 常见设置方式如下。此命令只说明注册参数,不包含令牌,也不表示完成了主机清理:

./config.sh --url "$RUNNER_URL" \
  --token "$RUNNER_TOKEN" \
  --ephemeral

GitHub 文档说明,一次性 Runner 只接收一个任务,完成后自动从服务端注销;如需再次运行,承载环境的准备、擦除或重建仍由团队的自动化流程负责。

02

先按任务来源划分信任边界

仓库属于同一组织,并不意味着其中的每个工作流都可信。应以触发事件、被执行的代码来源、工作流修改权限和任务可获取的凭证为判断依据;特别检查外部贡献分支、由手动触发的工作流,以及能够检出并执行外部提交内容的任务。

例如,外部贡献者提交的代码可能经由构建脚本、依赖安装或测试命令在 Runner 上执行。审批流程可以限制任务是否启动,却不等于主机隔离;如果获批的工作流实际执行不可信代码,Runner 所在环境仍需按不可信任务评估。官方安全使用说明明确提醒,自托管 Runner 不保证运行在临时、干净的虚拟机中,不可信代码可能持续影响 Runner 环境。

任务类别 初始信任判断 Runner 选择倾向 必须核对的条件
受保护分支的常规构建 相对可信,但仍须审查工作流与依赖 可评估常驻 代码审查、最小令牌权限、工具链变更记录
外部贡献代码的构建与测试 不可信输入 优先评估一次性 不向任务提供不必要的 Secrets;验证主机清理或重建
发布签名与部署 高权限、影响面大 使用隔离且受控的执行路径 签名材料访问范围、审批路径、Keychain 清理与审计
手动触发的临时任务 取决于触发者、参数和代码来源 按权限与代码来源决定 谁能触发、能否改变工作流、任务是否会执行外部内容

使用 pull_request_target 时尤其要审查工作流是否检出并执行外部贡献代码。官方说明指出,该事件在基础分支上下文中运行;不能因为工作流审批或分支归属,就把被执行的代码自动视为可信。安全使用 pull_request_target 的说明

03

凭证管理要覆盖任务结束之后

评估 Mac CI 环境隔离时,不要只问“本次工作流拿到了哪些 Secrets”,还要追踪它们进入主机后的去向。工作流显式注入的环境变量、临时文件、SSH 密钥、签名身份、Keychain 项,以及构建脚本可能访问的内网服务,都可能让任务影响超出单次执行。

GITHUB_TOKEN 会按工作流任务生成,并在任务结束时失效;但这不代表其他凭证也自动失效。仓库或组织 Secrets、签名材料及自行配置的访问令牌,仍应按其各自的有效期、访问权限和清理方式验证。官方令牌说明和Secrets 管理文档建议限制凭证权限,并明确哪些工作流可以使用它们。

环境 Secrets 的审批也不是主机安全边界。官方文档特别说明,自托管 Runner 上的工作流不会因使用环境而在隔离容器中运行;因此,不能把“设置了必需审查者”当成节点已隔离的证据。环境与部署保护规则说明

具体核查时,可要求每个高权限任务提供以下证据:

  • 工作流的 permissions 只开放实际需要的令牌权限,并能说明为什么需要写入权限。
  • 签名任务使用的身份仅由指定任务访问;任务后检查 Keychain 和临时文件,不假设注销 Runner 会移除它们。
  • Runner 网络只开放构建所需的仓库、依赖源和服务;不要因为任务属于组织就默认其可访问内网。
  • 清理记录能显示工作区、凭证落点和主机状态的核验结果;无法确认清理完成时,停止节点复用。
04

第二步:把环境重建与日志留存纳入验收

常驻节点的便利在于保留工具链、依赖和缓存,但环境可能随手工更新、失败任务或残留文件逐渐偏离基线。一次性节点更容易把“每次如何得到环境”变成可审查流程,但若重建脚本没有覆盖 Xcode、依赖、模拟器状态和必要配置,也不能仅凭“重新创建”证明环境一致。

环境一致性应靠实际对照,而非推测构建速度。在试运行中记录工具链版本、依赖锁定状态、工作区清理结果与模拟器状态;同一工作负载分别检查常驻任务前后和重建后差异。没有测量记录时,不应承诺某种模式更快,也不应把缓存保留当作性能结论。

审计也要跟着生命周期设计。常驻 Runner 的本地 _diag 目录可提供 Runner 与任务诊断日志,但如果节点故障或被重置,日志可能一并丢失;一次性 Runner 同样需要在环境销毁前将日志转存到外部,并验证外部记录能关联到对应任务。官方监控文档说明,Runner 日志保存在安装目录的 _diag 文件夹,同时要求一次性 Runner 的日志在外部转发和保留。监控与故障排查文档

05

按证据完成验收,而不是只看 Runner 状态

以下步骤可用于现有 Mac Runner 试点,也适用于准备新增节点的评审。每一步都应保留配置或测试结果;如果某项无法验证,先把节点限定为已知可信的低权限工作负载。

第一步:列出触发源与执行内容。从工作流文件和仓库设置中,标出受保护分支、外部贡献、手动触发、发布任务及能执行外部代码的步骤。审查触发事件、检出 ref 和构建命令,不以仓库归属代替信任判断。

第二步:盘点任务可用凭证。逐项列出 GITHUB_TOKEN、仓库或环境 Secrets、签名身份、SSH 凭证和内网访问能力,记录任务是否确实需要这些权限。对签名材料,安排任务结束后的实际清理与再读取测试。

第三步:观察任务之间的残留。在隔离的测试流程中,检查工作区、缓存、临时文件、Keychain 和模拟器状态。可在任务中输出非敏感的环境标识或预设测试文件状态,用以确认后续任务能否读到前一任务留下的内容;不要把真实凭证写入日志。

第四步:验证清理或重建链路。确认自动化流程覆盖 Runner 注销之后的主机动作,并记录成功、失败与回退状态。若只能注销 Runner、无法确认主机内容已擦除,应按未完成隔离处理,禁止不可信任务与可信任务复用。

第五步:验证日志外传和故障调查。模拟一次失败任务,确认外部日志包含足以定位 Runner 与工作流任务的信息;再确认删除或重建承载环境后,调查人员仍能取得这些证据。若日志只能留在即将销毁的节点本地,先补齐外部留存再投入生产。

第六步:先小范围运行并设置回退条件。在常驻与一次性模式各选一类可信任务进行验收,比较基线偏差、残留检查、凭证范围与排障材料。只要出现清理不可证明、日志无法取回或权限超出任务需要,就回退到可信任务专用节点,暂停高风险任务接入。

06

用三个决策表确定运行模式

下表用于把运行模式与基础设施责任一起评审。一次性 Runner 的单任务属性有官方依据;表内关于组织如何安排主机清理、工具链重建和恢复责任,则是企业应自行验证的控制措施,不是 Runner 自动提供的保证。

评审指标 可评估常驻 Runner 优先评估一次性 Runner 不满足时的处理
任务信任 受保护分支、代码来源和依赖均受控 外部代码或信任程度不确定 不把任务放入共享常驻节点
清理能力 有可执行的任务间清理及检查记录 可自动销毁或重建承载环境 不能证明干净时,不认定隔离完成
凭证边界 仅可信任务可访问限定凭证 凭证使用短时、范围最小且可撤销 拆分签名任务与普通构建任务
工具链一致性 版本与缓存变化可追踪 环境可按基线重建并验收 暂停扩大任务范围,先建立基线
审计与恢复 节点本地日志有备份,责任人明确 节点销毁前日志已外传 无法调查失败任务时,不进入生产
运维责任 有人负责更新、清理、故障恢复 有人维护创建、销毁与重建自动化 明确责任人和回退路径后再选型
验收对象 应保留的证据 通过条件
工作流信任 触发条件、代码来源、仓库权限 能区分可信发布与不可信贡献代码
凭证暴露 permissions、Secrets 范围、Keychain 检查记录 后续任务不能读取前序任务遗留凭证
主机清理 注销记录、擦除或重建结果、残留检查 有可复核的主机状态证据,而非只有 Runner 离线状态
环境一致性 Xcode、依赖、工作区与模拟器检查结果 版本及状态符合团队维护的基线
故障诊断 外部 Runner 日志、任务日志与关联信息 承载环境删除后仍能还原故障经过

GitHub 也提供从组织或仓库移除 Runner 的操作说明,但从服务端移除注册记录与擦除 Mac 上的数据仍是不同动作;验收时应分别核对服务端记录和主机处理结果。移除自托管 Runner 的说明

⚠️ 一次性 Runner 只表示它在完成单个任务后不再继续接收任务。若没有主机销毁、重置或干净环境重建的可验证记录,就不能据此宣称 Mac CI 环境已隔离。

07

常见问题

外部贡献代码可以放进组织级常驻 Runner 吗?

不应只因 Runner 属于组织或仓库,就视为外部贡献代码可信。先确认触发条件、实际执行的代码以及该任务可用的令牌、Secrets 和网络资源。若任务会执行不可信代码,优先评估一次性承载,并验证主机清理或重建;若清理无法证明,就不要让它与发布任务共用节点。

Runner 注销后,怎么确认 Mac 已经干净?

注销记录只能证明 Runner 不再以原注册身份接收任务,不能单独证明主机状态。需要查看任务结束后的清理记录,并抽查工作区、临时凭证、Keychain、模拟器状态和网络访问配置。若没有可审计的重置结果,按环境仍可能残留处理,选择销毁并重建,或停止节点复用。

审批和 Runner 分组能不能替代 Mac CI 环境隔离?

不能。审批用于约束任务是否获准继续,分组用于安排 Runner 的可用范围;它们都不等同于磁盘、用户目录或系统状态隔离。评估时应分别测试主机之间的访问边界、任务后的凭证清理和日志外传。只有这些主机层证据齐备,才能把隔离作为实际控制措施。

一次性 Runner 需要保留哪些排障材料?

至少要让 Runner 日志与具体工作流任务可以关联,并在节点销毁之前完成外部转存;此外,还应按企业审计要求保存工作流日志、环境版本和清理结果。演练时先删除或重建测试节点,再由未登录该节点的排障人员调取材料,确认失败原因仍可调查。

08

结尾建议:先核对 Mac 的交付与清理责任

常驻方案的主要代价,是需要持续治理节点更新、工作区残留、凭证回收和工具链漂移;一次性方案则增加创建、日志外传、主机清理与重建失败恢复等运维责任。两者都不是免运维方案,关键是团队能否拿出任务权限、清理结果和故障证据。

若团队需要临时或按周期增加真实 Mac 构建环境,可先查看远程 Mac 方案与交付选项,再从NodeMini 服务入口核对实际访问方式、环境重置责任和限制。只有这些条件能被书面确认并纳入验收,才适合评估租赁;若要求长期固定高负载、必须直接控制物理接口,或清理责任无法确认,则应优先评估自购设备或团队可直接管理的其他基础设施。