41

SUMMARY:

If you open a project in Xcode 8 with "Automatically manage signing" enabled and a new bundle ID, it will automatically create and download a provisioning profile for it. But how can I make the same thing happen with xcodebuild, so I can use it on a remote build server?

DETAILS:

I'm trying to build a Cordova app on a Mac. Cordova configures the Xcode project to use "Automatically manage signing", so I'm trying to use that.

I change the bundle ID often, so I want Cordova to be able to build it with a new bundle ID, that hasn't been used before.

But when I run cordova build ios --release --device --buildConfig build.json, I get a return code 65 and the following error:

Check dependencies
No profiles for 'com.my.bundle.id' were found:  Xcode couldn't find a provisioning profile matching 'com.my.bundle.id'.
Code signing is required for product type 'Application' in SDK 'iOS 10.3'

** ARCHIVE FAILED **

The following build commands failed:
    Check dependencies
(1 failure)
Error: Error code 65 for command: xcodebuild with args: -xcconfig,/cordova-project/platforms/ios/cordova/build-debug.xcconfig,-workspace,MyApp.xcworkspace,-scheme,MyApp,-configuration,Debug,-destination,generic/platform=iOS,-archivePath,MyApp.xcarchive,archive,CONFIGURATION_BUILD_DIR=/cordova-project/platforms/ios/build/device,SHARED_PRECOMPS_DIR=/cordova-project/platforms/ios/build/sharedpch

(I can manually run that xcodebuild command and get the same error, so it's probably not a Cordova issue.)

My build.json file looks like this:

{
    "ios": {
        "debug": {
            "codeSignIdentity": "iPhone Developer",
            "developmentTeam": "MY_TEAM_ID",
            "packageType": "development"
        },
        "release": {
            "codeSignIdentity": "iPhone Developer",
            "developmentTeam": "MY_TEAM_ID",
            "packageType": "enterprise"
        }
    }
}

I'm using cordova 7.0.1, cordova-ios 4.4.0, Xcode 8.3.3, and MacOS 10.12.5. I have an Apple Enterprise account.

WHAT I TRIED:

If I open the generated project in Xcode, it fixes the automatic signing, and from then on I can run cordova successfully with that bundle ID. But if I try to run it with a different bundle ID, it will fail again.

I tried using security unlock-keychain ~/Library/Keychains/login.keychain-db first, since that's worked in the past, but it didn't help.

I also tried opening my private signing key in Keychain Access and setting it to "Allow all applications to access this item", without any luck.

I get the same error regardless of whether I pass --debug or --release to cordova.

JW.
  • 50,691
  • 36
  • 115
  • 143
  • The only way I have been able to make this work is by specifying the `provisioningProfile` in build.json, despite the [Cordova documentation](https://cordova.apache.org/docs/en/latest/guide/platforms/ios/#signing-an-app) indicating that it's no longer required. – DaveAlden Jun 10 '17 at 14:55
  • @JW. i hope this should help you out - http://code-dojo.blogspot.in/2012/09/fix-ios-code-signing-issue-when-using.html – Gandhi Jul 07 '17 at 04:24
  • @JW. also try manually deleting local profiles in: ~/Library/MobileDevice/Provisioning Profiles if any – Gandhi Jul 07 '17 at 05:03
  • @JW. Tyr out Ajeet's answer in this link - https://stackoverflow.com/questions/39500634/use-xcodebuild-xcode-8-and-automatic-signing-in-ci-travis-jenkins-environmen/39559864 – Gandhi Jul 08 '17 at 17:11
  • @Gandhi that looks like it's for manual signing – JW. Jul 10 '17 at 20:17
  • @JW. It talks about executing shell script as part of jenkins build. It should be automatic signing i believe – Gandhi Jul 11 '17 at 03:40
  • @JW. Was going through this link - http://blog.bitrise.io/2016/09/21/xcode-8-and-automatic-code-signing.html for better understanding of how automatic code signing works. But I dont see any reference of app ID or provisioning profile getting created automatically. All it says it can pick up the profiles automatically when all the inputs are provided properly. Also it says codesigndoc eases up this doc. So wondering creation of app ID or provisioning profile automatically is really a part of automatic signing or just a wrong perception? – Gandhi Jul 11 '17 at 04:31
  • https://forums.developer.apple.com/thread/69950 seems to be the same issue with a solution posted – Matt Jul 12 '17 at 01:43
  • @JW. Hi, does my answer makes sense? – Gandhi Jul 13 '17 at 07:17
  • @Gandhi Yeah, you may be right about the definition of automatic signing. But even if that's the case, Xcode is doing some process when you open a project with automatic signing, to create the app ID and profile. That's what I'm trying to reproduce on the command line. – JW. Jul 13 '17 at 22:31

9 Answers9

22

This isn't directly supported in Xcode 8. In Xcode 9, however, you can pass -allowProvisioningUpdates to xcodebuild and automatic signing will work just as in the Xcode UI, without needing any additional tools.

e.g. cordova run ios --buildFlag="-allowProvisioningUpdates"

Chui Tey
  • 5,436
  • 2
  • 35
  • 44
itai195
  • 1,261
  • 7
  • 6
  • 1
    I think this is technically the only answer to the question I was asking, even though it means waiting until Xcode 9. So congratulations! – JW. Jul 13 '17 at 22:39
  • 2
    How can you pass this arg with the cordova build command? I tried `--buildFlag="-allowProvisioningUpdates"`, but it seems to be ignored – Cocowalla Sep 20 '17 at 16:06
  • @itai195 you seemingly left out an incredibly important piece of the puzzle. How does one actually get that flag to the xcodebuild command. I tried `cordova build ios .... -- -allowProvisioningUpdates` but it didn't work. – James Gilchrist Oct 11 '17 at 21:52
  • 1
    This is coming in the next version of Cordova-iOS, and will be enabled by specifying `--automaticProvisioning` on the command-line or `"automaticProvisioning": true` in build.json. – dpogue Nov 16 '17 at 07:52
  • I'm doing `cordova run ios --buildFlag="-allowProvisioningUpdates"` and it works fine. I'm using a clean install of Cordova 7.1.0. – feupeu Nov 16 '17 at 13:23
  • @Cocowalla I think you also need to set a unique widget id in Cordova's config.xml, i.e. change the default one to something particular for your app. – Otto Dec 23 '18 at 12:44
6

Answer is yes. What I used and what I can confirm is working and it is great:

https://fastlane.tools/

You can set up everything to be automatic:

  1. Signing keys
  2. Taking screenshots
  3. Uploading on iTunes

and many other things

In background it is using xcodebuild command line. I was skeptic that something like this is possible, but just set up, start and enjoy.

mommcilo
  • 956
  • 11
  • 28
5

For Automatically manage signing you can use Fastlane. It's easy to install and setup.

For using it on a remote build server - you can use Jenkins.

Here example. You need to setup Jenkins with Fastlane to your remote machine. Than Jenkins will check your repository thread or just by you command to it. After it Jenkins run Fastlane on remote build server. And Fastlane will create all certificate and other setup that you write in Fastfile.

If you have only one deploy certificate, you can use Fastlane service called Match

Easily sync your certificates and profiles across your team using Git

or just send and setup it locally.

Hope it helps you, good luck!

Here example for beta deploy (for me work with Xcode 9):

 desc "Build devFoo and upload it to Fabric"
      lane :uploadToFabric do
        cocoapods
        cert(
        development: true,
        output_path: "./fastlane"
        )
        sigh(
        development: true,
        output_path: "./fastlane"
        )
        clear_derived_data
        gym(
        scheme: "Foo",
        configuration: "Debug",
        clean: true,
        output_directory: "./fastlane",
        )
        crashlytics(
        api_token: "foofoofoofoo",
        build_secret: "foofoofoofoo",
        emails: ["foo@foo.com"],
        notifications: true
        )
        slack(
        message: "New build for test successfully deployed in Fabric",
        success: true
        )
      end

Here example for release deploy:

desc "Build and upload it to the AppStore and TestFlight"
  lane :uploadToAppStore do
    cocoapods

    cert(
    development: false,
    output_path: "./fastlane"
    )
    sigh(
    development: false,
    app_identifier: "foofoo",
    output_path: "./fastlane"
    )
    clear_derived_data
    gym(
    scheme: "Foo",
    configuration: "Release",
    clean: false,
    output_directory: "./fastlane",
    )
    deliver(
    force: true,
    app_identifier: "foo",
    skip_metadata: true,
    skip_screenshots: true,
    submit_for_review: false,
    skip_binary_upload: false
    )
    slack(
    message: "New build successfully deployed to AppStore",
    success: true
    )
    upload_symbols_to_crashlytics(dsym_path: "./fastlane/foo.app.dSYM.zip")
    slack(
    message: "dSYM symbolication files uploaded to Crashlytics",
    success: true
    )
S. Matsepura
  • 1,673
  • 1
  • 17
  • 24
4

You can do it using fastlane.

https://fastlane.tools/

cert : Fetch or generate the latest available code signing identity

sigh : Generates a provisioning profile. Stores the profile in the current folder

ps : If you are running it from a CI server (for example jenkins) you need then to unlock login keychain :

security unlock-keychain -p PASSWORD /Users/YOUR-USER/Library/Keychains/login.keychain

Example within the fastfile :

cert(
  development: true,
)

sigh(
  development: true,
  app_identifier: "YOUR_APP_IDENTIFIER"
)

Here's an example of a basic Fastfile :

fastlane_version "2.27.0"
default_platform :ios

platform :ios do

lane :beta do
   cert
   sigh
   gym
end

error do |lane, exception|
  puts "Got an error! #{exception.error_info.to_s}"
end

end
Fares Benhamouda
  • 589
  • 8
  • 21
3

There is no way to manage signing automatically using xcodebuild. You must either use third parties like Fastlane as mentioned before or use manual code signing as mentioned here.

Vahan Babayan
  • 723
  • 7
  • 21
3

As some other answers have already mentioned, what you are looking for is a release automation tool called Fastlane. https://fastlane.tools/

If you are not familiar with it, I believe best place to get started would be raywenderlich's fastlane tutorial.

https://www.raywenderlich.com/136168/fastlane-tutorial-getting-started-2

Rukshan
  • 7,902
  • 6
  • 43
  • 61
3

Notice: This answer assumes that bundle ID and provisioning profiles are created manually. Only build process can be automated using this method.

Yes that is possible even without using third party tools. you should be comfortable using script file or a make file. I'm using 2 lines of code in a makefile on Mac Mini at work. And that gives us either ad-hoc or appstore version ready for upload according to our configuration.

  1. make sure your project has enabled automatic configuration.
  2. make sure on your remote mac that all singing certificates and provisioning are downloaded. for this case, I always, for the first building, open Xcode and build & export on my remote machine. If that works then nothing is missing. But make sure that you always allow access to the singing certificate. Xcode also asks this for the first the build. Otherwise a popup will show up on your remote server and waits till someone allows access to the signing certificate.
  3. you need a plist file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>  
  <key>teamID</key>  
  <string>MY_TEAM_ID_XXYY</string> //put your iPhone distribution team ID. in my case developer team ID is different than my distribution team ID. just wondering.
  <key>method</key>  
  <string>app-store</string> // for appstore upload or use <string>ad-hoc</string> for ad-hoc  
  <key>uploadSymbols</key>  
  <true/>  
  <key>uploadBitcode</key>  
  <true/>  
</dict>  
</plist>

You should save plist configuration somewhere accessible, e.g., as options.plist just a reminder: make sure that you have your ad-hoc/distribution provisioning profile on your remote Mac.

  1. xcodebuild will create an archive then we can export .app. In your make file or script file use these lines:

4.1. First we create the archive file.

xcodebuild archive -derivedDataPath build/ -project myProject.xcodeproj -scheme myScheme -archivePath build/ios/myProject.xcarchive

derivedDataPath parameter is just a folder that can be deleted later after building the app. you know how much junk is produced in derived data. project name is your project name, and scheme name is right after play|stop button in Xcode. You must choose an archive name and path for the next step.

4.2 After your archive has been built successfully, use this code to create the app:

xcodebuild -exportArchive -archivePath build/ios/myProject.xcarchive -exportPath build/ios/ -exportOptionsPlist build/ios/options.plist

Here you use the archive name and path that was used in previous step. exportOptionsPlist needs to know the path and name for your plist configuration that we created in step 3.

And that's it! You can run these commands in a terminal window it will build your app as well. You can put these 2 line in a script file / makefile and use variables for project name, path and options.plist, Then you can use that to build all of your apps.

PS: If anything is unclear please let me know and I will add more explanation.

Hashmat Khalil
  • 1,826
  • 1
  • 25
  • 49
  • That's useful, but Cordova pretty much does the same thing. It doesn't quite solve my case, when you haven't created the app ID or provisioning profile yet, and you want to create it automatically the way Xcode does. – JW. Jul 10 '17 at 20:14
  • As others have posted, fastlane and some other tools can do that. but that means somehow they need you login to developer portal or they know how to manipulate Xcode to do that. I'm not yet aware of any Xcode command line, but I will look into it. in your case, one of answers with fastlane is more what you want than my answer. – Hashmat Khalil Jul 10 '17 at 20:45
  • 1
    FYI, I looked into the fastlane source and found out that they are sending web request with JSON object for creating bundle ID for example. So there is probably no Xcode command line, probably that's why they are leveraging "web api". I won't rely on that "unofficial web api". They can be changed any time by apple. – Hashmat Khalil Jul 11 '17 at 06:12
3

As far as my understanding and recent readings, the answer to OP's question:

"Can xcodebuild manage automatic signing?" is "YES" but not as per the OP's expectations in lines of "when you haven't created the app ID or provisioning profile yet, and you want to create it automatically the way Xcode does"

As per this informative blog on xcode8 and automatic code signing, it clearly states that :

"If you want to create for example an App Store signed IPA, on the Mac you have to have both a Wildcard, Team / Development AND the App Store distribution certificates and provisioning profiles!"

Hence, the app ID and provisioning profile wont be auto created. Fastlane may be a workaround to this problem but i guess that is not the OP's expectation. Hope it makes sense.

Gandhi
  • 11,875
  • 4
  • 39
  • 63
3

If you are archiving the xCode project with xcodebuild and you have xCode 9 installed you can provide the following FLAGS to the compilation command:

CODE_SIGN_STYLE="Manual" \
DEVELOPMENT_TEAM="" \

It will set the automatic signing to false and the development team to empty. You can set the values you need. For instance:

xcodebuild \
-scheme "your_scheme" \
-sdk iphoneos \
-archivePath "/Users/youruser/Developer/Jenkins/Home/customWorkspace/folder/platforms/ios/build/device/yourproject.xcarchive" \
-configuration Release \
-allowProvisioningUpdates \
CONFIGURATION_BUILD_DIR="/Users/youruser/Developer/Jenkins/Home/customWorkspace/folder/platforms/ios/build/device" \
CODE_SIGN_IDENTITY="your code sign identity" \
PROVISIONING_PROFILE="your provisioning profile" \
CODE_SIGN_STYLE="Manual" \
DEVELOPMENT_TEAM="" \
archive

Then you can create the ipa with -exportArchive and it will create the ipa as you need