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 才适合作为目标环境。
判断标准应是:
- 依赖解析结果一致。
- 编译警告和错误没有新增阻断项。
- 单元测试、UI 测试和模拟器启动均通过。
.xcarchive能正常生成。- 构建产物能被后续发布任务读取。
- 失败后能在原镜像或备用节点重跑。
第二种场景:固定 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 步执行:
- 冻结现状:导出所有 YAML、模板、变量组、Agent Pool、签名任务和发布环境。
- 建立资产表:为每条任务标记镜像、Xcode、Runtime、网络、证书和负责人。
- 选两条代表流水线:一条普通 PR,一条生产发布。
- 开启双跑:同一提交同时跑旧环境与候选环境。
- 隔离敏感节点:签名、私网和生产发布进入独立 Pool。
- 设定关闭门槛:连续构建成功、签名产物一致、恢复演练通过后,才移除 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 仍可能更合适。