expo / expo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
https://docs.expo.dev
MIT License
34k stars 5.44k forks source link

[Expo51] Manual code signing / provisioning profile for `expo prebuild` ios project fails with `xxx does not support provisioning profiles.` #29526

Open stefan-schweiger opened 4 months ago

stefan-schweiger commented 4 months ago

Summary

When I freshly prebuild my project with npx expo prebuild --platform ios --clean and then try to do a manual code signing / provisioning profile it fails since updating to expo 51.

The output is just a bunch of those errors for different pods:

ios/Pods/Pods.xcodeproj: error: ExpoLocalization does not support provisioning profiles. ExpoLocalization does not support provisioning profiles, but provisioning profile AppStore - Zastrpay POS (Test) has been manually specified. Set the provisioning profile value to "Automatic" in the build settings editor. (in target 'ExpoLocalization' from project 'Pods')

I can fix this by including the following code in the pod file:

  post_install do |installer|
    react_native_post_install(
      installer,
      config[:reactNativePath],
      :mac_catalyst_enabled => false,
      :ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
    )

    # START: added code to fix build
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
        config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
        config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
      end
    end
    # END: added code to fix build

    # This is necessary for Xcode 14, because it signs resource bundles by default
    # when building for devices.
    installer.target_installation_results.pod_target_installation_results
      .each do |pod_name, target_installation_result|
      target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
        resource_bundle_target.build_configurations.each do |config|
          config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
        end
      end
    end
  end

I have use used the same method (prebuild + manual code sign) without a problem with SDK50 and below for many months.

What platform(s) does this occur on?

iOS

SDK Version

51

Environment

expo-env-info 1.2.0 environment info: System: OS: macOS 14.5 Shell: 5.9 - /bin/zsh Binaries: Node: 22.2.0 - /opt/homebrew/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 10.5.2 - /opt/homebrew/bin/npm Watchman: 2024.05.06.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.15.2 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: DriverKit 23.5, iOS 17.5, macOS 14.5, tvOS 17.5, visionOS 1.2, watchOS 10.5 IDEs: Xcode: 15.4/15F31d - /usr/bin/xcodebuild npmPackages: expo: ~51.0.11 => 51.0.11 react: 18.2.0 => 18.2.0 react-dom: 18.2.0 => 18.2.0 react-native: 0.74.2 => 0.74.2 react-native-web: ~0.19.10 => 0.19.10 npmGlobalPackages: eas-cli: 9.1.0 Expo Workflow: managed

Minimal reproducible example

Since I can't really share provisioning profiles etc I can't create a direct reproduction, but the steps I did are the following:

  1. run npx expo prebuild --platform ios --clean
  2. Open the project in xcode
  3. Unselect automatic signing and select your Appstore Provisioning Profile image
joshuaben commented 2 months ago

Just wanted to share, I have been able to adjust the manual toggle, but cannot seem to set the build settings for the provisioning profile...

plugins: [
    ...,
    [
      './plugins/withCustomXcodeBuildSettings.js',
      {
        version: '9.1.10',
        buildNumber: '3'
      }
    ]
]    

and then:


const { withXcodeProject } = require('@expo/config-plugins')

const withCustomXcodeBuildSettings = (
  config,
  { version, buildNumber } = {}
) => {
  return withXcodeProject(config, (config) => {
    const xcodeProject = config.modResults

    const buildConfigurations = xcodeProject.pbxXCBuildConfigurationSection()

    Object.keys(buildConfigurations).forEach((key) => {
      const buildConfig = buildConfigurations[key]
      if (buildConfig.buildSettings) {
        buildConfig.buildSettings.CODE_SIGN_STYLE = 'Manual'
        // unable to set PROVISIONING_PROFILE here
      }
    })

    if (version) {
      xcodeProject.addBuildProperty('MARKETING_VERSION', version)
    }

    if (buildNumber) {
      xcodeProject.addBuildProperty('CURRENT_PROJECT_VERSION', buildNumber)
    }

    return config
  })
}

module.exports = withCustomXcodeBuildSettings
chris-garrett commented 1 month ago

I am trying to do the same thing and got it working with your code + https://github.com/expo/expo/issues/28363#issue-2256248301

const { IOSConfig, withXcodeProject } = require("@expo/config-plugins");

const withCustomXcodeBuildSettings = (
  config,
  {
    keychainFile,
    developmentTeam,
    codeSignIdentity,
    provisioningProfile,
  } = {},
) => {
  return withXcodeProject(config, (config) => {
    const project = config.modResults;

    const targets = IOSConfig.Target.findSignableTargets(project);

    targets.forEach(([nativeTargetId, nativeTarget]) => {
      IOSConfig.XcodeUtils.getBuildConfigurationsForListId(
        project,
        nativeTarget.buildConfigurationList,
      ).forEach((config) => {
        const [, item] = config;

        item.buildSettings.DEVELOPMENT_TEAM = developmentTeam;
        item.buildSettings.CODE_SIGN_IDENTITY = `"${codeSignIdentity}"`;
        item.buildSettings.PROVISIONING_PROFILE = provisioningProfile;
        item.buildSettings.CODE_SIGN_STYLE = "Manual";
        if (keychainFile) {
          item.buildSettings.OTHER_CODE_SIGN_FLAGS = `"--keychain=${keychainFile}"`;
        }
      });

      Object.entries(IOSConfig.XcodeUtils.getProjectSection(project))
        .filter(IOSConfig.XcodeUtils.isNotComment)
        .forEach(([, item]) => {
          if (!item.attributes.TargetAttributes[nativeTargetId]) {
            item.attributes.TargetAttributes[nativeTargetId] = {};
          }
          item.attributes.TargetAttributes[nativeTargetId].ProvisioningStyle =
            "Manual";
          item.attributes.TargetAttributes[nativeTargetId].DevelopmentTeam =
            developmentTeam;
          item.attributes.TargetAttributes[nativeTargetId].CodeSignStyle =
            `"${codeSignIdentity}"`;
        });
    });

    return config;
  });
};

module.exports = withCustomXcodeBuildSettings;