前言
提及自动化一词,我想很多同学会想到 CI/CD,这 2 者之间的确是存在肯定的分割,能够简略了解成父、子集合之间的关系。
而正如文章题目所言,近期我在钻研 macOS App 自动化散发 App Store 的事件,艰深点讲就是心愿把原先手动构建 .xcarchive
文件、导出 .pkg
文件以及上传 App Store 的操作转为 用 Shell 脚本自动化实现这些步骤。其中,减少的 Shell 脚本会基于现有的 CI/CD 的实现,退出到适当的地位。
那么,明天本文也会从 CI 根底登程,循序渐进地带着大家意识下 macOS App 自动化散发 App Store 实现的所以然。
1 意识继续集成(CI)根底
继续集成,Continuous Integration,简称 CI。这里咱们来看下 Wikipedia 上对 CI 的介绍:
—— In software engineering, continuous integration (CI) is the practice of merging all developers’ working copies to a shared mainline several times a day. Grady Booch first proposed the term CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.
通常状况下,这在咱们理论开发场景中,CI 指的是将我的项目的构建过程集成到某个独自的软件的实际。例如,在后面所说 macOS App 自动化散发 App Store 的 Shell 实现会退出到现有的 CI/CD 过程,它的 CI 的过程会是这样:
- 开发人员(构建者)触发 Jenkins 的 Job
- 执行 Job,这会由 Job 所在 Jenkins 的 Slave Node(构建机)执行,生产制品,例如一个 .dmg 或者 .pkg 文件
- 上传制品到制品库
其中,比拟要害的则是构建机(Slave Node),咱们的整个构建过程的 脚本 实现都会 在构建机上执行,例如前面要讲的自动化散发 App Store 的实现。而这里脚本应用的是 Shell 编写,当然也能够用 Google 的 zx,有趣味的同学能够自行理解,这里不做开展。
因为,在意识 macOS App 自动化散发 App Store 之前,咱们须要先晓得 macOS App 手动散发的过程是怎么样的,以便于后续用自动化脚本一一实现手动散发的步骤。
2 手动散发(Distribute)
macOS App 手动散发 App Store 的过程,艰深点讲就是 应用 Xcode 提供的 GUI 界面操作 实现。然而,在进行正式的操作应用的前提是要有一个能够公布到 App Store 配置齐备的 macOS App,这要求你须要满足以下 3 点:
- 注册成为 Apple Developer Program,在 Apple Store 中下载 Apple Developer,而后在利用的账户中注册成为一个“尊贵的 688 会员”
- 在 https://developer.apple.com/ 后盾,别离在 Certificates, Identifiers & Profiles 和 App Store Connect 创立证书相干(Bundle Identifier、Provision Profile、Signing Certificate)和注册 App
- 本地初始化创立一个简略的 macOS App,并关联上后面创立的 Bundle Identifier、Provision Profile、Signing Certificate
对于第 1 点,我想应该没什么难了解的。上面,咱们从创立一个 macOS App 登程来串联第 2、3 点要做的事件。
2.1 前置筹备(创立一个齐备的利用)
创立一个 macOS App 的我的项目,能够通过 Xcode 疾速创立一个,关上 Xcode ——> Create a new Xcode Project ——> 抉择创立利用的 Platform(macOS)——> 填写项目名称、Team、Organization Identifier 等信息 ——> 在 General 中抉择 App Category 和 App Icons,这里我创立的利用叫 FEKit。
应用 Xcode 关上该项目标 .xcodeproj
文件,或者在终端输出,在咱们这个例子则是:
open FEKit.xcodeproj
抉择构建的指标,这里咱们抉择 macOS 作为协定(Scheme)和指标(Target):
配置利用的 Bundle Identifier、Provision Profile、Signing Certificate,这能够 在 Apple Developer 后盾或者在 Xcode 的 Preferences 中增加 Apple ID 来创立,无论应用其中哪种形式创立的,都会在 Apple Developer 后盾的 Certificates, Identifiers & Profiles 中展现:
其中,如果咱们要散发 App Store,则须要这 2 个证书:
- Mac App Distribution,用于签名散发 App Store 的利用和配置对应的 Provisioning Profile
- Mac Installer Distribution,用于签名利用的安装包和提交到 App Store
当然,除开这 2 个证书,咱们还须要在 Certificates, Identifiers & Profiles 页面的 Identifiers 和 Profiles 中别离创立 App ID 和 Provisioning Profile,这 2 个步骤比较简单(这里不做开展)。
在证书、Indentifiers、Profiles 创立完后,则能够下载证书(.cer)和 Provisioning Profile(.provisionprofile)文件到本地,而后别离双击关上,其中证书则会加载到电脑登录对应的钥匙串(keychain)中,而 Provisioning Profile 则会被 Xcode 应用。并且,值得一提的是每个证书都是加密的,须要配套的密钥来解密应用,也就是 一个证书(.cer 文件)对应一个密钥(.p12 文件),这个密钥则是由证书创建者生成的,所以,你在创立证书的时候须要抉择一个 .certSigningRequest 文件:
而后在加载证书(.cer 文件)到本地,并且确保有证书对应的密钥(.p12 文件)后,最终登录的钥匙串中的证书会是这样:
2.2 Xcode 手动散发 App Store
接着,咱们则能够应用 Xcode 的 Production -> Archive 来构建 .xcarchive 文件:
构建完后,Xcode 会弹出窗口让你抉择 Distribute App 或 Validate App:
这里,咱们抉择 Distribution App -> App Store Connect -> Export -> 抉择 Development Team -> Manually manage signing,此时会要求咱们抉择后面提及的 Distribution 证书、Installer 证书和 Provisioning Profile:
抉择 Next -> Export 后,须要抉择导出的文件目录,则在该目录下会生成 FEKit.pkg 文件,而后咱们能够通过 Transporter 工具来将该文件上传到 App Store Connect(或者后面 Xcode 抉择 Export 或 Upload 的时候抉择 Upload),之后则能够在 App Store Connect 后盾的 TestFlight 查看:
所以,咱们通常所说的上传 App Store,指的是 上传到 App Store Connect 的 TestFlight,后续再由这里的 App Store 中提交上传文件的审核,审核通过再进行上架的操作。并且,须要留神的是每次上传的 .pkg 文件的版本号都须要比上一次的版本号大一(相似于 NPM 的 Package Version)。
那么,到这里整个手动散发 App Store 的过程就介绍结束了,总结起来次要是这 3 个步骤:
- 构建我的项目生成 .xcarchive 文件
- 导出 .pkg 文件
- 上传 .pkg 文件至 App Store Connect
所以,上面咱们须要 用 Shell 脚本自动化 实现这 3 个步骤,也就是 macOS App 自动化散发 App Store。
3 自动化散发(Distribute)
在介绍 macOS App 自动化散发 App Store 实现之前,咱们先来意识这 3 个工具:
- xcodebuild 是 Xcode 的一个命令行工具包,次要用于构建我的项目相干
- altool 是一个内置于 Xcode 中的命令行工具,用于验证 App 的二进制文件并将其上传至 App Store 或者对 App 进行公证(Notarize)
- xcrun 也是 Xcode 的一个命令行工具包,次要用于执行 Xcode 相干的工具链,例如
xrun altool
、xrun xcode-select
而在接下来解说 macOS App 自动化散发 App Store 过程中,则会别离提及应用这些工具提供的能力来实现后面的手动步骤。那么,上面就让咱们开始逐渐意识下自动化的实现过程,首先是构建 .xcarive 文件。
3.1 构建 .xcarchive 文件
咱们能够应用 xcodebuild.xcarchive
命令来构建生成 .xcarchive 文件:
xcodebuild -archive \
-scheme "FEKit (macOS)" \
-configuration Release \
-archivePath ./Output/FEKit
能够看到,这里咱们应用了 3 个 Option,它们别离的作用:
-scheme
构建的协定,不同的指标 Target 通常对应不同的协定,例如FEKit (iOS)
或FEKit (macOS)
,前者是 IOS,后者是 macOS-configuration
构建的配置,例如 Debug 或 Release,不同的配置对应的证书、签名配置会有不同-archivePath
构建 .xcarchive 导出的目录和文件名,这里则会导出到 Output 目录下并命名为 FEKit.xcarchive
其中,对于我的项目已有的协定和配置,则能够应用 xcodebuild -list
命令查看。
3.2 导出 .pkg 文件
构建完 .xcarchive 文件后,则须要依据改文件导出 .pkg 文件,这同样能够应用 xcodebuild
提供的 Option 命令实现:
xcodebuild -exportArchive \
-archivePath ./Output/FEKit.xcarchive \
-exportPath ./Output/Pkgs \
-exportOptionsPlist ./Build/ExportOptions.plist
其中,对于 -exportOptionsPlist
则是你导出 .pkg
相干的配置,它会是这样:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>destination</key>
<string>export</string>
<key>installerSigningCertificate</key>
<string> 你的 Mac AppStore Install 证书 ID</string>
<key>manageAppVersionAndBuildNumber</key>
<true/>
<key>method</key>
<string>app-store</string>
<key>provisioningProfiles</key>
<dict>
<key> 你的 Bundle ID</key>
<string> 你的 Provisioning Profile 的名称 </string>
</dict>
<key>signingCertificate</key>
<string> 你的证书 ID</string>
<key>signingStyle</key>
<string>manual</string>
<key>teamID</key>
<string> 你的 Team ID</string>
<key>uploadSymbols</key>
<true/>
</dict>
</plist>
当然,如果你不想手动创立或填写这些信息,能够用 Xcode 手动导出 .pkg 操作一次,ExportOptions.plist
文件会主动生成在导出的文件目录下。
执行完后面的命令后,导出的 .pkg 文件则会在 -exportPath
配置的文件门路下,在这里也就是在 /Outputs/Pkgs/
文件目录下。
3.3 验证和散发 .pkg 文件
TODO: 这里能够补充应用 keychain 的形式生产专有明码
接着,则是最初一步验证和散发 .pkg 文件。这一步骤须要应用 xcrun
和 altool
实现。首先,执行 xcrun altool --validate-app
来验证 .pkg 文件,这个次要用于确认你的利用是否满足上传的条件,例如是否抉择 App Category、App Icon 以及版本号递增等,相应的命令则是:
xcrun altool --validate-app \
-f ./Output/Pkgs/FEKit.pkg \
-t macOS \
-u xxxxx \
-p xxxxx \
--show-progress
能够看到,这里应用到了 5 个 Options,它们各自的作用:
-f
须要验证的 .pkg 文件所在文件目录地位-t
验证的指标类型,例如 macOS 或 IOS-u
用于连贯 App Store Connect 的 Apple Developer 账号(Apple ID)-p
和账号(Apple ID)对应的 App 专用明码--show-progress
用于输入验证过程的执行状况
其中,对于 -p
的 App 专用明码则须要去 Apple ID 后盾申请。并且,为了防止将明码明文展现在执行的命令中,咱们能够独自保护一个文件来存储账号和明码:
#!/bin/bash
# App Developer 账号(Apple ID)user="xxxxxxxx"
# App 专用明码
pwd="xxxxxx"
相应地,还须要依据 xcrun altool --validate-app
命令执行的后果(胜利或失败)做不同的后续解决:
#!/bin/bash
# app_store_user_pwd.sh 能够独自放到一个暗藏目录,这里只是作为例子所以没有放到暗藏目录
source "./app_store_user_pwd.sh"
echo "Run xcrun altool --validate-app..."
xcrun altool --validate-app --f ./FEKit.pkg -t macOS -u $user -p $pwd --show-progress
if [$? -eq 0]; then
echo "validate-app success"
# 执行上传的命令
else
echo "validate-app fail"
exit -1;
fi
其中,$?
示意上个命令执行后果,0
示意胜利,1
示意失败,所以这里咱们应用 if [$? -eq 0]; then
判断验证命令执行后果是否等于 0
,是则进行后续上传的解决,不是则输入验证失败的信息并退出。
那么,如果在验证通过 .pkg
文件后,咱们则能够上传 .pkg
文件至 App Store Connect,这须要执行 xcrun altool --upload-app
命令:
xcrun altool --upload-app \
-f ./Output/Pkgs/FEKit.pkg \
-t macOS \
-u xxxxx \
-p xxxxx \
--show-progress
能够看到上传的命令和验证的命令应用上大同小异,只有第一个 Option 不同。那么,到这里整个实现自动化散发 App Store 的过程曾经介绍完了,因为后面都是分步骤解说的,所以 Shell 脚本的实现都是离开的,这里咱们把下面讲到的 Shell 实现都合并到一个 .sh 文件中:
#!/bin/bash
echo "Run xcodebuild archive..."
xcodebuild archive \
-scheme "FEKit (macOS)" \
-configuration Release \
-archivePath ./Output/FEKit
ARCHIVE_FILE=./Output/FEKit.xcarchive
if [! -e "$ARCHIVE_FILE"]; then
echo ".xarchive doesn't exist";
exit -1;
fi
echo "Run xcodebuild -exportArchive..."
xcodebuild -exportArchive \
-archivePath ./Output/FEKit.xcarchive \
-exportPath ./Output/Pkgs \
-exportOptionsPlist ./Build/ExportOptions.plist
PKG_FILE=./Output/Pkgs/FEKit.pkg
if [! -e "$PKG_FILE"]; then
echo ".pkg doesn't exist";
exit -1;
fi
source "./Build/app_store_user_pwd.sh"
xcrun altool --validate-app --f $PKG_FILE -t macOS -u $user -p $pwd --show-progress
if [$? -eq 1]; then
echo "altool validate-app fail"
exit -1;
fi
echo "altool validate-app success"
xcrun altool --upload-app --f $PKG_FILE -t macOS -u $user -p $pwd --show-progress
if [$? -eq 0]; then
echo "altool --upload-app success"
else
echo "altool --upload-app fail"
fi
4 应用 fastlane 自动化散发
fastlane 是一个能够便捷地帮你实现 证书治理、代码签名和公布等相干 的工具,实用于 iOS、macOS 和 Android 利用。那么,咱们也就能够应用 fastlane 来实现下面应用 Shell 脚本实现的自动化散发 App Store 过程。
首先,必定是装置 fastlane,对于这方面的介绍官网文档解说的很是详尽,这里就不反复阐述。而当你装置好 fastlane,则能够在利用我的项目的根目录执行 fastlane init
来初始化它相干的配置,在初始化的过程会让你抉择应用 fastlane 的形式,这里咱们抉择手动配置即可,而后它会在我的项目根目录下创立一个 fastlane/Fastfile
目录和文件,后续咱们在执行 fastlane xxx
命令的时候则会依据该文件的代码实现执行具体的操作,默认生成的 Fastfile 文件的配置会是这样:
default_platform(:ios)
platform :ios do
desc "Description of what the lane does"
lane :custome_lane do
# add actions here: https://docs.fastlane.tools/actions
end
end
其中,default_platform
用于定义一个默认的平台 Platform,例如当咱们有 2 个平台(iOS 和 macOS)的时候,它的的配置须要这样:
default_platform(:ios)
platform :ios do
desc "Description of what the lane does"
lane :custome_lane do
# add actions here: https://docs.fastlane.tools/actions
end
end
platform :mac do
desc "Description of what the lane does"
lane :custome_lane do
# add actions here: https://docs.fastlane.tools/actions
end
end
此时,如果咱们执行 fastlane custome_lane
,因为这里平台默认为 ios
,所以则会执行 platorm:ios
下的 custome_lane
,反之执行 fastlane mac custome_lane
,则是 platform :mac
下的 custome_lane
。那么,对于后面咱们这个例子而言只须要 platform:mac
:
default_platform(:ios)
platform :mac do
desc "Description of what the lane does"
lane :custome_lane do
# add actions here: https://docs.fastlane.tools/actions
end
end
接着,则能够在 platform:mac
写咱们须要实现的自动化散发 App Store 相干的代码。fastlane 便捷之处在于它实现了很多开箱即用的 Action,这里咱们须要应用 build_mac_app 和 upload_to_app_store 2 个 Action,前者能够用于构建导出 .pkg 文件,后者能够用于上传 .pkg 文件到 Apple Store Connect:
default_platform(:mac)
platform :mac do
desc "Description of what the lane does"
lane :build_upload_appstore do
# 构建、导出 .pkg 文件
build_mac_app(scheme: "FEKit (macOS)",
export_method: "app-store",
output_directory: "./Output/Test",
output_name: "FEKit",
export_team_id: "xxxxxx",
export_options: {
provisioningProfiles: {"com.xxxxxx.xxxx" => "macOSAppStore"}
}
)
# 上传 .pkg 到 App Store Connect
upload_to_app_store(
pkg: "./Output/Pkgs/FEKit.pkg",
platform: "osx",
username: "xxxxxxxxx"
)
end
end
其中,在应用 upload_to_app_store
的时候须要留神的是,这里只是申明了你 App Store 的用户名,而专用明码须要事后在零碎环境变量中增加 FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
,而后 fastlane 在执行 upload_to_app_store
Action 时会去读取该环境变量。
结语
最初,这里咱们用一个流程图再回顾下整个自动化散发 App Store 的过程:
并且,我想可能有同学会问,作为前端咱们须要懂这个吗?集体认为是须要的,因为在一些场景下,比如说做 React Native 或 Electron 开发的时候,不可避免地就会接触到原生利用的签名、构建、公证(Notarize)和散发 App Store 的概念,所以,通过亲自地体验一番原生利用实现这些的过程还是有肯定收益的(知其然使其然)。
如果,文中存在表白不当或谬误的中央,欢送各位同学提 Issue ~
点赞
通过浏览本篇文章,如果有播种的话,能够 点个赞,这将会成为我继续分享的能源,感激~
我是五柳,喜爱翻新、捣鼓源码,专一于源码(Vue 3、Vite)、前端工程化、跨端等技术学习和分享,欢送关注我的 微信公众号:Code center。