☰
Sequel-Ace 的 Fastlane 发布流水线:从 Lane 到 App Store 的一体化发布实践
2026/9/28 3:46:30 网站建设 项目流程
  • 数据库
  • 桌面应用
  • 开发工具

【免费下载链接】Sequel-Ace

MySQL/MariaDB database management for macOS

项目地址:https://gitcode.com/gh_mirrors/se/Sequel-Ace
点击查看免费下载

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_filesbundle exec fastlane mac prepare_release_files设置显式发布版本/构建号并重新生成 changelog;从不提交或推送
stage_app_store_releasebundle exec fastlane mac stage_app_store_release创建/更新生产元数据但不提交审核
submit_app_store_releasebundle exec fastlane mac submit_app_store_release提交"已精确 staging 的"生产版本/构建号进入审核
generate_changelog_locallybundle exec fastlane mac generate_changelog_locally本地生成 changelog,无任何 git 副作用

退役 Lane(9 个)

Lane状态说明
prepare_releaseRetired unsafe release lane
prepare_release_bump_patch_versionRetired unsafe release lane
prepare_beta_release_bump_versionRetired unsafe release lane
prepare_beta_release_bump_patch_versionRetired unsafe release lane
prepare_beta_releaseRetired unsafe release lane
generate_changelogRetired unsafe release lane
increment_build_versionRetired unsafe release lane
increment_app_versionRetired unsafe release lane
increment_app_patch_versionRetired 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)会依次做四件事:

  1. 校验 git 工作区干净(git.ensure_clean!);
  2. 校验HEAD与expected_main_sha一致、base_tag/changelog_base_tag各自解析出的 SHA 与预期值一致,否则报 "comparison tag does not match its approved SHA";
  3. 通过VersionFiles更新项目版本文件(构建号、渠道等);
  4. 调用 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 中有明确设计意图:

  1. stage_app_store_release只写元数据;
  2. Ruby 客户端通过文档化的 App Store version/build 关系附加精确构建产物;
  3. API 回读本地化文案、Promotional Text、十张完整截图、审核信息、选中构建、排期与分阶段发布状态;
  4. 全部验证通过后才由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_KEYBase64 编码的.p8私钥内容UI.user_error!("SA_ASC_PRIVATE_KEY is required")
SA_ASC_ISSUER_IDTeam 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 teamNKQ4HJ66PX)、公证与 stapling、Gatekeeper、启动/退出行为,打包 updater ZIP 存档至私有 GHCR,再附加校验和一致的副本到 GitHub prerelease,随后 stage/校验/提交 App Store 构建;
  • Release finalizer(release_finalize.yml):等待 App StoreREADY_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

项目地址:https://gitcode.com/gh_mirrors/se/Sequel-Ace
点击查看免费下载

相关推荐

上一篇:不用自己收数据:FMA 音乐数据集三步走到流派分类
下一篇:AntiMicroX 完整指南:10 分钟把手柄映射成键盘鼠标,老游戏一键复活

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询