iOS CI (Jenkins + Phabricator + Slack)

Install Jenkins with brew install jenkins in the shell

Then start Jenkins, enter 127.0.0.1:8080 in the browser

Install the xcode related plugins in Jenkins

The steps are available in other blogs, Google ā€œios ci continuous integrationā€œ, for example:

The versions may be a bit outdated, but it should do.

For our use, we have Phabricator installed locally on a Mac instead of a server since itā€™s an iOS project, so setting up the private key is sufficient. We donā€™t need to worry about Jenkins and Phabricator callback interaction.

In addition, we encountered several problems:

jenkins.plugins.slack.ActiveNotifier hudson.model.listeners npe

Sending test messages worked fine.

I spent two hours trying to resolve it, but I didnā€™t know what the problem was. After a good nightā€™s sleep, it was back to normal the next dayā€¦

It seems that I know the reason now, the Project Channel canā€™t be empty.

ResourceRules.plist

On the first day, it complained that ResourceRules.plist was incorrect, so I added it to both the project and Jenkins configuration.

Custom xcodebuild arguments $(SDKROOT)/ResourceRules.plist

The next day, it complained that it couldnā€™t find ResourceRules.plist, but removing it in Jenkins made it work. Really strange.

iPhone Developer: no identity found

swift-stdlib-tool failed with exit code 1

I downloaded various certificates from developer.apple.com, but none of them worked.

Without any other options, I directly opened the project under ~/.jenkins/jobs/**** with Xcode to compare. I found that there was an additional certificate in the keychain, and then it succeeded.


Also, we havenā€™t purchased the enterprise account yet, and Jenkins doesnā€™t have an account system, so we continue to wait for the pit.

DUNS (Dun & Bradstreet Number)

The enterprise account was stuck here before, and Appleā€™s email response was delayed, so we must call Apple customer service. It was resolved within one or two days.

Bundle Identifier

Previously, the company account had occupied .alpha and .beta, and the enterprise account couldnā€™t create the same certificate. So I had to either delete the original account or change the ID.

When I tried to delete it, I realized that the app needed to be in a few specific states. Official documentation: TransferringAndDeletingApps

Since beta was already used for TestFlight and it hadnā€™t been uploaded to the App Store, I emailed Apple and got the following response:

Currently, your app does not have at least one approved version.

ā€¦

So I had to change the ID.

Over-the-Air Distribution

I finished all the preparations and quickly exported it, but I found that after Xcode 6, exporting an IPA only gave me an .ipa file without an accompanying .plist file. I had to write it myself (fortunately, Jenkins can generate it automatically). It looks something like this: plist (change the corresponding value in the $ $ placeholders)

Then, $ python -m SimpleHTTPServer, open it with Safari on the iPhone, butā€¦ it still didnā€™t workā€¦

Later, I found out that the server must be httpsā€¦

Build Number

targets -> Build Phases -> + New Run Script Phase

1
2
3
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

In this way, when the scheme is release, the build will automatically increment by 1.

PS:

Actually, this can be written in the shell of the Jenkins build step, then push it to origin/master and upload the *.ipa file to the server.

OS X Server

Pit, I will organize it when I have time.

DistributionProvisioningProfiles

Directly specifying the path for the downloaded *.mobileprovision file didnā€™t work, so I had to manually package it.

1
2
3
xcodebuild -exportArchive -exportFormat IPA -archivePath "$Yourarchive" \
-exportPath imeican-Beta-xcodebuild.ipa \
-exportProvisioningProfile $YourDistributionProvisioningProfiles

Summary:

It was a path full of pits.

Translated by gpt-3.5-turbo