iosipafastlanecodesignxcarchive

How do I use fastlane to compile my iOS app into an .xcarchive, then separately sign and make an IPA?


I’m making an iOS app for a client, but don’t have access to their provisioning profiles or signing certificates.

I’d like to give my client an already compiled version of the app so that all they need to do is sign it and then upload it to TestFlight and the App Store.

Previously I was giving my client the whole .xcodeproj, in this case exported from a Unity game, but there have been issues with them using a different version of Xcode and issues with using CocoaPods on a different machine.

It looks like I can do this by exporting my iOS app to an .xcarchive without any provisioning profiles or signing certificates, then give them the .xcarchive and have them sign it, make an .ipa, and upload it to the App Store. I’m currently using fastlane for automating builds, and would like to continue to do so with this new solution.


Solution

  • You can use the following in fastlane to export MyArchiveName.xcarchive:

      build_app(
        configuration: "Release",
        project: "Path/To/My.xcodeproj",
        export_method: "app-store",
        export_options: {iCloudContainerEnvironment: "Production"},
        skip_codesigning: true,
        skip_package_ipa: true,
        archive_path: "MyArchiveName.xcarchive"
     )
    

    Then you can take MyArchiveName.xcarchive and give it to your client, and then they can run the following build in fastlane:

    lane :sign_xcarchive_and_publish do
      default_platform(:ios)
      sync_code_signing(
        type: "appstore"
      )
    
      # You must create a fake xcodeproj to pass in.
      # This is needed to work around this issue in fastlane: https://github.com/fastlane/fastlane/issues/13528
      # See also: https://github.com/fastlane/fastlane/issues/11402 and https://github.com/fastlane/fastlane/issues/15876
      xcodeproj_path = File.expand_path("../fake.xcodeproj")
      Xcodeproj::Project.new(xcodeproj_path).save
    
      build_app(
        configuration: "Release",
        project: xcodeproj_path,
        output_name: "MyOutput.ipa",
        export_method: "app-store",
        export_options: { iCloudContainerEnvironment: "Production" },
        export_team_id: CredentialsManager::AppfileConfig.try_fetch_value(:team_id), # This requires the team_id to be set in the fastlane `Appfile`
        skip_build_archive: true,
        skip_package_dependencies_resolution: true,
        archive_path: "MyArchiveName.xcarchive"
     )
    
      upload_to_testflight(
        skip_submission: true,
        skip_waiting_for_build_processing: true
      )
    end
    

    Note that you'll need to validate that plugins are built and signed correctly. I haven't had issues yet, but more complex builds may. Also note that this is only for the client directly uploading to the app store, I haven't attempted any other kind of signing.