使用Travis CI和GitHub进行iOS的持续部署和持续集成

让我们看看如何将GitHub项目与Travis链接。 使用您的GitHub帐户登录Travis网站。 对于私人存储库,您需要注册一个Travis Pro帐户。 登录后,您必须为Travis启用项目。 导航到配置文件页面,其中列出了您的所有GitHub项目。 请注意,以后创建新存储库时,请使用立即同步按钮。 Travis仅偶尔更新列表

现在使用开关启用您的项目。 之后,您应该在GitHub项目设置中看到Travis挂钩。 下一步是告诉Travis一旦收到更改通知该怎么办。

最小的项目配置

Travis CI需要有关您的项目的一些基本信息。 在项目根目录中创建一个名为“ .travis.yml”的文件,其内容如下:

自定义构建命令

Travis从命令行构建您的项目。 因此,第一步是使您的项目在本地编译。 作为Xcode命令行工具的一部分,Apple附带了xcodebuild

打开您的终端并输入:

  xcodebuild —帮助 

这应该列出xcodebuild的所有可能参数。 如果失败,请确保正确安装了命令行工具。 这是典型的构建命令的外观:

  xcodebuild -project {project} .xcodeproj -target {target} -sdk iphonesimulator ONLY_ACTIVE_ARCH = NO 

设置“ iphonesimulator” SDK以避免签名问题。 这是必需的,直到我们稍后包含证书为止。 通过设置“ ONLY_ACTIVE_ARCH = NO”,我们确保可以针对模拟器架构进行构建。 您还可以设置其他属性(例如,配置)。 输入man xcodebuild’以阅读文档。

对于CocoaPods项目,您必须改为指定工作区和方案:

  xcodebuild -workspace {workspace} .xcworkspace -scheme {scheme} -sdk iphonesimulator ONLY_ACTIVE_ARCH = NO 

使用XCode自动创建方案,但这不会在服务器上发生。 确保将方案声明为共享,并将其添加到存储库。 否则它将在本地运行,但不能在Travis CI上运行。

我们的示例项目的“ .travis.yml”现在看起来像这样:

 语言:Objective-C 
osx_image:xcode9.3script:-xcodebuild -workspace TravisExample.xcworkspace -scheme TravisExample -sdk iphonesimulator ONLY_ACTIVE_ARCH = NO

为了在Travis上签名我们的应用,我们必须创建所有必要的证书和配置文件。

在此示例中,我们已使用分发证书来生成生产IPA,如果要生成Development(Debug)IPA文件,则可以使用开发证书。

1.苹果全球开发者关系认证中心

从Apple页面下载或从钥匙串导出。 将其保存在脚本/certs/apple.cer下的项目中。

2. iPhone发行证书+私钥

如果您还没有一个新的发行证书,请创建一个。 为此,请转到您的Apple开发者帐户,并按照以下步骤为生产创建新证书(证书>生产>添加> App Store和Ad Hoc)。 确保下载并安装证书。 之后,您应该在带有附加私钥的钥匙串中找到它。 在Mac上打开应用程序“钥匙串访问”:

右键单击项目,然后选择“导出…”,将证书导出到scripts / certs / dist.cer中。 然后导出私钥并将其保存到scripts / certs / dist.p12中。 输入您选择的密码。 由于Travis需要知道此密码,因此我们必须将其存储在某个地方。 当然,我们不想将其另存为纯文本。 但是我们可以利用Travis安全环境变量。 打开终端,然后浏览到包含“ .travis.yml”的项目文件夹。 首先,让我们通过运行’ gem install tr​​avis’来安装Travis gem。 之后,您可以通过执行以下命令添加密码:

  travis加密“ KEY_PASSWORD = {密码}”-添加 

这会将加密的环境变量KEY_PASSWORD添加到您的.travis.yml。 然后可以在Travis CI执行的任何脚本中使用它。

我们还可以通过使用Travis帐户设置页面来实现此目的:添加必需的变量及其值,Travis将所有变量加密为隐藏的环境变量:

3. iOS供应配置文件(分发)

如果尚未创建新的分发配置文件。 根据您的帐户,您可以创建“临时”或“内部”配置文件(“配置文件”>“分发”>“添加”>“临时或内部”)。 下载并保存在脚本/配置文件/下。

由于需要从Travis访问此配置文件,因此必须将名称存储为全局环境变量。 将其添加到.travis.yml全局环境变量部分。 例如,如果文件名是TravisExample_Ad_Hoc.mobileprovision,则添加以下内容:

 环境: 
全球:
-APP_NAME =“ TravisExample”
-'DEVELOPER_NAME =“ iPhone发行版:{您的名字}({code})”'
-PROFILE_NAME =“ TravisExample_Ad_Hoc”

声明了两个以上的环境变量。 APP_NAME(第3行)通常与您的主要目标名称相同。 DEVELOPER_NAME(第4行)是您在“代码签名身份”>“发布”下检查主要目标的XCode Build Settings时看到的内容。 搜索您的应用程序的临时或内部配置文件。 以黑色字母表示文本部分。 根据您的设置,它可能会或可能不会在方括号中包含代码。

如果您的GitHub项目是公开的,则您可能希望对证书和配置文件进行加密,因为它们包含敏感数据。 如果您有私有存储库,则可以继续进行下一部分。

首先,我们必须提供一个密码来加密所有文件(机密)。 在我们的示例中,让我们选择“ foo”,但是您应该为您的项目提供一个更安全的密码。 在命令行上,使用openssl加密所有三个敏感文件:

  openssl aes-256-cbc -k“ foo”-输入脚本/配置文件/TravisExample_Ad_Hoc.mobileprovision-输出脚本/profile/TravisExample_Ad_Hoc.mobileprovision.enc -aopenssl aes-256-cbc -k“ foo”-输入脚本/证书/ dist .cer -out脚本/证书/dist.cer.enc -aopenssl aes-256-cbc -k“ foo” -in脚本/证书/dist.p12 -out脚本/certs/dist.p12.enc -a 

这将创建以.enc结尾的文件的加密版本。 现在,您可以删除或忽略原始文件。 至少,请确保不要提交它们,否则它们将显示在GitHub上。 如果您不小心犯了或已经推了它们,请寻求帮助。

现在我们的文件已加密,我们需要告诉Travis重新对其进行解密。 为此,特拉维斯需要这个秘密。 我们使用与KEY_PASSWORD相同的方法:

  travis加密“ ENCRYPTION_SECRET = foo” --add 

最后,我们必须告诉Travis要解密哪些文件。 将以下命令添加到.travis.yml中的脚本之前阶段:

  before_script:-openssl aes-256-cbc -k“ $ ENCRYPTION_SECRET” -in脚本/配置文件/TravisExample_Ad_Hoc.mobileprovision.enc -d -a -out脚本/profile/TravisExample_Ad_Hoc.mobileprovision- openssl aes-256-cbc -k“ $ ENCRYPTION_SECRET“-在脚本/证书/dist.cer.enc -d -a -out脚本/证书/dist.cer- openssl aes-256-cbc -k” $ ENCRYPTION_SECRET“-在脚本/certs/dist.p12.enc -d -a -out脚本/证书/dist.p12 

这样,您在GitHub上的文件将受到保护,而Travis仍然可以读取和使用它们。 您只需要了解一个安全问题:您可以(偶然)在Travis构建日志中公开一个解密的环境变量。 但是请注意,拉取请求禁用了解密。

添加脚本

现在,我们必须确保将证书导入到Travis CI钥匙串中。 为此,我们应该在scripts文件夹中添加一个新文件add-key.sh

 #!/ bin / sh#创建自定义钥匙串 
安全性create-keychain -p travis ios-build.keychain#将自定义钥匙串设为默认,因此xcodebuild将使用它进行签名
安全性默认钥匙串-s ios-build.keychain#解锁钥匙串
安全解锁密钥链-p travis ios-build.keychain#对于长构建,将密钥链超时设置为1小时
#参见http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/
安全性set-keychain-settings -t 3600 -l〜/ Library / Keychains / ios-build.keychain#将证书添加到钥匙串中并允许codesign访问它们
安全导入./scripts/certs/apple.cer -k〜/ Library / Keychains / ios-build.keychain -T / usr / bin / codesign
安全导入./scripts/certs/dist.cer -k〜/ Library / Keychains / ios-build.keychain -T / usr / bin / codesign
安全导入./scripts/certs/dist.p12 -k〜/ Library / Keychains / ios-build.keychain -P $ KEY_PASSWORD -T / usr / bin / codesignsecurity set-key-partition-list -S apple-tool :,苹果:-s -k travis ios-build.keychain#将供应配置文件放置到位
mkdir -p〜/ Library / MobileDevice / Provisioning \ Profilescp“ ./scripts/profile/$PROFILE_NAME.mobileprovision”〜/ Library / MobileDevice / Provisioning \ Profiles /

在这里,我们创建了一个名为ios-build的新临时钥匙串 ,它将包含所有证书,并确保已准备好用于代码签名。 请注意,我们在此处使用$ KEY_PASSWORD导入私钥。 最后一步,将移动供应配置文件复制到“库”文件夹中。

创建此文件后,请确保授予其可执行权限。 在命令行上,输入chmod a + x scripts / add-key.sh 。 您还必须针对以下脚本执行此操作。

更新捆绑包详细信息

要更新诸如Bundle VersionBundle IdentifierBundle Display Name之类的包详细信息,我们应该在scripts文件夹中添加一个新文件update-bundle.sh

  #!/ bin / shif [!  -z“ $ INFO_PLIST”]; 然后 
/ usr / libexec / PlistBuddy -c“设置:CFBundleVersion $ TRAVIS_BUILD_NUMBER”“ $ INFO_PLIST”
回声“设置CFBundleVersion为$ TRAVIS_BUILD_NUMBER” fiif [! -z“ $ BUNDLE_IDENTIFIER”]; 然后
/ usr / libexec / PlistBuddy -c“设置:CFBundleIdentifier $ BUNDLE_IDENTIFIER”“ $ INFO_PLIST”
echo“将CFBundleIdentifier设置为$ BUNDLE_IDENTIFIER” fiif [! -z“ $ BUNDLE_DISPLAY_NAME”]; 然后
/ usr / libexec / PlistBuddy -c“设置:CFBundleDisplayName $ BUNDLE_DISPLAY_NAME”“ $ INFO_PLIST”
echo“将CFBundleDisplayName设置为$ BUNDLE_DISPLAY_NAME” fi

现在,所有证书和配置文件都已导入,我们可以对我们的应用程序进行签名。 请注意,我们必须先构建应用程序,然后才能对其进行签名。 由于我们需要知道构建在磁盘上的存储位置,因此我建议通过在build命令中声明OBJROOT和SYMROOT来指定输出文件夹。 另外,我们应该通过将SDK设置为iphoneos并将配置设置为Release来创建发布版本:

  xcodebuild-项目TravisExample.xcodeproj-方案TravisExample -sdk iphoneos-配置版本OBJROOT = $ PWD / build SYMROOT = $ PWD / build 

如果运行此命令,则应在之后的build / Release-iphoneos文件夹中找到应用程序二进制文件。

对于调试版本,请将配置设置为“调试”而不是“发行版”。 之后,您应该在build / Debug-iphoneos文件夹中找到应用程序二进制文件。

在导出存档并生成实际IPA之前,我们需要提供一个包含导出配置选项的导出选项plist文件。 让我们在脚本中的脚本/exportOptions-Enterprise.plist中创建以下内容:

   


compileBitcode

方法
企业
teamID
您的团队ID
uploadBitcode

uploadSymbols


注意:如果在创建plist时遇到任何困难或错误,只需使用Xcode从本地计算机生成IPA文件。 您将看到ExportOptions.plist以及应用程序的.ipa。 您可以将ExportOptions.plist中的内容复制到exportOptions-Enterprise.plist

现在我们已经准备好了plist,我们可以对其进行签名并创建实际的IPA文件。 为此,我们应该在scripts文件夹中添加一个新文件sign-and-upload.sh

  #!/ bin / sh 
#存档应用程序xcodebuild \
-workspace IMSApp.xcworkspace \
-方案“ $ SCHEME” \
-sdk“ iphoneos”
-archivePath“ $ OUTPUTDIR / $ APP_NAME.xcarchive” \
配置发布
PROVISIONING_PROFILE =“ $ PROVISIONING_PROFILE” \
archive#将存档导出到ipa
xcodebuild \
-exportArchive \
-archivePath“ $ OUTPUTDIR / $ APP_NAME.xcarchive” \
-exportOptionsPlist“脚本/exportOptions-Enterprise.plist” \
-exportPath“ $ OUTPUTDIR”

最后一个脚本将再次删除临时钥匙串,并删除移动供应配置文件。 它不是真正必要,但在本地测试时会有所帮助。 为此,我们应该在scripts文件夹中添加一个新文件remove-key.sh

  #!/ bin / shsecurity delete-keychain ios-build.keychain 
rm -f“〜/ Library / MobileDevice / Provisioning Profiles / $ PROFILE_NAME.mobileprovision”

最后一步,我们必须告诉Travis什么时候执行这三个脚本。 密钥应在构建应用程序之前添加,签名和清理应在之后进行。 在.travis.yml中添加/替换以下步骤:

 语言:Objective-C 
osx_image:xcode9.3分支机构:
只要:
-masterenv:
全球:
-APP_NAME =“ TravisExample”
-'DEVELOPER_NAME =“ iPhone发行版:{您的名字}({code})”'
-PROFILE_NAME =“ TravisExample_Ad_Hoc”
-PROVISIONING_PROFILE =“ $ HOME / Library / MobileDevice / Provisioning Profiles / $ PROFILE_NAME.mobileprovision”
-OUTPUTDIR =“ $ PWD / build / Release-iphoneos” before_script:
-openssl aes-256-cbc -k“ $ ENCRYPTION_SECRET”-输入脚本/配置文件/TravisExample_Ad_Hoc.mobileprovision.enc -d -a-输出脚本/配置文件/TravisExample_Ad_Hoc.mobileprovision
-openssl aes-256-cbc -k“ $ ENCRYPTION_SECRET”-输入脚本/证书/dist.cer.enc -d -a-输出脚本/证书/dist.cer
-openssl aes-256-cbc -k“ $ ENCRYPTION_SECRET”-输入脚本/证书/dist.p12.enc -d -a-输出脚本/证书/dist.p12
-“ ./scripts/add-key.sh”
-“ ./scripts/update-bundle.sh”之前安装:
-gem install cocoapods --pre --no-rdoc --no-ri --no-document --quietscript:
-设置-o pipefail
-xcodebuild -version
-xcodebuild -showsdks
-xcodebuild -project TravisExample.xcodeproj -scheme TravisExample -sdk iphoneos-配置发行版OBJROOT = $ PWD / build SYMROOT = $ PWD / buildafter_script:
-“ ./scripts/remove-key.sh”之后成功:
-“ ./scripts/sign-and-upload.sh”

完成后,我们可以将所有内容推送到GitHub,并等待Travis对我们的应用程序进行签名。 我们可以通过调查项目页面上的Travis控制台来验证它是否有效。 如果一切正常,我们可以看看如何将应用程序分发到GitHub版本。

要设置标签, 在脚本文件夹中添加新文件set_tags.sh

  BRANCH =“ master” if [“ $ TRAVIS_BRANCH” =“ $ BRANCH”]; 然后 
如果[“ $ TRAVIS_PULL_REQUEST” = false]; 然后
如果[-z“ $ TRAVIS_TAG”]; 然后
echo -e“开始标记提交。\ n” git config --global user.email“ travis@travis-ci.org”
git config --global user.name“ Travis” git config --global push.default简单git remote set-url origin https:// $ {GH_TOKEN} @ github.com / GitHub帐户名/repo.git#添加标签和推向高手。
git tag -av $ {TRAVIS_BUILD_NUMBER} -m“ Travis构建$ TRAVIS_BUILD_NUMBER已推送标签。”
git push origin-标签
git fetch origin echo -e“完成带有标签的魔术。\ n” fi
科幻
科幻

要将IPA文件部署到GitHub Releases,并在IPA文件的名称后附加Travis内部版本号,您需要在.travis.yml文件中编写以下脚本。

  before_deploy:-ls -al ./build/Release-iphoneos/*.ipa 
-mv ./build/Release-iphoneos/TravisExample.ipa ./build/Release-iphoneos/TravisExample-v$TRAVIS_BUILD_NUMBER.ipa
-“ ./scripts/set_tags.sh”部署:
提供者:发布
api_key:
安全:$ {GH_TOKEN}
文件:
-“ ./build/Release-iphoneos/TravisExample-v$TRAVIS_BUILD_NUMBER.ipa”
skip_cleanup:是
上:
repo:GitHub Repo的名称

在上面的脚本GH_TOKEN中是“ GITHUB OAUTH TOKEN”。

确保将“ skip_cleanup”设置为true,否则Travis CI将删除在构建过程中创建的所有文件,这可能会删除您尝试上传的文件。

要为Travis CI组织GitHub存储库,您可以从https://github.com/MattesGroeger/TravisExample-iOS获取参考

在此博客中,我从https://www.objc.io/issues/6-build-tools/travis-ci/和https://medium.com/@atsakiridis/continuous-deployment-for-ios中获取了参考-using-travis-ci-55dcea342d9(我将这两个博客结合在一起编写了此博客,并添加了一些要点,这些内容涵盖了从Travis CI到GitHub Releases部署IPA文件)。