Azure Pipelines macOS-14 下线:2026 企业迁移怎么选

Azure Pipelines macOS-14 下线:2026 企业迁移怎么选

流水线今天仍然成功,但 brownout 会主动制造失败;继续把所有任务固定在 macOS-14,迁移窗口只会越来越短。

最快解法:不要直接切到 macOS-latest。 无状态 PR 构建先迁移到经过双跑验证的受支持托管镜像;固定 Xcode、私网依赖、模拟器 Runtime 或生产签名任务,转入隔离的 self-hosted macOS agent。最稳妥的企业路径是先建立双轨节点池,再关闭 macOS-14。

本文适合仍使用 macOS-14 镜像、需要在移除前完成流水线迁移的 Azure Pipelines 管理者。企业 IT、研发效能、安全团队,以及负责 Xcode、私有依赖、代码签名和发布连续性的技术负责人,也可以直接使用后文的决策矩阵。

最后更新于 2026 年 9 月 20 日,时间表、镜像标签、Agent 能力和 Xcode 27 状态已根据官方托管 Agent 文档及官方镜像清单核实。

macOS-14 下线迁移:先判断失败类型,再决定节点

截至 2026 年 9 月 20 日,macOS-14 托管镜像已经进入停用流程。官方计划从 2026 年 7 月 6 日开始弃用,并在 2026 年 10 月安排 brownout,于 2026 年 11 月 2 日正式移除。macOS-14 任务可能不是每天都失败,而是在 brownout 时段、镜像重建或标签切换后间歇性失败。

真正需要区分的是两类问题:

  • 镜像移除风险:YAML 中仍存在 vmImage: macos-14,或者通过变量间接引用该标签。
  • 普通构建故障:镜像仍能启动,但 Xcode、SDK、Simulator Runtime、插件或签名脚本已经不兼容。

先在代码库中盘点这些字段:

grep -RInE "macos-14|macOS-14|vmImage|Xcode|xcodebuild|simctl|sign|archive" \
  azure-pipelines*.yml pipelines/ . 2>/dev/null

建议把每条流水线记录成任务资产,而不是只记录“构建是否成功”。

资产 当前状态 负责人 主要阻断项 推荐下一步
PR 编译与单元测试 macOS-14 iOS 平台组 无固定 Runtime 双跑 macOS-15 / macOS-26
UI 测试 macOS-14 测试团队 指定 Simulator Runtime 先验证 Runtime,再决定节点
归档与签名 macOS-14 发布团队 Keychain、证书、出口 IP 独立签名池
私有依赖拉取 macOS-14 IT 网络组 内部 Git、制品库、代理 self-hosted macOS agent
灾备构建 macOS-14 研发效能组 无备用容量 纳入混合节点池

macOS-14 移除后,现有流水线会出现哪些变化?
固定引用 macos-14 的任务会在镜像不可用后无法按原配置获取 Agent;使用 macos-latest 的任务则可能因为默认镜像、架构或预装工具变化而出现另一类失败。两者不能混为一谈,前者是资源标签失效,后者是环境漂移。

第一种场景:无状态 PR 构建优先迁移到托管镜像

PR 编译、单元测试、静态检查通常具备三个特征:代码和依赖可在 Job 内重新获取,不需要访问生产网络,也不依赖机器上上一次任务留下的缓存。

这类任务适合先尝试 macOS-15 或 macOS-26,但不要只验证 Agent 能否上线。托管 Agent 每个 Job 使用新的虚拟机,Job 结束后文件系统变化不会保留;自托管 Agent 则可以保留机器级缓存和配置。这个差异会影响依赖下载、编译缓存和构建时间,但性能结论必须来自同一提交的双跑记录,而不是凭经验判断。

双跑时应固定以下变量:

parameters:
- name: image
  type: string
  default: 'macOS-15'

jobs:
- job: Validate
  pool:
    vmImage: ${{ parameters.image }}
  steps:
  - bash: |
      set -e
      sw_vers
      xcodebuild -version
      xcodebuild -showsdks
      xcrun simctl list runtimes
    displayName: "Record macOS and Xcode environment"

输出至少要保留:

ProductName: macOS
ProductVersion: 15.x
BuildVersion: xxxxx
Xcode 26.x
iPhoneOS SDK 26.x
Simulator Runtime: iOS 26.x

这里的版本必须以发布时官方镜像清单为准。官方镜像仓库显示,macOS-15、macOS-26、Arm64 镜像和 xcode-27 标签分别具有不同状态;latest 不是固定工具链,而是会随 GA 镜像变更的移动标签。(官方镜像标签与状态)

选择迁移目标时,关键不是版本号更大,而是项目是否已经完成新 SDK 和新 Runtime 的实际验收。如果项目仍依赖较旧 SDK、插件或已验证的 macOS-15 环境,优先选择 macOS-15 并锁定明确标签;如果项目已经完成新 SDK 和新 Simulator Runtime 验证,macOS-26 才适合作为目标环境。

判断标准应是:

  1. 依赖解析结果一致。
  2. 编译警告和错误没有新增阻断项。
  3. 单元测试、UI 测试和模拟器启动均通过。
  4. .xcarchive 能正常生成。
  5. 构建产物能被后续发布任务读取。
  6. 失败后能在原镜像或备用节点重跑。

第二种场景:固定 Xcode、旧版 SDK 与模拟器 Runtime

旧项目最容易在这里误判。流水线表面上只是从 macOS-14 换到 macOS-15 或 macOS-26,实际变化可能包括:

  • 默认 Xcode 小版本改变。
  • 旧版 iOS、watchOS 或 tvOS SDK 不再预装。
  • 历史 Simulator Runtime 被移除。
  • Ruby、Node.js、脚本解释器或系统工具版本变化。
  • Intel 与 Apple Silicon 的二进制插件行为不同。
  • 依赖解析器重新计算版本,导致锁文件之外的变化。

如果项目必须使用特定 Xcode 小版本,macos-latest 就不应作为生产发布池标签。托管镜像可以用于兼容性验证,但不能替代固定环境控制。

哪些构建任务更适合放入自托管 Mac Agent?
满足以下任一条件,就应把任务列入 self-hosted macOS agent 评估范围:

  • 必须安装特定 Xcode 小版本或旧 Simulator Runtime。
  • 依赖内部 Git、私有制品库或固定出口 IP。
  • 需要持久化 Keychain、证书、Provisioning Profile 或硬件授权。
  • 构建脚本依赖机器级配置、缓存或固定路径。
  • 发布任务必须在受控节点上运行。
  • 需要连续运行、定时任务或本地恢复脚本。

自托管并不意味着把所有任务都放到一台共享 Mac 上。官方建议每台机器只运行一个 Agent,以避免多个 Agent 争抢资源并影响流水线结果。(官方 Agent 安全与运行说明)

第三种场景:Apple Silicon 与 Xcode 27 只能先做兼容验证

Apple Silicon 是架构决策,不只是“换一台更快的 Mac”。需要关注三个问题:

  • 项目依赖是否提供 arm64 原生包。
  • 构建脚本是否暗含 x86_64 路径。
  • 模拟器、插件和签名工具是否已通过真实项目验收。

官方镜像清单已列出 macOS-26 Arm64 与 xcode-27 Arm64 镜像。Xcode 27 当前仍应按公开预览状态处理,不能因为镜像能够启动,就直接替换生产签名池。(官方 Xcode 27 Arm64 镜像说明)

按量托管 Apple Silicon Agent 适合短期兼容验证和弹性构建,但它依然是平台提供方管理的 Agent。企业无法把所有机器级配置、私网路由、证书存储和恢复逻辑都当成永久不变。自托管 Apple Silicon Mac 才适合长期保留固定工具链,前提是企业能承担补丁、监控、磁盘清理、重启和故障替换。

验收顺序应保持一致:

uname -m
xcodebuild -version
xcodebuild -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath "$PWD/build/App.xcarchive" archive

codesign --display --verbose=4 "$PWD/build/App.xcarchive/Products/Applications/App.app"

预览镜像只完成“兼容性验证”这一职责。生产池需要额外通过真实项目、真实模拟器、真实签名证书和真实发布链路验证。

第四种场景:私网依赖与生产签名必须拆成可信节点

内部 Git、制品库、私有包源、固定出口和生产证书会改变迁移结论。托管镜像的优势是每次 Job 获得干净环境,但它不一定满足企业网络边界;自托管 Mac 的优势是网络和工具链可控,代价是它会长期保存工作区、缓存、日志和签名材料。

生产签名节点不应与普通 PR 构建共用 Agent Pool。官方安全建议包括:不同项目使用不同 Agent Pool,生产产物使用独立池,Agent 运行账号使用最低权限,并限制防火墙和服务连接范围。(官方流水线安全建议)

建议把凭证流向画出来:

Pipeline
  ├─ PR 构建池:无生产证书,只读依赖
  ├─ 集成测试池:测试证书、测试设备
  └─ 生产签名池:受限分支、受限 Pool、最小权限账号
                         └─ 发布服务

自托管 Mac 的运行账号不要直接拥有组织级权限,也不要使用管理员账号运行 Agent。官方文档特别提醒,Agent 会执行从流水线下载的代码,若运行身份权限过高,恶意或被篡改的任务可能读取密钥、访问其他系统或横向移动。macOS Agent 应使用专用非 root 账号,并限制 Agent 目录、日志和构建产物的访问范围。(macOS Agent 安全说明)

macOS-14 停用前,Xcode 和签名链路应怎样验收?
不要只验证 xcodebuild build。至少要用同一提交完成依赖解析、编译、单元测试、归档、签名、导出和发布前校验。每一步都保存日志、产物哈希、Xcode 版本、SDK 列表和签名身份,最后再验证失败回退是否可用。

第五种场景:发布高峰适合混合节点池,而不是单一路线

企业常见的混合方案是:

  • 日常 PR 构建使用受支持的托管镜像。
  • 固定 Xcode 或私网依赖任务使用自托管 Mac。
  • 生产签名使用隔离的可信节点。
  • 发布高峰保留一组备用容量。
  • brownout 期间保留临时回退路径,但不把回退当成长期方案。

如果企业需要弹性自定义池,也可以评估托管 DevOps Pool 一类的管理模式。此类方案通常支持自定义镜像、网络接入、自动扩缩和团队专属池,但其底层资源与标准 Microsoft-hosted Agent 的隔离方式不同,仍需单独核对网络、区域、镜像和安全边界。

迁移实施可以按以下 6 步执行:

  1. 冻结现状:导出所有 YAML、模板、变量组、Agent Pool、签名任务和发布环境。
  2. 建立资产表:为每条任务标记镜像、Xcode、Runtime、网络、证书和负责人。
  3. 选两条代表流水线:一条普通 PR,一条生产发布。
  4. 开启双跑:同一提交同时跑旧环境与候选环境。
  5. 隔离敏感节点:签名、私网和生产发布进入独立 Pool。
  6. 设定关闭门槛:连续构建成功、签名产物一致、恢复演练通过后,才移除 macOS-14。

本站没有获得可公开核验的真实 Azure Pipelines 双轨迁移记录,因此不虚构构建时长、恢复时间、节点规格或成本数字。企业应使用自己的流水线记录填入下表。

验证项目 托管镜像双跑 自托管 Mac 双跑 合格条件
依赖解析 记录锁文件与解析日志 记录锁文件与缓存状态 结果可解释
编译 保存警告与错误 保存警告与错误 无新增阻断错误
Simulator 记录 Runtime 与设备 记录 Runtime 与设备 真实测试通过
归档 保存 .xcarchive 哈希 保存 .xcarchive 哈希 产物可复核
签名 记录身份与导出日志 记录身份与导出日志 只在受控池执行
重启恢复 重新排队验证 重启 Mac 后验证 Agent 自动回归可用

迁移方案怎么选:三条路径的企业决策表

方案 适合任务 主要优点 主要限制 回退方式
继续使用受支持托管镜像 无状态 PR、单元测试、静态检查 环境干净,维护责任较少 每次 Job 重建,工具链控制有限 切换到另一受支持镜像
自托管 Apple Silicon Mac 固定 Xcode、私网依赖、持久缓存 环境可控,适合固定工具链 需要补丁、监控、权限和恢复 切换备用 Mac 节点
混合节点池 日常构建加生产发布 兼顾弹性、隔离和连续性 路由、Pool 和权限设计更复杂 托管池与专用 Mac 互相承接

可以把验收门槛写成简单的条件逻辑:

如果:
  依赖可公开或按 Job 拉取
  不需要生产证书
  不依赖固定出口
  双跑结果一致
则:
  迁移到受支持的托管镜像

否则如果:
  需要固定 Xcode / Runtime
  或需要私网访问
  或需要生产签名
则:
  使用隔离的 self-hosted macOS agent

如果两类任务同时存在:
  采用托管构建池 + 自托管 Mac 签名池的双轨方案
关闭 macOS-14 前的证据 未通过时的处理
PR 流水线在候选镜像连续通过 暂不切换默认镜像
旧 SDK 与 Simulator Runtime 已确认 建立短期兼容池
签名产物可复核且权限隔离 转入专用签名节点
私网依赖访问稳定 保留自托管节点
Agent 重启后可自动回归 增加备用节点或恢复脚本
brownout 期间无关键发布失败 才关闭 macOS-14

当前方案与远程 Mac 方案:不要忽略迁移后的运维成本

继续依赖旧版 macOS-14 的缺点很明确:镜像即将移除,brownout 会制造间歇性失败,团队还要同时处理 Xcode、SDK 和 Simulator Runtime 的环境漂移。全部改用新托管镜像也不是万能答案:固定工具链、私网访问和生产签名仍可能被环境隔离、权限边界或镜像变更卡住。

如果企业已经确认任务必须使用固定 Mac 环境,但又不想立刻采购和维护多台实体设备,可以把专用远程 Mac 节点作为双轨 PoC 的第三条路径。SFTPMAC 提供按周期交付的真实 Mac 主机,适合先验证 self-hosted macOS agent、固定 Xcode、签名节点和备用容量;具体可先查看远程 Mac 租赁方案与Mac mini 租赁价格。

更稳妥的做法不是立即批量迁移,而是选取一条真实 PR 流水线和一条生产发布流水线进行双轨 PoC。若新版托管镜像无法通过固定环境、私网或签名验收,再评估按周期交付的专用远程 Mac 节点;若长期高负载、需要物理接口或必须完全自有资产,企业自购 Mac 仍可能更合适。