For my personal project, I am using Circle.ci to test and deploy the OSX application (with upload hook to S3, to distribute it outside the AppStore - using the signed with Developer ID distribution method). I am using FastLane to build the app, which works flawlessly when building it from my local terminal, but I cannot get past code signing step when using the CI server.
The issue is very simple, the keychain does not import the provision profile, which I can tell from the pre-build step:
1 key imported.
No provisioning profiles found in repository.
You must add a provisioning profile to your repository
to enable CircleCI code-signing support.
Currently installed Code-Signing identities:
Policy: Code Signing
Matching identities
0 identities found
Valid identities only
0 valid identities found
I have my .p12 with private key and certificate uploaded to the repository, no issue there. I have also added the .provisionprofile to the repository (root, even different locations) but to no avail. The documentation states (https://circleci.com/docs/ios-code-signing/) that there is a need for .mobileprovision, but that only covers the iOS, not the OSX, while the system should be nearly identical so I assumed that would work as well.
So the TLDR question is: How do I import the provisioning profile of the OSX distribution on the Circle.CI, so the keychain accepts the entry? Or is there a way around it - like skipping the signing step (disabling it in XCode) and signing it by hand with some .sh?
Thanks everyone!
I am sharing my experience of deploying iOS app to Testflight using CircleCI. Maybe this helps.
Put the provision profile file in the root of your project directory. Make sure it is a normal "Distribution Profile" not a App Store submission profile.
Just add the .p12 key in the project settings of CircleCI. Remove all other certificates / .p12 file from the repository.
I tried using fastlane to build and distribute the build but it was failing in CircleCI. I had these three steps in my Fastfile beta environment.
increment_build_number
gym(scheme: "myScheme”)
pilot
I changed that to just
increment_build_number
My Circle CI file
machine:
environment:
GYM_CODE_SIGNING_IDENTITY: "iPhone Distribution: Company Name (XXXXXX)"
xcode:
version: "8.0"
test:
override:
- set -o pipefail && xcodebuild -workspace 'my.xcworkspace' -scheme 'myscheme' clean build test -sdk iphonesimulator -destination 'id=AC291080-8EFE-4095-8C55-B1E952EFFC36' CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= PROVISIONING_PROFILE=
dependencies:
pre:
- gem update fastlane
deployment:
beta_distribution:
branch: master
commands:
- fastlane beta
- gym --scheme "myscheme" --workspace "my.xcworkspace" --export_method app-store --use_legacy_build_api false
- pilot upload
With the release of Xcode 8, Apple introduced a new way of managing the signing configuration. Now you have two options Manual and Automatic.
According to the WWDC 2016 Session about Code signing (WWDC 2016 - 401 - What's new in Xcode app signing), when you select Automatic signing, Xcode is going to:
Create signing certificates
Create and update App IDs
Create and update provisioning profiles
But according to what Apple says in that session, the Automatic Signing is going to use Development signing and will be limited to Xcode-created provisioning profiles.
The issue comes when you try to use Automatic Signing on a CI environment (like Travis CI or Jenkins). I'm not able to figure out an easy way to keep using Automatic and sign for Distribution (as Xcode forces you to use Development and Xcode-created provisioning profiles).
The new "Xcode-created provisioning profiles" do not show up in the developer portal, although I can find then in my machine... should I move those profiles to the CI machine, build for Development and export for Distribution? Is there a way to override the Automatic Signing using xcodebuild?
I basically run into the same issue using Jenkins CI and the Xcode Plugin.
I ended up doing the build and codesigning stuff myself using xcodebuild.
0. Prerequisites
In order to get the following steps done successfully, you need to have installed the necessary provisioning profiles and certificates. That means your code signing should already be working in general.
1. Building an .xcarchive
xcodebuild -project <path/to/project.xcproj> -scheme <scheme-name> -configuration <config-name> clean archive -archivePath <output-path> DEVELOPMENT_TEAM=<dev-team-id>
DEVELOPMENT_TEAM: your 10 digit developer team id (something like A1B2C3D4E5)
2. Exporting to .ipa
xcodebuild -exportArchive -archivePath <path/to/your.xcarchive> -exportOptionsPlist <path/to/exportOptions.plist> -exportPath <output-path>
Example of an exportOptions.plist:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>development</string>
<key>teamID</key>
<string> A1B2C3D4E5 </string>
</dict>
</plist>
method: is one of development, app-store, ad-hoc, enterprise
teamID: your 10 digit developer team id (something like A1B2C3D4E5)
This process is anyway closer to what you would do with Xcode manually, than what for example the Jenkins Xcode Plugin does.
Note: The .xcarchive file will always be develpment signed, but selecting "app-store" as method in the 2nd step will do the correct distribution signing and also include the distribution profile as "embedded.mobileprovision".
Hope this helps.
After trying a few options, these are the solutions that I was able to use on my CI server:
Include the Developer certificate and private key as well as the auto generated provisioning profiles in the CI environment:
Using Automatic signing forces you to use a Developer certificate and auto-generated provisioning profiles. One option is to export your development certificate and private key (Application -> Utilities -> Keychain Access) and the auto-generated provisioning profiles to the CI machine. A way to locate the auto-generated provisioning profiles is to navigate to ~/Library/MobileDevice/Provisioning\ Profiles/, move all files to a backup folder, open Xcode and archive the project. Xcode will create auto-generated development provisioning profiles and will copy them to the Provisioning Profiles folder.
xcodebuild archive ... will create a .xcarchive signed for Development. xcodebuild -exportArchive ... can then resign the build for Distribution
Replace 'Automatic' with 'Manual' when building on a CI environment
Before calling xcodebuild a workaround is to replace all instances of ProvisioningStyle = Automatic with ProvisioningStyle = Manual in the project file. sed can be used for a simple find an replace in the pbxproj file:
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' <ProjectName>.xcodeproj/project.pbxproj
#thelvis also created a Ruby script to do this using the xcodeproj gem. The script gives you a better control over what is changed.
xcodebuild will then use the code signing identity (CODE_SIGN_IDENTITY) set in the project, as well as the provisioning profiles (PROVISIONING_PROFILE_SPECIFIER). Those settings can also be provided as parameters to xcodebuild and they will override the code signing identity and/or provisioning profile set in the project.
EDIT: with Xcode 9, xcodebuild has a new build settings parameter CODE_SIGN_STYLE to select between Automatic and Manual so there's no need to find and replace instances of automatic with manual in the project file, more info in WWDC 2017 Session 403 What's New in Signing for Xcode and Xcode Server
Switch to manual signing
Manual signing will provide total control over the code signing identities and provisioning profiles being used. It's probably the cleanest solution, but with the downside of losing all the benefits of Automatic signing.
To learn more about code signing with Xcode 8 I really recommend this article as well as the WWDC2016 session 401 - What's new in Xcode app signing
I'm considering another option I've not seen mentioned here yet. Setup two identical targets, that only differ in their signing settings.
Development Target uses automatic signing to get all of those benefits when new devices / developers are added
CI Target uses manual signing
Downside is that you would have to manage two identical targets. Upside is that get the benefits of automatic signing for development, and don't have to maintain potentially brittle scripts that modify your project just before build time.
If you are using Xcode 8.x and Jenkins for CI. Then probably you would face issue with "Signing for “YourProjectName" requires a development team. Select a development team in the project editor.
Code signing is required for product type 'Application' in SDK 'iOS 10.1’”.** BUILD FAILED ** when running the job.
What is the solution?.
Solution is:
set Provisioning profile to None in Xcode project build settings.
In jenkins, Create a execute shell before the Xcode setting and write the below command
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/' ProjectName.xcodeproj/project.pbxproj
Remember: keep that execute shell before Xcode settings in Build section of jenkins.
This works.
There is one more way to workaround nonfunctional signing in CI/CD pipeline when the signing specified in the target (or project) fails.
We use automatic signing for our apps to have a good developer experience, and in CI/CD only signing is done in the last step when .ipa is produced.
Produce an unsigned .xcarchive
xcodebuild -workspace Runner.workspace CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO <more parameters follow>
Sign the final .ipa file with configuration in exportOptions.plist
xcodebuild -exportArchive -archivePath <.xcarchive> -exportOptionsPlist <exportOptions.plist> -exportPath <output-path>
For me, nothing worked. I solved my problem by changing a file in Xcode app installed on your Mac Mini (CI server with Jenkins), as shown in this link:
https://www.jayway.com/2015/05/21/fixing-your-ios-build-scripts/
Additionally I turned off automatic signing from Xcode.
All done! Finally works!
I noticed my Unity build was never adding a ProvisioningStyle key to my XCode project. I then found a way to manually add the ProvisioningStyle by using a "PostProcessBuild" build script. i.e. a unit of code that is called after the IOS XCode project has been built by Unity.
First I had a look at what the project.pbxproj file should look like - when it is set to Manual Provisioning:
/* Begin PBXDictionary section */
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
TargetAttributes = {
1D6058900D05DD3D006BFB54 /* Unity-iPhone */ = {
ProvisioningStyle = Manual;
};
5623C57217FDCB0800090B9E /* Unity-iPhone Tests */ = {
TestTargetID = 1D6058900D05DD3D006BFB54 /* Unity-iPhone */;
};
};
};
Then I created my code to replicate the "structure" of the file seen above. (using the XCodeEditor project found here: XCodeEditor)
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
// Create a new project object from build target
XCProject project = new XCProject(path);
if (target == BuildTarget.iOS)
{
//Add Manual ProvisioningStyle - this is to force manual signing of the XCode project
bool provisioningSuccess = AddProvisioningStyle(project, "Manual");
if (provisioningSuccess)
project.Save();
}
}
private static bool AddProvisioningStyle(XCProject project, string style)
{
var pbxProject = project.project;
var attr = pbxProject.data["attributes"] as PBXDictionary;
var targetAttributes = attr["TargetAttributes"] as PBXDictionary;
var testTargetIDGuid = FindValue(targetAttributes, "TestTargetID");
if (!string.IsNullOrEmpty(testTargetIDGuid))
{
var settings = new PBXDictionary();
//here we set the ProvisioningStyle value
settings.Add("ProvisioningStyle", style);
targetAttributes.Add(testTargetIDGuid, settings);
var masterTest = FindValue(targetAttributes, "ProvisioningStyle");
if (masterTest == style)
{
return true;
}
}
return false;
}
private static string FindValue(PBXDictionary targetAttributes, string key)
{
foreach (var item in targetAttributes)
{
var ma = item.Value as PBXDictionary;
foreach (var di in ma)
{
var lookKey = di.Key;
if (lookKey == key)
{
return di.Value.ToString();
}
}
}
return "";
}
What fixed it for me was this: http://code-dojo.blogspot.jp/2012/09/fix-ios-code-signing-issue-when-using.html
... copying certificates from Login keychain to System keychain.
You might also want to set all dev certificates to 'Allow all applications to access this item' (Right-click/Get Info/Access Control).
There is a tool called fastlane which makes using xcodebuild much easier and it is maintained meaning new updates will continue to provide support for changes to xcode. It makes it much easier to create scripts and config for building and codesigning your app among many other xcode automation tools it supports. I'd recommend giving it a look into.
During our iOS client build we run a clean to prevent/reduce failures. But last week all our build servers failed with this error
fatal error: malformed or corrupted AST file: 'could not find file 'worspace/file_name.h' referenced by AST file'
It seemed that file_name.h was no longer required and a developer removed the svn external which brought it in. But the AST files still held a reference to it - despite the clean.
After investigating I found it was the files in the following folder
var/folders/f3/bznwl6md2bx82f1fv_kkdzl00000gn/C/com.apple.DeveloperTools/5.0.2-5A3005/Xcode/SharedPrecompiledHeaders
Deleting SharedPrecompiledHeaders fixed the issue. At the time I manually did this.
But I'd like a way to automate it. Is there an environmental variable/alternative that can be used to find this directory? I noticed it varies between machines.
The environment variable you are looking for is SHARED_PRECOMPS_DIR
The final solution was to place the shared precomps dir within the checkout. This allowed the build servers to completely clean the workspace between builds.
Achieved this by passing in the SHARED_PRECOMPS_DIR to xcodebuild.
e.g.
xcodebuild -project ProjectName -target "Target" -configuration Configuration -sdk SDKName SHARED_PRECOMPS_DIR=/absolute/path/to/checkout
By passing this value in at the command line the SHARED_PRECOMPS_DIR was set for all projects. i.e. Including Dependent Projects.
Lane's answer is correct. If you need to retrieve this value from the command line parse the output of
xcodebuild -project myProj.xcodeproj -target "myTarg" -showBuildSettings
For further details see How do I print a list of "Build Settings" in Xcode project?
I'm setting up a CI system using Jenkins and was finding that the build was failing because xcodebuild reports there are no schemes when I was executing the line
-xcodebuild -workspace XXX -scheme NNN.
I couldn't figure out why this could be happening, so to eliminate something screwy being up with my workspace I created a new project template using XCode and found that I am getting a difference in behavior for any xcodebuild command and for any workspace/project.
The template project was called scrap and if from the terminal command line I run this command for example:
xcodebuild -list
It outputs
Information about project "scrap":
Targets:
scrap
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
scrap
But if I run xcodebuild -list from within Jenkins then the output instead is:
Building in workspace /Users/Shared/Jenkins/Home/workspace/scrap
[scrap] $ /bin/sh -xe /var/folders/ph/s6dvlfq9769741g_yzmjlmz000007c/T/hudson3765407964219991487.sh
+ xcodebuild -list
Information about project "scrap":
Targets:
scrap
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
This project contains no schemes.
This is the most simple of jenkins jobs - all I do is create a new job, set it to a free-style software project, then add a build step of Execut shell and add the xcodebuild -list command, that's it.
Why is xcodebuild saying there are no schemes when there are? And why is it behaving differently when run from within Jenkins?
Figured out that all you need to do is to set the scheme to be shared.
Scheme > Manage Schemes
Make sure "Shared" is checked.
This will then generate out a new folder/file .../xcshareddata/xcschemes/???.xcscheme
Check this file into your source control and scheme should now appear on your jenkins box.
you must ignore your .xcodeproj/xcuserdata/.xcuserdatad in your .gitignore file.
xcodebuild -list get schemes from .xcodeproj/xcuserdata/.xcuserdatad/xcschemes.
jenkins server has no this file so get no schemes,you can open *.xcodeproj in your jenkins server,it will create the file and then do xcodebuild -list can get the current schemes.I have the same problem and solved by the method above.
Yet another code sign error.
I'm running command:
xcodebuild -project $DIR/myproject.xcodeproj -sdk iphoneos5.0 -alltargets
and my project.pbxproj
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Ryan"
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "/Users/ryan/12345678-9012-3456-7890-123456789012.mobileprovision";
with output
=== BUILD NATIVE TARGET myproject OF PROJECT myproject WITH THE DEFAULT CONFIGURATION (Release) ===
Check dependencies
[BEROR]Code Sign error: Provisioning profile '/Users/ryan/12345678-9012-3456-7890-123456789012.mobileprovision' can't be found
I can't find any guidance on how to do this. Ive tried putting the provision in ~/Library/MobileDevice/Provisioning Profiles and setting the profile field in project.pbxproj to just the profile ID
It is a requirement that I need to be configure this at the command line w/o Jenkins/Hudson
Provisioning file goes to ~/Library/MobileDevice/Provisioning Profiles and you you can select the provisioning profile like this:
xcodebuild PROVISIONING_PROFILE=12345678-9012-3456-7890-123456789012