ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚡️
https://capacitorjs.com
MIT License
11.8k stars 994 forks source link

feat(cli): support manual signing on build command #7625

Open pfumagalli opened 3 weeks ago

pfumagalli commented 3 weeks ago

Capacitor Version

Latest Dependencies:

@capacitor/cli: 6.1.2 @capacitor/core: 6.1.2 @capacitor/android: 6.1.2 @capacitor/ios: 6.1.2

Installed Dependencies:

@capacitor/android: not installed @capacitor/cli: 6.1.2 @capacitor/core: 6.1.2 @capacitor/ios: 6.1.2

Other API Details

No response

Platforms Affected

Current Behavior

When disabling "Automatically Manage Signing" and setting up the correct Provisioning Profiles and Signing Certificate, and running cap build ios, xcodebuild crashes with a segmentation fault.

Basically cap build ios runs a couple of commands:

The issue lies with the archive.plist file generated here (cli/src/ios/build.ts#L51-L58).

It seems to be missing the signingStyle key. Even setting it to automatic (rather than manual) makes xcodebuild work:

<?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>method</key>
    <string>app-store</string>
    <key>signingStyle</key>
    <string>automatic</string>
  </dict>
</plist>

Expected Behavior

Well, xcodebuild shouldn't segfault!

Project Reproduction

http://none-avail/

Additional Information

Apologies for the lack of reproduction, but without the proper provisioning profiles and certificates (obtainable only from Apple) there's not much we can do to "reproduce" this...

Acanthostega commented 2 weeks ago

Hi, I can reproduce this problem, using manual signing too.

The segmentation fault occurs for me with Xcode at version 15.4. Downgrading to 15.3 resolves the segmentation fault, and displays more information on the error, but not really useful.

Running by hand the command used to generate the IPA, gives in this step:

$ xcodebuild archive -archivePath App.xcarchive -exportArchive -exportOptionsPlist archive.plist -exportPath output -allowProvisioningUpdates -configuration Release

2024-08-26 18:43:15.090 xcodebuild[68234:1099871] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path "/var/folders/64/620ppm4j76170kbtc7wjh8f80000gn/T/App_2024-08-26_18-43-15.090.xcdistributionlogs".
error: exportArchive: "App.app" requires a provisioning profile.

Error Domain=IDEProvisioningErrorDomain Code=9 ""App.app" requires a provisioning profile." UserInfo={IDEDistributionIssueSeverity=3, NSLocalizedDescription="App.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}

** EXPORT FAILED **

Modifying the archive.plist generated by capacitor command with this content (assuming the app identifier is com.app.id):

<?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>method</key>
<string>app-store-connect</string>
        <key>provisioningProfiles</key>
        <dict>
                <key>com.app.id</key>
                <string>match AppStore com.app.id</string>
        </dict>
        <key>signingStyle</key>
        <string>manual</string>
</dict>
</plist>

make the above command successful. (also replaced app-store by app-store-connect since the xcodebuild command complains about is being deprecated).

Is this something that recent versions of Xcode have broken and that capacitor should take care of, or is it something we are missing in the configuration to use manual signing with Capacitor on iOS?

pfumagalli commented 2 weeks ago

If this helps anyone else, we solved the problem by switching to Fastlane for building the iOS part. First there's the usual vite build and cap sync:

vite build
cap sync ios

... and then our fastlane/Fastfile is a simple:

platform :ios do
  # Directories and paths
  ios_dir = File.expand_path("../ios")
  app_dir = File.join(ios_dir, "App")
  workspace_dir = File.join(app_dir, "App.xcworkspace")
  profiles_dir = File.join(ios_dir, "Profiles")
  certificates_dir = File.join(ios_dir, "Certificates")
  output_dir = File.join(app_dir, "output")
  archive_dir = File.join(output_dir, "App.xcarchive")
  project_dir = File.join(app_dir, "App.xcodeproj")
  ipa_file = File.join(output_dir, "App.ipa")

  # Provisioning profiles UUIDs, generate this with
  # security cms -D -i ...file ...mobileprovision | plutil -extract UUID raw -o - -
  uuid_distribution = "... omitted ..."
  # Certificate fingerprint, generate this with
  # openssl x509 -in ... certificate file... -noout -fingerprint -sha1
  sha1_distribution = "... omitted ..."
  bundle_id = "... omitted ..." # Bundle from XCode / Capacitor config / ...
  team_id = "... omitted ..."
  app_id = "1617680793" # from App Store Connect -> App Info -> Apple Id

  # Create a "xcarchive" for our iOS App
  lane :do_build do
    build_app(
      workspace: workspace_dir,
      archive_path: archive_dir,
      scheme: "App",
      destination: "generic/platform=iOS",
      skip_codesigning: true,
      skip_package_ipa: true,
    )
  end

  # Sign the "xcarchive" and prepare an IPA
  lane :do_sign do
    build_app(
      workspace: workspace_dir,
      archive_path: archive_dir,
      output_directory: output_dir,
      output_name: File.basename(ipa_file),
      configuration: "Release",

      skip_build_archive: true,
      skip_package_dependencies_resolution: true,

      # Signing configuration
      export_method: "app-store",
      export_team_id: team_id,
      export_options: {
        signingStyle: "manual",
        signingCertificate: sha1_distribution,
        provisioningProfiles: Hash[ bundle_id, uuid_distribution ],
      },
    )
  end

  # Verify that our IPA file conforms to our needs
  lane :do_verify do
    verify_build(
      ipa_path: ipa_file,
      provisioning_type: "distribution",
      provisioning_uuid: uuid_distribution,
      team_identifier: team_id,
      team_name: "... omitted ...",
      app_name: "... omitted ...",
      bundle_identifier: bundle_id,
    )
  end

  # Prepare a release (as an .IPA file for TestFlight)
  lane :release do
    do_build()
    do_sign()
    do_verify()
  end
end
jcesarmobile commented 2 weeks ago

Manual signing is not supported at the moment.

The segmentation fault is a bug in Xcode 15.4+ that shows the segmentation fault instead of the actual error, if you try in older Xcode versions you'll see the actual error.

Turning this issue into a feature request.