We have these environment variables
within the Xcode Scheme
Which works well locally with this code
let webHost = ProcessInfo.processInfo.environment["HOST_URL"]!
let apiHost = ProcessInfo.processInfo.environment["API_URL"]!
let beamsKey = ProcessInfo.processInfo.environment["BEAMS_KEY"]!
let mixpanelKey = ProcessInfo.processInfo.environment["MIXPANEL_KEY"]!
However, when deploying using Xcode Cloud with the same environment variables
.
It succeeds in building, but the app crashes with this log.
What is the right way to read these environment variables when using Xcode Cloud?
So, this was an absolute headache but I finally figured out a satisfactory way to access and use these variables in code.
My solution uses:
ci_pre_xcodebuild.sh
file to write the environment variables in the JSON(at: YourProject/SupportingFiles/secrets.json)
{
"STRIPE_KEY": "",
"GOOGLE_MAPS_KEY": "",
"GOOGLE_PLACES_KEY": "",
"BASE_URL": "https://dev.api.example.fr"
}
In this screenshot you can see that I've duplicated the keys for different environments. I didn't expand on this for the sake of brevity, but you can definitely have different secrets JSON files for different Xcode Scheme configurations.
ci_pre_xcodebuild.sh
fileImportant: the name of the files and their position matter.
The goal here is to add a script that the CI (Xcode Cloud) will execute each time it builds. In this script, we're going to create and fill our JSON.
In this group, add a new file called ci_pre_xcodebuild.sh
Write the following:
#!/bin/sh
echo "Stage: PRE-Xcode Build is activated .... "
# Move to the place where the scripts are located.
# This is important because the position of the subsequently mentioned files depend of this origin.
cd $CI_PRIMARY_REPOSITORY_PATH/ci_scripts || exit 1
# Write a JSON File containing all the environment variables and secrets.
printf "{\"STRIPE_KEY\":\"%s\",\"GOOGLE_MAPS_KEY\":\"%s\",\"GOOGLE_PLACES_KEY\":\"%s\",\"BASE_URL\":\"%s\"}" "$STRIPE_KEY" "$GOOGLE_MAPS_KEY" "$GOOGLE_PLACES_KEY" "$BASE_URL" >> ../Dream\ Energy/SupportingFiles/Secrets.json
echo "Wrote Secrets.json file."
echo "Stage: PRE-Xcode Build is DONE .... "
exit 0
Of course, you need to change this text depending on your keys and the location of the file. I added a few keys as an example.
chmod +x ci_pre_xcodebuild.sh
. This fixes a warning in Xcode Cloud.import Foundation
struct Secrets {
private static func secrets() -> [String: Any] {
let fileName = "Secrets"
let path = Bundle.main.path(forResource: fileName, ofType: "json")!
let data = try! Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
return try! JSONSerialization.jsonObject(with: data) as! [String: Any]
}
static var baseURL: String {
return secrets()["BASE_URL"] as! String
}
static var stripeKey: String {
return secrets()["STRIPE_KEY"] as! String
}
}