Goal โ one button Xcode builds with Xcode Server or XCS
Do you have CI or Continuous Integration for your applications built with Xcode? There are plenty to choose from and they have their advantages. But consider Xcode Server Bots built directly into Xcode: there is nothing to install and your project can be up and running in a matter of minutes.
We all want simple builds. If you are able to check your code into a git
repo, then it should be able to git pull
and build in small number of steps. If you can minimize the number of dependencies to be installed or to be fetch
ed, then your builds will be more repeatable. More repeatable; possibly better quality. More repeatable; prime for automation with Xcode Server Bots.
Many Open Source Xcode projects already have a CI architecture. But if you want to learn the code or achieve one button Xcode builds, then you would have to install or learn a new dependency. Xcode Server Bots can still be used in this case.
The Xcode Server Bots documentation makes the compelling case to use Bots. The documentation on Continuous integration using Xcode Server from Apple is the best resource for setting up your Xcode Server Bots.
In Xcode, continuous integration is the process of automating and streamlining the building, analyzing, testing, and archiving of your Mac and iOS apps, in order to ensure that they are always in a releasable state. [1] The goal of continuous integration is to improve software quality, and there are a number of ways this is achieved:
- Catching problems quickly, easily, and early.
- Enhancing collaboration.
- Broadening test coverage.
- Generating build and test statistics over time.
- [1] : https://developer.apple.com/library/archive/documentation/IDEs/Conceptual/xcode_guide-continuous_integration/index.html
- [2] : https://developer.apple.com/search/?q=xcode%20server&type=Videos
- Xcode Server Environment Variable Reference
- Xcode Server API Reference
This repo includes CI scripts for use in Xcode Continuous Integration Bots. Also useful for manual builds. Support for carthage
for fetching binaries. If you CocoaPods, you can still use this repo. It's likely you can still use this as you will likely be using the CocoaPods .xcworkspace
, which this can still be integrated into.
Add this repo as a git submodule
. The directory name it creates will be xcode-continuous-integration
and the shell scripts will be in that directory.
# Add repo to the current directory
git submodule add https://github.com/roblabs/xcode-continuous-integration.git
Edit Scheme
> Build
> Pre-Actions
> Run Script
> Add the following (assuming the proper path relative to your ${PROJECT_DIR}
)
cd ${PROJECT_DIR}
git submodule update --init --recursive
wait
sh ${PROJECT_DIR}/xcode-continuous-integration/ci.sh
Let's take the special case of building Mapbox GL Native for iOS. See the examples
folder for scripts for setting up XCS
with
mapbox-gl-native-ios
, versions <= v5.9mapbox-gl-native-ios
, versions > 6.0
- The Git branch and Xcode scheme you want to test is very important, so check out a local copy to your development folder. For example, set the branch you want and perform the initial step to make the Xcode Project.
mapbox-gl-native-ios
, versions <= v5.9
git clone --branch ios-v5.9.0 \
https://github.com/mapbox/mapbox-gl-native-ios.git \
tmp/mapbox-gl-native-ios
cd tmp/mapbox-gl-native-ios
make iproj
mapbox-gl-native-ios
, versions > 6.0, or master
git clone \
https://github.com/mapbox/mapbox-gl-native-ios.git \
tmp/mapbox-gl-native-ios
cd tmp/mapbox-gl-native-ios
make iproj
- The call to
make iproj
will automatically open the Xcode Project on your development Mac.
- Change the Scheme to
CI
, which is already configured in the source for CI. On your development Mac, chooseProduct
>Create Bot
. - Add Pre-Integration Triggers
environment
- Git repo metadata & Build versions- project specific build commands - for your version of
mapbox-gl-native-ios
- Example Data is generated from a project that makes use of these scripts on GitHub, roblabs / openmaptiles-ios-demo
Project & Development Environment `metadata` ๐ค
Sat Sep 19 13:35:34 PDT 2020
PROJECT_DIR = /Users/roblabs/Documents/github/roblabs/openmaptiles-ios-demo/tmp/openmaptiles-ios-demo
gitBranch = master
gitSHA = aaa53c24cce044e2e2fbfc49b56bd83d825b969d
CURRENT_PROJECT_VERSION = 0
MARKETING_VERSION = 1.341.0
DEVELOPMENT_TEAM = R7O3BWLEA8BS
PREBUILD_LOG = /Users/roblabs/Documents/github/roblabs/openmaptiles-ios-demo/tmp/openmaptiles-ios-demo/prebuild.log
ProductName: Mac OS X
ProductVersion: 10.15.6
BuildVersion: 19G2021
Xcode 11.7
Build version 11E801a
If built using Xcode Server Bots, then log several key XCS_
environment variables. See Apple's Xcode Server Environment Variable Reference.
Example Xcode Server Environment Variables ๐ค
XCS = 1
XCS_BOT_NAME = OSM2VectorTiles Bot
XCS_BOT_ID = drb3o4b067dec6e781b4976604a291
XCS_BOT_TINY_ID = CB1D194
XCS_INTEGRATION_ID = drb3o4b067dec6e781b4976604a291
XCS_INTEGRATION_TINY_ID = R698E33
XCS_INTEGRATION_NUMBER = 4
XCS_INTEGRATION_RESULT = unknown
XCS_SOURCE_DIR = /Users/roblabs/Library/Caches/XCSBuilder/Bots/drb3o4b067dec6e781b4976604a291/Source
XCS_OUTPUT_DIR = /Users/roblabs/Library/Caches/XCSBuilder/Integration-drb3o4b067dec6e781b4976604a291
XCS_DERIVED_DATA_DIR = /Users/roblabs/Library/Caches/XCSBuilder/Bots/drb3o4b067dec6e781b4976604a291/DerivedData
XCS_XCODEBUILD_LOG = /Users/roblabs/Library/Caches/XCSBuilder/Integration-drb3o4b067dec6e781b4976604a291/xcodebuild.log
INTEGRATION_URL = https://roblabs.local/xcode/bots/CB1D194/integrations/R698E33
# Log data generated from this script: ci.sh
PREBUILD_LOG = /Users/roblabs/Library/Caches/XCSBuilder/Bots/drb3o4b067dec146e781b4976604a291/Source/openmaptiles-ios-demo/prebuild.RB1A194.4.log
You can also log some interesting URL's from the Xcode Server API Reference
Example Xcode Server URLs ๐ค
http://Bots JSON = https://oldSanJuan.local:20343/api/bots
http://bots/latest = https://oldSanJuan.local/xcode/bots/latest
http://latest this bot = https://oldSanJuan.local/xcode/bots/latest/EC6DB3B
http://Integration JSON = https://oldSanJuan.local/xcode/internal/api/integrations/771613596b2cdb2a24eaa2108be1b1
http://Download = https://oldSanJuan.local/xcode/internal/api/integrations/771613596b2cdb2a24eaa2108be1b1/assets
xcbot://See Bot in Xcode = xcbot://oldSanJuan.local/botID/dcb3a48067dec1e781b49766016a8f/integrationID/771613596b2cdb2a24eaa2108be1b1
How to add the XCS
integration or build number into your Xcode project.
- XCS builds will automatically update the build number
- Example, If you are doing a non
XCS
build with the following values for current & marketing version then,- The variable
${XCS_INTEGRATION_NUMBER}
will be""
or null. - Local builds version will be
1.278.314
with a build number of314
- An example
XCS
build version for the 101 st build will be 1.278.314101 with a build number of 314101.
- The variable
- To acheive this, hand edit all instances in file
<project>.xcodeproj/project.pbxproj
. It is not possible to do this in Xcode directly.
CURRENT_PROJECT_VERSION = "314${XCS_INTEGRATION_NUMBER}";
MARKETING_VERSION = "1.278.314${XCS_INTEGRATION_NUMBER}";
You can use XCS
with open source projects and apply your own signing credentials for deploying to devices in your local lab. See the file ExportOptions.plist
.
Configuration
>Archive
>Use Custom Export Options Plist
When you apply a proper ExportOptions.plist
, then you can
Install on device...
Show in Organizer...
Viewing ExportOptions.plist
in Xcode
Documentation for the Export Options can be found by typing:
xcodebuild -h
Here are some of those settings after running the online documentation for these settings. You can review Apple Technical Note TN2339 for more information.
destination
: String
Determines whether the app is exported locally or uploaded to Apple. Options are
export
orupload
. The available options vary based on the selected distribution method. Defaults toexport
.
method
: String
Describes how Xcode should export the archive. Available options:
app-store
,validation
,ad-hoc
,package
,enterprise
,development
,developer-id
, andmac-application
. The list of options varies based on the type of archive. Defaults todevelopment
.
signingStyle
: String
The signing style to use when re-signing the app for distribution. Options are
manual
orautomatic
. Apps that were automatically signed when archived can be signed manually or automatically during distribution, and default to automatic. Apps that were manually signed when archived must be manually signed during distribution, so the value of signingStyle is ignored.
stripSwiftSymbols
: Bool
Should symbols be stripped from Swift libraries in your IPA? Defaults to YES.
teamID
: String
The Developer Portal team to use for this export. Defaults to the team used to build the archive.
uploadBitcode
: Bool
For App Store exports, should the package include bitcode? Defaults to YES.
uploadSymbols
: Bool
For App Store exports, should the package include symbols? Defaults to YES.