fastlane: Gym auto selects provisioning profile mapping wrong in an Xcode project with multiple configs

New Issue Checklist

Issue Description

Running the lane deploy_testflight, gym generate a plist file with the wrong provisioning profile

[13:27:07]: Generated plist file with the following values:
[13:27:07]: ▸ -----------------------------------------
[13:27:07]: ▸ {
[13:27:07]: ▸   "provisioningProfiles": {
[13:27:07]: ▸     "com.xxx.yyy${BUNDLE_ID_SUFFIX}": "xxx Dev AdHoc Distribution"
[13:27:07]: ▸   },
[13:27:07]: ▸   "method": "app-store"
[13:27:07]: ▸ }
[13:27:07]: ▸ -----------------------------------------

BUNDLE_ID_SUFFIX is a user define config variabile I have in my project. It’s value, for a TestFlight build (ProdRelease config) is empty btw.

The problem is that the chosen provisioning profile is wrong. To deploy the app on TestFlight, the AppStore distribution profile must be used. The Xcode project is correctly configured to do so


Edit by @joshdholtz: This method is the causing this issue when Xcode project have multiple configurations - https://github.com/fastlane/fastlane/blob/6a82b16373568b0d2cd793998dd6164503831aef/gym/lib/gym/detect_values.rb#L89-L120. It sometimes selects the wrong profile and makes things go 💥


Environment

Please run fastlane env and copy the output below. This will help us help you 👍 If you used --capture_output option please remove this block - as it is already included there.

🚫 fastlane environment 🚫

Stack

Key Value
OS 10.12.5
Ruby 2.4.0
Bundler? false
Git git version 2.11.0
Installation Source /usr/local/bin/fastlane
Host Mac OS X 10.12.5 (16F73)
Ruby Lib Dir /usr/local/Cellar/ruby/2.4.0/lib
OpenSSL Version OpenSSL 1.0.2j 26 Sep 2016
Is contained false
Is homebrew false
Is installed via Fabric.app false
Xcode Path /Applications/Xcode.app/Contents/Developer/
Xcode Version 8.3.1

System Locale

Error
No Locale with UTF8 found 🚫

fastlane files:

`./fastlane/Fastfile`
xcode_select "/Applications/Xcode.app"

# Fastlane constants
fastlane_version "2.7.0"
default_platform :ios
itc_uri = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/" + "xyz"

platform :ios do

  before_all do
    
    # Shared information
    ENV['APP_MARKETING_VERSION'] = `cd .. && agvtool what-marketing-version -terse1 | tr -d '\n'`

  end

  desc "Build and deploy app for public testing on TestFlight"
  lane :deploy_testflight do
    
    # Check ENV
    raise "Please specify SLACK_URL inside `.env` file before run this lane again".red unless ENV['SLACK_URL']
    raise "Please specify SLACK_USERNAME inside `.env` file before run this lane again".red unless ENV['SLACK_USERNAME']
    
    # Ensure what-to-test is up-to-date
    UI.header "testflight-what-to-test.txt"
    UI.message(File.read("./metadata/testflight-what-to-test.txt"))
    unless UI.confirm("Is the what-to-test correct?")
      UI.user_error!("Please update `testflight-what-to-test.txt` file.")
    end

    # Build
    build_ipa(environment: 'prod')

    # Upload and share build with external betatesters
    upload_ipa_testflight

    # Notify on Slack
    slack({
      message: "*Radio iOS #{ENV['APP_MARKETING_VERSION']}* has been uploaded and it's waiting for betatesting review 🚀",
      success: true,
      username: "#{ENV['SLACK_USERNAME']} (fastlane)",
      channel: '#releases',
      payload: {
        'CHANGELOG' => "```" + File.read("./metadata/testflight-what-to-test.txt") + "```"
        },
      default_payloads: [], # No default payload
      })

  end

  desc "Build ipa for AppStore or Ad-Hoc distribution"
  private_lane :build_ipa do |options|

    # Check options
    scheme = ""
    output = ""
    configuration = ""
    export = ""

    case options[:environment]
    when 'prod'
      scheme = "Radio Prod"
      output = "Radio Prod"
      configuration = "ProdRelease"
      export = "app-store"
    
    when 'dev'
      scheme = "Radio Dev"
      output = "Radio Dev"
      configuration = "DevRelease"
      export = "ad-hoc"
    
    when 'beta'
      scheme = "Radio Beta"
      output = "Radio Beta"
      configuration = "BetaRelease"
      export = "ad-hoc"
    
    else
      UI.user_error!("Invalid environment passed to lane: #{options[:environment]}")
    end

    UI.message("Building scheme `#{scheme}` with configuration `#{configuration}`")

    # pod install
    cocoapods

    # Build
    gym(
      scheme: scheme,
      output_name: output,
      configuration: configuration,
      export_method: export
      )

  end

  desc "Upload ipa (PROD) to TestFlight and HockeyApp"
  private_lane :upload_ipa_testflight do

    # Check ENV
    raise "Please specify HOCKEYAPP_TOKEN inside `.env` file before run this lane again".red unless ENV['HOCKEYAPP_TOKEN']
    raise "Please specify SLACK_URL inside `.env` file before run this lane again".red unless ENV['SLACK_URL']
    raise "Please specify SLACK_USERNAME inside `.env` file before run this lane again".red unless ENV['SLACK_USERNAME']

    # Upload build to iTunesConnect
    pilot(
      username: ENV['FASTLANE_USERNAME'],
      changelog: File.read("./metadata/testflight-what-to-test.txt"),
      beta_app_description: File.read("./metadata/testflight-description.txt"),
      beta_app_feedback_email: "xxx@yyy.com",
      distribute_external: true,
      skip_submission: true
      )

    # Send dSYM to HockeyApp
    upload_ipa_hockeyapp(
      environment: 'prod',
      notes: "New build available in AppStore for external testers."
      )

    # Notify on Slack
    slack({
      message: "Uploaded Radio iOS (PROD) app #{ENV['APP_MARKETING_VERSION']} to TestFlight",
      success: true,
      channel: '#bot',
      username: "#{ENV['SLACK_USERNAME']} (fastlane)",
      payload: {
        'iTunes Connect link' => itc_uri
        },
      default_payloads: [], # No default payload
      })

  end

  desc "Upload ipa to HockeyApp"
  private_lane :upload_ipa_hockeyapp do |options|

    raise "Please specify `environment` parameter".red unless options[:environment]

    identifier = ""
    dsym_only = false
    notes = options[:notes] || "New build available on HockeyApp."

    case options[:environment]
    when 'prod'
      identifier = '123'
      dsym_only = true
    
    when 'dev'
      identifier = '456'
      dsym_only = false
    
    when 'beta'
      identifier = '789'
      dsym_only = false
    
    else
      UI.user_error!("Invalid environment passed to lane: #{options[:environment]}")
    end

    UI.message("Uploading dsym only? #{dsym_only}")

    hockey(
      api_token: ENV['HOCKEYAPP_TOKEN'],
      upload_dsym_only: dsym_only,
      public_identifier: identifier,
      notes: notes
      )

  end

  #
  # On lane success
  #
  after_all do |lane|

    unless is_ci?
      # Mac OS notification
      notification(
        title: "Radio iOS 🚀: 👍", 
        message: "#{lane} succeded!"
        )
    end

  end

  #
  # On lane failure
  #
  error do |lane, exception|

    unless is_ci?
      # Mac OS notification
      notification(
        title: "Radio 🚀: 🔥", 
        message: "#{lane} failed: #{exception.message}"
        )
    end

  end
end

# More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/docs/Platforms.md
# All available actions: https://github.com/fastlane/fastlane/blob/master/docs/Actions.md
`./fastlane/Appfile`
# More information: https://github.com/fastlane/fastlane/blob/master/docs/Appfile.md

for_lane :dev do
  app_identifier "com.xxx.yyy.dev"
  app_icon "./Resources/AppIcon-dev-1024.png"
end

for_lane :beta do
  app_identifier "com.xxx.yyy.beta"
  app_icon "./Resources/AppIcon-beta-1024.png"
end

fastlane gems

Gem Version Update-Status
fastlane 2.47.0 🚫 Update available

Loaded fastlane plugins:

Plugin Version Update-Status
fastlane-plugin-framer 0.2.0 ✅ Up-To-Date
Loaded gems
Gem Version
did_you_mean 1.1.0
slack-notifier 1.5.1
CFPropertyList 2.3.5
multipart-post 2.0.0
word_wrap 1.0.0
tty-screen 0.5.0
babosa 1.0.2
colored 1.2
highline 1.7.8
commander-fastlane 4.4.5
http-cookie 1.0.3
faraday-cookie_jar 0.0.6
fastimage 2.1.0
gh_inspector 1.0.3
declarative 0.0.9
declarative-option 0.1.0
representable 3.0.4
public_suffix 2.0.5
addressable 2.5.1
mime-types-data 3.2016.0521
mime-types 3.1
httpclient 2.8.3
google-api-client 0.12.0
mini_magick 4.5.1
multi_json 1.12.1
multi_xml 0.6.0
rubyzip 1.2.1
security 0.1.3
xcpretty-travis-formatter 0.0.4
bundler 1.14.3
faraday_middleware 0.11.0.1
json 2.1.0
io-console 0.4.6
excon 0.57.1
openssl 2.0.2
plist 3.3.0
faraday 0.12.2
jwt 1.5.6
os 0.9.6
signet 0.7.3
googleauth 0.5.3
unf 0.1.4
domain_name 0.5.20170404
claide 1.0.2
colored2 3.1.2
nanaimo 0.2.3
xcodeproj 1.5.1
terminal-table 1.8.0
unicode-display_width 1.3.0
fastlane-plugin-framer 0.2.0

generated on: 2017-07-28

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 23 (15 by maintainers)

Most upvoted comments

@daltonclaybrook Thanks for letting me know of the version number that last worked for you! Huge help ✊ Will make this easier to look into 😊

Thank you so much @joshdholtz for helping me out on this! 👍

Ended up solving this issue with @dral3x in the fastlane slack team.

Cause of the issue

https://github.com/fastlane/fastlane/blob/6a82b16373568b0d2cd793998dd6164503831aef/gym/lib/gym/detect_values.rb#L62-L65

Temporary solution (probably won’t work in Xcode 9 but only in Xcode 8)

Add export_options. provisioningProfiles (like below) to short circuit the self.detect_selected_provisioning_profiles method (from above) to not automatically select provisioning profiles. There is some issue when having multiple configurations were this method actually grabs the wrong profile from the config.

I have personally experienced this issue as well so I will handle the fixing this (somehow) so other people don’t run into it since the current solution isn’t a very straight forward one 😇

gym(
      scheme: scheme,
      output_name: output,
      configuration: configuration,
      export_method: export,

     # We added this right here to make things work
      export_options: {
        provisioningProfiles: {}
      }
)

Actual solution that needs to get implemented yet (Need this for Xcode 9)

Figure out why this logic (https://github.com/fastlane/fastlane/blob/6a82b16373568b0d2cd793998dd6164503831aef/gym/lib/gym/detect_values.rb#L89-L120) is choosing the wrong profile sometimes.

We are still seeing this issue in version 2.53.1 In our case, the Xcode project has 10 different app targets that all build as part of one lane. Each target has configurations for Debug, AdHoc, and Release with specific provisioning profiles assigned for each configuration. On this particular lane, we are only trying to build the AdHoc configuration. I am seeing the following incorrect output (actual bundle ID and profiles are redacted):

Detected provisioning profile mapping: {nil=>"<wrong profile>", "<wrong bundle ID>"=>"<wrong profile>"}

When I downgrade to fastlane 2.38.1, the problem no longer occurs (This is not to say that 2.38.1 is the last working version, just the last one I have installed that works).

Quick question: since I don’t have anything setup to test this unique config, maybe @daltonclaybrook, @chefnobody, or @dral3x could try out the referenced PR?

Hello fellow gym signing issue family 👋 Got a PR up with some fixes and better warnings for these errors ^

@joshdholtz I’d love to help with this if possible… I have tried all kinds of tricks to get this to work.

My goal is to get an AdHoc build archived and provisioned correctly with gym.

Just spit balling…

  • I have a pretty basic set up with CocoaPods and a Product (app Target) and ProductTests (Target) in my main Project.
  • We use fastlane match to sync certs and profiles to our machines and the Jenkins slave. That is all cream cheese 🙌 , so no issues there.
  • The main Project’s app Target “Product” has 4 Build Configurations (Debug, AdHoc, Release and Distribution). Each Build Configuration is pointing at the corresponding Provisioning Profile (Development, AdHoc, Distribution and Distribution respectively and so Xcode is happy with that as far as I can tell.
  • Testing, Building and Archiving all succeed from within Xcode and the build log confirms this.
  • I’m definitely passing the ad-hoc export_method to my call to gym:
    gym(
      output_directory: "./build/",
      output_name: output_name,
      scheme: "ProductScheme",
      clean: true,
      export_method: "ad-hoc",
      xcargs: params
    )

And the gym output reflects this.

Unfortunately no matter what I do I can’t seem to get gym to archive this app with the correct AdHoc provisioning profile, it always uses my match AppStore com.foo.bar Profile:

...
Detected provisioning profile mapping: {nil=>"match AppStore com.foo.bar"}
...

Now,

  • I have double-checked that the Project’s app Target has a PRODUCT_BUNDLE_IDENTIFIER specified somewhere. It does not. Adding one did not make a difference.
  • I have double-checked that the Project’s app Target has a PROVISIONING_PROFILE_SPECIFIER and a PROVISIONING_PROFILE value set, but the former is preferred if my understanding of the Ruby (above) is accurate. Plus fastlane match ensure those are always valid (if I’ve synced the latest to my repo from Apple’s Developer Portal).
  • I have tried to the override the export_options with an empty export_options.provisioningProfiles like so:
      # We added this right here to make things work
      export_options: {
        provisioningProfiles: {}
      }

But that failed as well with the same detected profile as above.

  • I also tried explicitly telling it to use the provided provisioningProfile like so:
      export_options: {
        provisioningProfiles: {
           "com.foo.bar" => "match AdHoc com.foo.bar"
        }
      }

But it still included an AppStore one with a nil key like this:

Detected provisioning profile mapping: {nil=>"match AppStore com.foo.bar", "com.foo.bar"=>"match AdHoc com.foo.bar" }

And preferred the nil key value instead.

@daltonclaybrook 10 might be unique but I don’t think having more than 1 is terribly unique 🤔 I usually have multiple for different environments.

I am working on a different PR right now but will be attempting to tackle this issue later tonight ✊