- 数据库
- 桌面应用
- 开发工具
【免费下载链接】Sequel-Ace
MySQL/MariaDB database management for macOS
fastlane/README.md是 Sequel-Ace 仓库中由 fastlane 自动生成的发布动作清单。本篇指南以此清单为主体,结合 Fastfile、RELEASING.md 与发布工具源码,系统讲解 Sequel-Ace 如何用 4 个活跃 Lane 与 9 个退役 Lane 组织 macOS App 的发布流程。读完本文,你将掌握这些 Lane 的调用方式、参数约束、环境变量与 fail-closed 安全机制,以及它们在整个发布链路(GitHub Actions + Xcode Cloud + App Store Connect)中的准确位置。
环境准备与安装
官方文档要求先安装最新的 Xcode 命令行工具:
xcode-select --install随后在仓库根目录安装依赖(Gemfile 已锁定 fastlane 版本),并通过 Bundler 调用:
bundle install bundle exec fastlane mac <lane_name>README 中所有 Lane 都标注了[bundle exec]前缀,说明仓库约定每次调用都必须经过 Bundler,避免本机全局 fastlane 版本漂移。RELEASING.md 进一步说明:Bundler 方案同时被 GitHub 工作流与本地工具共用,两者运行的是同一套 Ruby 库与锁定的 gem。
fastlane 在 Sequel-Ace 发布体系中的定位
Fastfile 开头的注释明确了一个关键设计:Fastfile 是"围绕仅含基础设施的 Ruby 发布工具的一层薄适配器(thin adapter)"。也就是说:
- 分支、提交、推送、PR、构建号选择、GitHub Release 均由受保护的 GitHub 工作流控制;
- fastlane 只负责它擅长的 App Store 操作(App Store Connect 鉴权与元数据上传);
- fastlane 从不自行决定构建号、创建 git 分支、提交、推送或创建 GitHub Release。
这种"职责分离"贯穿整个发布体系:真正的发布编排入口是Scripts/release-tool,而 fastlane 只承担其中与 App Store Connect 直接交互的部分。从 release-tool 的源码可以看到,该脚本会切换到 Homebrew 的 keg-only Ruby 并设置BUNDLE_GEMFILE指向仓库自身的 Gemfile,再调用fastlane/bin/sa-release,保证与工作流环境一致。
可用动作总览
README 在## Mac平台下列出了全部 15 个 Lane,按其状态可分成两类:
活跃 Lane(4 个)
| Lane | 调用方式 | 作用 |
|---|---|---|
prepare_release_files | bundle exec fastlane mac prepare_release_files | 设置显式发布版本/构建号并重新生成 changelog;从不提交或推送 |
stage_app_store_release | bundle exec fastlane mac stage_app_store_release | 创建/更新生产元数据但不提交审核 |
submit_app_store_release | bundle exec fastlane mac submit_app_store_release | 提交"已精确 staging 的"生产版本/构建号进入审核 |
generate_changelog_locally | bundle exec fastlane mac generate_changelog_locally | 本地生成 changelog,无任何 git 副作用 |
退役 Lane(9 个)
| Lane | 状态说明 |
|---|---|
prepare_release | Retired unsafe release lane |
prepare_release_bump_patch_version | Retired unsafe release lane |
prepare_beta_release_bump_version | Retired unsafe release lane |
prepare_beta_release_bump_patch_version | Retired unsafe release lane |
prepare_beta_release | Retired unsafe release lane |
generate_changelog | Retired unsafe release lane |
increment_build_version | Retired unsafe release lane |
increment_app_version | Retired unsafe release lane |
increment_app_patch_version | Retired unsafe release lane |
这些退役 Lane 在 Fastfile 中统一由一段%i[...]循环生成:所有动作都会调用UI.user_error!并提示"` was retired. Use fastlane/bin/sa-release plan and the guarded release workflow."。也就是说,旧式的"本地增量 + 直接发布"路径已彻底关闭,任何误用都会被立即拒绝,引导开发者转向受保护的发布工作流。
活跃 Lane 深入解析
prepare_release_files:显式版本 + changelog 再生
这是唯一不触碰任何发布环境变量的 Lane,也是本地与 CI 都可以安全执行的准备动作。调用形式:
bundle exec fastlane mac prepare_release_files \ version:6.0.1 build:20113 channel:production \ base_tag:production/6.0.0-20104 expected_base_sha:<SHA> \ changelog_base_tag:production/6.0.0-20104 expected_changelog_base_sha:<SHA>从 Fastfile 的实现看,它要求 6 个必填参数:version、build、channel、base_tag、expected_base_sha、changelog_base_tag、expected_changelog_base_sha(源码中required_option!对空值直接报错);expected_main_sha为可选参数,用于冻结当前 main 的提交。
该 Lane 的核心是把参数原样转发给fastlane/bin/sa-release prepare子命令。sa-release的prepare实现(cli.rb)会依次做四件事:
- 校验 git 工作区干净(
git.ensure_clean!); - 校验
HEAD与expected_main_sha一致、base_tag/changelog_base_tag各自解析出的 SHA 与预期值一致,否则报 "comparison tag does not match its approved SHA"; - 通过
VersionFiles更新项目版本文件(构建号、渠道等); - 调用 Scripts/generate-changelog.sh 在
RANGE_START..RANGE_END之间生成 changelog,最后校验被改动的路径集合是否只包含白名单版本文件。
注意--expected-*系列参数保证了"冻结 SHA"语义:任何标签漂移、main 变更都会在写入前被拦截。
generate_changelog_locally:无副作用的本地 changelog
bundle exec fastlane mac generate_changelog_locally version:6.0.1它只要求version一个参数,并直接调用Scripts/generate-changelog.sh。该脚本(set -euo pipefail)会自动定位最近的上一个production/<semver>-<build>稳定标签作为比较基准;若本地没有标签,则退化为"最后一次修改 CHANGELOG.md 的提交",最终再退化到仓库根提交。脚本按#added、#fixed、#removed、#infra等前缀(或语义化的动词首词)对提交进行分类,并生成五段式 changelog(Added / Fixed / Changed / Removed / Infra)。它支持DRY_RUN=1环境变量实现"只预览不写入"。
stage_app_store_release:先 staging,不提交
bundle exec fastlane mac stage_app_store_release \ version:6.0.1 build:20113 \ release_notes_file:./app-store-notes.txt \ promotional_text_file:./promotional.txt \ auto_release_date:1716768000这是生产发布的第一步,只会创建/更新 App Store Connect 上的元数据(版本、构建号、Release Notes、Promotional Text、自动发布日期),submit_for_review: false。它的关键参数与源码行为如下:
release_notes_file/promotional_text_file:从文件读取文本并去首尾空白,二者均不可为空,否则直接UI.user_error!;auto_release_date:以秒为单位的 Unix 时间戳,源码用Integer(..., 10)强制解析;- 调用的 fastlane action 固定为
upload_to_app_store,并显式配置:app_identifier: "com.sequel-ace.sequel-ace"(PRODUCTION_BUNDLE_ID)、platform: "osx";skip_binary_upload: true(本步骤只传元数据)、skip_screenshots: true;phased_release: true(7 天分阶段发布)、reset_ratings: false(保留评分);run_precheck_before_submit: false;force: true。
源码中两个重要守卫值得注意:
- 该 Lane 首先调用
require_release_automation_enabled!:只有当环境变量SA_RELEASE_AUTOMATION_ENABLED == "true"时才会继续,否则报错 "Release publishing is disabled until every feasibility gate passes"——直接调用 fastlane 无法绕过可行性门禁; - App Store Connect 鉴权统一由
release_api_key完成(见下节)。
submit_app_store_release:只提交已 staging 的精确版本
bundle exec fastlane mac submit_app_store_release version:6.0.1 build:20113该 Lane 同样要求SA_RELEASE_AUTOMATION_ENABLED=true,只接受version与build两个参数,并以skip_binary_upload: true、skip_metadata: true、submit_for_review: true调用upload_to_app_store。这种"先 stage 后 submit"的两阶段拆分在 RELEASING.md 中有明确设计意图:
stage_app_store_release只写元数据;- Ruby 客户端通过文档化的 App Store version/build 关系附加精确构建产物;
- API 回读本地化文案、Promotional Text、十张完整截图、审核信息、选中构建、排期与分阶段发布状态;
- 全部验证通过后才由
submit_app_store_release真正提交审核。
若提交返回结果不明确,工作流会用独立的 Ubuntu 恢复任务轮询该精确版本与构建号最长 15 分钟,macOS 发布者不阻塞等待;只有选中构建仍匹配生产构建号时才接受"已提交"状态。
App Store Connect 鉴权与环境变量
stage与submit两个 Lane 都通过release_api_key方法获取 ASC 鉴权,相关环境变量如下:
| 环境变量 | 含义 | 缺失时的行为 |
|---|---|---|
SA_ASC_KEY_ID | 专用 Team ASC Key ID(App Manager 角色) | UI.user_error!("SA_ASC_KEY_ID is required") |
SA_ASC_PRIVATE_KEY | Base64 编码的.p8私钥内容 | UI.user_error!("SA_ASC_PRIVATE_KEY is required") |
SA_ASC_ISSUER_ID | Team API Issuer ID | 当SA_ASC_REQUIRE_ISSUER=1时缺失即报错(fail-closed) |
SA_ASC_PRIVATE_KEY_BASE64 | 设为1时表示私钥为 Base64 编码 | 工作流中固定为1 |
SA_ASC_REQUIRE_ISSUER | 设为1时强制要求 Issuer ID | 工作流中固定为1 |
源码最终调用:
app_store_connect_api_key( key_id: key_id, issuer_id: issuer_id.to_s.empty? ? nil : issuer_id, key_content: private_key, is_key_content_base64: ENV["SA_ASC_PRIVATE_KEY_BASE64"] == "1", in_house: false )这些密钥只存放在受保护的sequel-ace-release环境中,绝不出现在 manifest 或工作流日志中。
安全模型与 fail-closed 设计
整个发布体系围绕"即使有人直接调用 fastlane 也无法绕过门禁"设计:
SA_RELEASE_AUTOMATION_ENABLED初始值为false,只有 release_feasibility.yml 一类可行性工作流逐项验证(下载/验证/启动/退出构建产物、Team key 可读两个 App 与两个 Cloud 工作流、Alpha 运行产物、GitHub App 签名提交路径、私有 GHCR 推送/拉取校验和等)全部通过、并由维护者手动改为true后才放开发布;- 退役 Lane 一律
UI.user_error!拒绝执行; - 发布启动仅限
Jason-Morcos与Kaspik两人(同时校验原始actor与当前triggering_actor); - 仓库变量
SA_RELEASE_PENDING_ARTIFACT_TAG与SA_RELEASE_PENDING_FINALIZATION_TAG必须存在且初始为none,任一未设置都会在 checkout 前被拒绝; - 所有 HTTP 传输只对只读
GET自动重试,绝不重放POST/PATCH/PUT/DELETE类变更请求,避免远程副作用不明确。
发布全景:Lane 之外的真实链路
fastlane 只覆盖 App Store 元数据环节。真实发布的完整链条由Scripts/release-tool(其子命令见 cli.rb)与各 GitHub 工作流承担:
- 规划与审批:维护者先执行只读
Scripts/release-tool plan --channel production --target-version ... --base-tag ... --main-ref origin/main --app-store-notes ... --output release-plan.json,审核推荐版本、冻结 SHA、变更清单与审批 SHA-256 后,再以精确审批哈希派发release.yml; - Release starter(release.yml):冻结源与说明、准备并合并 release PR、创建轻量标签与 prerelease、启动精确的 Xcode Cloud 运行,并保存不可变的私有握手;
- Xcode Cloud:构建带标签源码并执行 Notarize/TestFlight 后置动作;构建号由 Xcode Cloud 而非 fastlane 决定,发布工具按"观测到的最高生产构建号 + 1"推导期望值;
- Release Artifact Publisher(release_publish.yml):下载精确 Cloud 产物,校验版本/构建、架构(universal arm64/x86_64)、签名身份(Moballo team
NKQ4HJ66PX)、公证与 stapling、Gatekeeper、启动/退出行为,打包 updater ZIP 存档至私有 GHCR,再附加校验和一致的副本到 GitHub prerelease,随后 stage/校验/提交 App Store 构建; - Release finalizer(release_finalize.yml):等待 App Store
READY_FOR_DISTRIBUTION,重新校验归档与公开产物,才将 prerelease 转为正式 release。
构建号由fastlane/bin/sa-release reconcile-build依据BuildReconciler在标签、App Store Connect 构建与 Cloud 运行三处观测到的最大值基础上推导,fastlane 永不自行计算或递增构建号。
本地开发与测试
fastlane/目录内置了完整的 Ruby 测试套件(test 下 40 余个*_test.rb,覆盖 planner、reconciler、artifact verifier、submission provenance、workflow recovery 等),由 Rakefile 聚合运行:
export BUNDLE_PATH="$(mktemp -d -t sequel-ace-release-bundle)" export PATH="/opt/homebrew/opt/ruby/bin:/opt/homebrew/bin:/opt/homebrew/sbin:${PATH}" bundle install bundle exec rake -f fastlane/Rakefile test仓库约定使用 Homebrew Ruby 与隔离的 Bundler 路径,不使用系统 Ruby。Scripts/release-tool会自动选中 keg-only 的 Homebrew Ruby 并设置BUNDLE_GEMFILE,因此从任意目录调用都能保持同一环境。release-tool help可列出全部子命令(plan、workflow-plan、guard、prepare、reconcile-build、verify-artifact、submit、finalize、github-* 系列、cloud-status、wait-cloud、download-cloud-artifacts、release-status、version 等)。
小结
fastlane/README.md虽然只是一份自动生成的 Lane 清单,但它准确刻画了 Sequel-Ace 发布体系的一个切面:fastlane 是 App Store 操作的薄适配器,其余发布职责全部收敛到受保护的工具链中。4 个活跃 Lane(prepare_release_files、generate_changelog_locally、stage_app_store_release、submit_app_store_release)+ 9 个强制退役 Lane 的布局,既保留了成熟的upload_to_app_store/app_store_connect_api_key能力,又以SA_RELEASE_AUTOMATION_ENABLED与"显式版本/构建号 + 冻结 SHA"的约束把所有高风险操作纳入了可审计、可恢复、fail-closed 的自动化流程。结合 Fastfile 与 RELEASING.md 阅读,即可完整理解这套从 GitHub Actions 到 Xcode Cloud、再到 App Store Connect 与 GitHub Release 的发布链路。
- 数据库
- 桌面应用
- 开发工具
【免费下载链接】Sequel-Ace
MySQL/MariaDB database management for macOS
相关推荐
Readest 应用商店发布自动化实战:基于 Fastlane 的 iOS/macOS App Store 与 Google Play 流水线解析
Readest 应用商店发布自动化实战:基于 Fastlane 的 iOS/macOS App Store 与 Google Play 流水线解析 本篇技术指南
桌面应用跨平台前端OptiScaler 实战指南:把游戏里 DLSS/FSR/XeSS 上采样替换掉,再补上帧生成
OptiScaler 实战指南:把游戏里 DLSS/FSR/XeSS 上采样替换掉,再补上帧生成 OptiScaler 是一款开源的上采样替换中间件:它拦截游戏
图形学游戏开发用fastlane构建iOS自动化发布流水线:从开发到上架的完整指南
用fastlane构建iOS自动化发布流水线:从开发到上架的完整指南 还在为iOS应用的手动打包、证书管理、App Store提交而烦恼吗?fastlane作为
开发工具CI/CD移动开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考