fastlane 2.182.0 → 2.184.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +103 -96
  3. data/cert/lib/cert/runner.rb +3 -7
  4. data/deliver/lib/assets/summary.html.erb +10 -10
  5. data/deliver/lib/deliver/commands_generator.rb +1 -1
  6. data/deliver/lib/deliver/detect_values.rb +5 -3
  7. data/deliver/lib/deliver/download_screenshots.rb +1 -1
  8. data/deliver/lib/deliver/html_generator.rb +2 -2
  9. data/deliver/lib/deliver/module.rb +6 -0
  10. data/deliver/lib/deliver/options.rb +36 -51
  11. data/deliver/lib/deliver/runner.rb +8 -11
  12. data/deliver/lib/deliver/setup.rb +1 -1
  13. data/deliver/lib/deliver/submit_for_review.rb +4 -4
  14. data/deliver/lib/deliver/upload_metadata.rb +20 -6
  15. data/deliver/lib/deliver/upload_price_tier.rb +1 -1
  16. data/deliver/lib/deliver/upload_screenshots.rb +1 -1
  17. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +7 -11
  18. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +12 -2
  19. data/fastlane/lib/fastlane/actions/carthage.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/check_app_store_metadata.rb +5 -1
  21. data/fastlane/lib/fastlane/actions/danger.rb +7 -1
  22. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +32 -12
  23. data/fastlane/lib/fastlane/actions/get_certificates.rb +5 -1
  24. data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +3 -1
  25. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +5 -1
  26. data/fastlane/lib/fastlane/actions/git_pull.rb +4 -10
  27. data/fastlane/lib/fastlane/actions/hipchat.rb +2 -1
  28. data/fastlane/lib/fastlane/actions/notification.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/register_device.rb +7 -10
  30. data/fastlane/lib/fastlane/actions/register_devices.rb +7 -10
  31. data/fastlane/lib/fastlane/actions/set_changelog.rb +7 -10
  32. data/fastlane/lib/fastlane/actions/swiftlint.rb +17 -15
  33. data/fastlane/lib/fastlane/actions/sync_code_signing.rb +6 -1
  34. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -1
  35. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +2 -1
  36. data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -5
  37. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +1 -1
  38. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  39. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -1
  40. data/fastlane/lib/fastlane/swift_fastlane_function.rb +6 -4
  41. data/fastlane/lib/fastlane/version.rb +1 -1
  42. data/fastlane/swift/Deliverfile.swift +1 -1
  43. data/fastlane/swift/DeliverfileProtocol.swift +20 -20
  44. data/fastlane/swift/Fastlane.swift +473 -247
  45. data/fastlane/swift/Gymfile.swift +1 -1
  46. data/fastlane/swift/GymfileProtocol.swift +1 -1
  47. data/fastlane/swift/Matchfile.swift +1 -1
  48. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  49. data/fastlane/swift/OptionalConfigValue.swift +2 -32
  50. data/fastlane/swift/Precheckfile.swift +1 -1
  51. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  52. data/fastlane/swift/Scanfile.swift +1 -1
  53. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  54. data/fastlane/swift/Screengrabfile.swift +1 -1
  55. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  56. data/fastlane/swift/Snapshotfile.swift +1 -1
  57. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  58. data/fastlane/swift/formatting/Brewfile.lock.json +11 -11
  59. data/fastlane_core/lib/fastlane_core/build_watcher.rb +39 -3
  60. data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +5 -0
  61. data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +5 -3
  62. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +1 -1
  63. data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
  64. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +4 -1
  65. data/frameit/lib/frameit/config_parser.rb +2 -2
  66. data/frameit/lib/frameit/frame_downloader.rb +2 -1
  67. data/gym/lib/gym/code_signing_mapping.rb +2 -2
  68. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +6 -5
  69. data/match/lib/match/importer.rb +6 -10
  70. data/match/lib/match/migrate.rb +2 -3
  71. data/match/lib/match/nuke.rb +3 -7
  72. data/match/lib/match/options.rb +1 -0
  73. data/match/lib/match/runner.rb +2 -3
  74. data/match/lib/match/spaceship_ensure.rb +3 -0
  75. data/match/lib/match/storage/google_cloud_storage.rb +2 -2
  76. data/match/lib/match/storage/s3_storage.rb +2 -2
  77. data/pilot/lib/pilot/build_manager.rb +7 -4
  78. data/pilot/lib/pilot/manager.rb +3 -7
  79. data/pilot/lib/pilot/options.rb +8 -0
  80. data/precheck/lib/precheck/runner.rb +8 -7
  81. data/scan/lib/scan/runner.rb +1 -1
  82. data/sigh/lib/assets/resign.sh +77 -46
  83. data/sigh/lib/sigh/download_all.rb +4 -8
  84. data/sigh/lib/sigh/runner.rb +4 -8
  85. data/spaceship/README.md +2 -2
  86. data/spaceship/lib/spaceship/connect_api/model.rb +1 -1
  87. data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +35 -4
  88. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +10 -0
  89. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +2 -3
  90. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +3 -1
  91. data/spaceship/lib/spaceship/connect_api/models/build.rb +2 -0
  92. data/spaceship/lib/spaceship/connect_api/token.rb +6 -0
  93. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +4 -2
  94. data/supply/lib/supply/client.rb +2 -2
  95. data/supply/lib/supply/uploader.rb +2 -2
  96. metadata +42 -39
@@ -91,9 +91,8 @@ module Match
91
91
  end
92
92
 
93
93
  def api_token(params)
94
- @api_token ||= Spaceship::ConnectAPI::Token.create(**params[:api_key]) if params[:api_key]
95
- @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
96
- return @api_token
94
+ api_token = Spaceship::ConnectAPI::Token.from(hash: params[:api_key], filepath: params[:api_key_path])
95
+ return api_token
97
96
  end
98
97
 
99
98
  def ensure_parameters_are_valid(params)
@@ -102,9 +102,11 @@ module Match
102
102
  end
103
103
 
104
104
  def spaceship_login
105
- if api_token
105
+ if (api_token = Spaceship::ConnectAPI::Token.from(hash: params[:api_key], filepath: params[:api_key_path]))
106
106
  UI.message("Creating authorization token for App Store Connect API")
107
107
  Spaceship::ConnectAPI.token = api_token
108
+ elsif !Spaceship::ConnectAPI.token.nil?
109
+ UI.message("Using existing authorization token for App Store Connect API")
108
110
  else
109
111
  Spaceship::ConnectAPI.login(params[:username], use_portal: true, use_tunes: false, portal_team_id: params[:team_id], team_name: params[:team_name])
110
112
  end
@@ -120,12 +122,6 @@ module Match
120
122
  end
121
123
  end
122
124
 
123
- def api_token
124
- @api_token ||= Spaceship::ConnectAPI::Token.create(**params[:api_key]) if params[:api_key]
125
- @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
126
- return @api_token
127
- end
128
-
129
125
  # Collect all the certs/profiles
130
126
  def prepare_list
131
127
  UI.message("Fetching certificates and profiles...")
@@ -207,6 +207,7 @@ module Match
207
207
  FastlaneCore::ConfigItem.new(key: :s3_secret_access_key,
208
208
  env_name: "MATCH_S3_SECRET_ACCESS_KEY",
209
209
  description: "S3 secret access key",
210
+ sensitive: true,
210
211
  optional: true),
211
212
  FastlaneCore::ConfigItem.new(key: :s3_bucket,
212
213
  env_name: "MATCH_S3_BUCKET",
@@ -139,9 +139,8 @@ module Match
139
139
  # rubocop:enable Metrics/PerceivedComplexity
140
140
 
141
141
  def api_token(params)
142
- @api_token ||= Spaceship::ConnectAPI::Token.create(**params[:api_key]) if params[:api_key]
143
- @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
144
- return @api_token
142
+ api_token = Spaceship::ConnectAPI::Token.from(hash: params[:api_key], filepath: params[:api_key_path])
143
+ return api_token
145
144
  end
146
145
 
147
146
  # Used when creating a new certificate or profile
@@ -13,6 +13,9 @@ module Match
13
13
  UI.message("Creating authorization token for App Store Connect API")
14
14
  Spaceship::ConnectAPI.token = api_token
15
15
  self.team_id = team_id
16
+ elsif !Spaceship::ConnectAPI.token.nil?
17
+ UI.message("Using existing authorization token for App Store Connect API")
18
+ self.team_id = team_id
16
19
  else
17
20
  # We'll try to manually fetch the password
18
21
  # to tell the user that a password is optional
@@ -123,8 +123,8 @@ module Match
123
123
  end
124
124
 
125
125
  def api_token
126
- api_token ||= Spaceship::ConnectAPI::Token.create(**self.api_key) if self.api_key
127
- api_token ||= Spaceship::ConnectAPI::Token.from_json_file(self.api_key_path) if self.api_key_path
126
+ api_token = Spaceship::ConnectAPI::Token.from(hash: self.api_key, filepath: self.api_key_path)
127
+ api_token ||= Spaceship::ConnectAPI.token
128
128
  return api_token
129
129
  end
130
130
 
@@ -196,8 +196,8 @@ module Match
196
196
  end
197
197
 
198
198
  def api_token
199
- api_token ||= Spaceship::ConnectAPI::Token.create(**self.api_key) if self.api_key
200
- api_token ||= Spaceship::ConnectAPI::Token.from_json_file(self.api_key_path) if self.api_key_path
199
+ api_token = Spaceship::ConnectAPI::Token.from(hash: self.api_key, filepath: self.api_key_path)
200
+ api_token ||= Spaceship::ConnectAPI.token
201
201
  return api_token
202
202
  end
203
203
  end
@@ -105,8 +105,10 @@ module Pilot
105
105
  app_version: app_version,
106
106
  build_version: app_build,
107
107
  poll_interval: config[:wait_processing_interval],
108
+ timeout_duration: config[:wait_processing_timeout_duration],
108
109
  return_when_build_appears: return_when_build_appears,
109
- return_spaceship_testflight_build: false
110
+ return_spaceship_testflight_build: false,
111
+ select_latest: config[:distribute_only]
110
112
  )
111
113
 
112
114
  unless latest_build.app_version == app_version && latest_build.version == app_build
@@ -365,6 +367,7 @@ module Pilot
365
367
  # If there are fewer than two teams, don't infer the provider.
366
368
  def transporter_for_selected_team(options)
367
369
  # Use JWT auth
370
+ api_token = Spaceship::ConnectAPI.token
368
371
  unless api_token.nil?
369
372
  api_token.refresh! if api_token.expired?
370
373
  return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text)
@@ -447,7 +450,7 @@ module Pilot
447
450
  end
448
451
 
449
452
  def update_review_detail(build, info)
450
- info = info.collect { |k, v| [k.to_sym, v] }.to_h
453
+ info = info.transform_keys(&:to_sym)
451
454
 
452
455
  attributes = {}
453
456
  attributes[:contactEmail] = info[:contact_email] if info.key?(:contact_email)
@@ -463,7 +466,7 @@ module Pilot
463
466
  end
464
467
 
465
468
  def update_localized_app_review(build, info_by_lang, default_info: nil)
466
- info_by_lang = info_by_lang.collect { |k, v| [k.to_sym, v] }.to_h
469
+ info_by_lang = info_by_lang.transform_keys(&:to_sym)
467
470
 
468
471
  if default_info
469
472
  info_by_lang.delete(:default)
@@ -509,7 +512,7 @@ module Pilot
509
512
  end
510
513
 
511
514
  def update_localized_build_review(build, info_by_lang, default_info: nil)
512
- info_by_lang = info_by_lang.collect { |k, v| [k.to_sym, v] }.to_h
515
+ info_by_lang = info_by_lang.transform_keys(&:to_sym)
513
516
 
514
517
  if default_info
515
518
  info_by_lang.delete(:default)
@@ -17,9 +17,11 @@ module Pilot
17
17
  end
18
18
 
19
19
  def login
20
- if api_token
20
+ if (api_token = Spaceship::ConnectAPI::Token.from(hash: config[:api_key], filepath: config[:api_key_path]))
21
21
  UI.message("Creating authorization token for App Store Connect API")
22
22
  Spaceship::ConnectAPI.token = api_token
23
+ elsif !Spaceship::ConnectAPI.token.nil?
24
+ UI.message("Using existing authorization token for App Store Connect API")
23
25
  else
24
26
  config[:username] ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
25
27
 
@@ -33,12 +35,6 @@ module Pilot
33
35
  end
34
36
  end
35
37
 
36
- def api_token
37
- @api_token ||= Spaceship::ConnectAPI::Token.create(**config[:api_key]) if config[:api_key]
38
- @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(config[:api_key_path]) if config[:api_key_path]
39
- return @api_token
40
- end
41
-
42
38
  # The app object we're currently using
43
39
  def app
44
40
  @app_id ||= fetch_app_id
@@ -286,6 +286,14 @@ module Pilot
286
286
  verify_block: proc do |value|
287
287
  UI.user_error!("Please enter a valid positive number of seconds") unless value.to_i > 0
288
288
  end),
289
+ FastlaneCore::ConfigItem.new(key: :wait_processing_timeout_duration,
290
+ env_name: "PILOT_WAIT_PROCESSING_TIMEOUT_DURATION",
291
+ description: "Timeout duration in seconds to wait for App Store Connect processing. If set, after exceeding timeout duration, this will `force stop` to wait for App Store Connect processing and exit with exception",
292
+ optional: true,
293
+ type: Integer,
294
+ verify_block: proc do |value|
295
+ UI.user_error!("Please enter a valid positive number of seconds") unless value.to_i > 0
296
+ end),
289
297
  FastlaneCore::ConfigItem.new(key: :wait_for_uploaded_build,
290
298
  env_name: "PILOT_WAIT_FOR_UPLOADED_BUILD",
291
299
  deprecated: "No longer needed with the transition over to the App Store Connect API",
@@ -18,6 +18,14 @@ module Precheck
18
18
  hide_keys: [:output_path],
19
19
  title: "Summary for precheck #{Fastlane::VERSION}")
20
20
 
21
+ api_token = if (token = Spaceship::ConnectAPI::Token.from(hash: Precheck.config[:api_key], filepath: Precheck.config[:api_key_path]))
22
+ UI.message("Creating authorization token for App Store Connect API")
23
+ token
24
+ elsif (token = Spaceship::ConnectAPI.token)
25
+ UI.message("Using existing authorization token for App Store Connect API")
26
+ token
27
+ end
28
+
21
29
  if api_token
22
30
 
23
31
  # As of 2020-09-15, App Store Connect API does not have support for IAPs yet
@@ -29,7 +37,6 @@ module Precheck
29
37
  UI.user_error!("Precheck cannot check In-app purchases with the App Store Connect API Key (yet). Exclude In-app purchases from precheck, disable the precheck step in your build step, or use Apple ID login")
30
38
  end
31
39
 
32
- UI.message("Creating authorization token for App Store Connect API")
33
40
  Spaceship::ConnectAPI.token = api_token
34
41
  elsif Spaceship::Tunes.client.nil?
35
42
  # Username is now optional since addition of App Store Connect API Key
@@ -75,12 +82,6 @@ module Precheck
75
82
  return true
76
83
  end
77
84
 
78
- def api_token
79
- @api_token ||= Spaceship::ConnectAPI::Token.create(**Precheck.config[:api_key]) if Precheck.config[:api_key]
80
- @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(Precheck.config[:api_key_path]) if Precheck.config[:api_key_path]
81
- return @api_token
82
- end
83
-
84
85
  def print_items_not_checked(processor_result: nil)
85
86
  names = processor_result.items_not_checked.map(&:friendly_name)
86
87
  UI.message("😶 Metadata fields not checked by any rule: #{names.join(', ')}".yellow) if names.length > 0
@@ -122,7 +122,7 @@ module Scan
122
122
  suites = failing_tests.split(/(?=\n\s+[\w\s]+:\n)/)
123
123
 
124
124
  suites.each do |suite|
125
- suite_name = suite.match(/\s*([\w\s]+):/).captures.first
125
+ suite_name = suite.match(/\s*([\w\s\S]+):/).captures.first
126
126
 
127
127
  test_cases = suite.split(":\n").fetch(1, []).split("\n").each
128
128
  .select { |line| line.match?(/^\s+/) }
@@ -75,6 +75,9 @@
75
75
  # new features August 2020
76
76
  # 1. fixes usage for users with GNU-sed in their $PATH
77
77
  #
78
+ # new features May 2021
79
+ # 1. fix entitlements merging when changing team
80
+ #
78
81
 
79
82
  # Logging functions
80
83
 
@@ -346,7 +349,7 @@ function provision_for_bundle_id {
346
349
  }
347
350
 
348
351
  # Find the bundle identifier contained inside a provisioning profile
349
- function bundle_id_for_provison {
352
+ function bundle_id_for_provision {
350
353
 
351
354
  local FULL_BUNDLE_ID=$(PlistBuddy -c 'Print :Entitlements:application-identifier' /dev/stdin <<< "$(security cms -D -i "$1")")
352
355
  checkStatus
@@ -384,7 +387,7 @@ function add_provision {
384
387
  error "Provisioning profile '$PROVISION' file does not exist"
385
388
  fi
386
389
 
387
- local BUNDLE_ID=$(bundle_id_for_provison "$PROVISION")
390
+ local BUNDLE_ID=$(bundle_id_for_provision "$PROVISION")
388
391
  add_provision_for_bundle_id "$PROVISION" "$BUNDLE_ID"
389
392
  }
390
393
 
@@ -434,7 +437,7 @@ function resign {
434
437
  error "Use the -p option (example: -p com.example.app=xxxx.mobileprovision)"
435
438
  fi
436
439
 
437
- local PROVISION_BUNDLE_IDENTIFIER=$(bundle_id_for_provison "$NEW_PROVISION")
440
+ local PROVISION_BUNDLE_IDENTIFIER=$(bundle_id_for_provision "$NEW_PROVISION")
438
441
 
439
442
  # Use provisioning profile's bundle identifier
440
443
  if [ "$BUNDLE_IDENTIFIER" == "" ]; then
@@ -580,7 +583,7 @@ function resign {
580
583
  # Found a reference bundle id, now get the corresponding provisioning profile for this bundle id
581
584
  REF_PROVISION=$(provision_for_bundle_id "$REF_BUNDLE_ID")
582
585
  # Map to the new bundle id
583
- NEW_REF_BUNDLE_ID=$(bundle_id_for_provison "$REF_PROVISION")
586
+ NEW_REF_BUNDLE_ID=$(bundle_id_for_provision "$REF_PROVISION")
584
587
  # Change if not the same and if doesn't contain wildcard
585
588
  # shellcheck disable=SC2049
586
589
  if [[ "$REF_BUNDLE_ID" != "$NEW_REF_BUNDLE_ID" ]] && ! [[ "$NEW_REF_BUNDLE_ID" =~ \* ]]; then
@@ -636,6 +639,20 @@ function resign {
636
639
  log "\nApp entitlements for ${APP_PATH}:"
637
640
  log "$(cat "$APP_ENTITLEMENTS")"
638
641
 
642
+ # Get the old and new app identifier (prefix)
643
+ APP_ID_KEY="application-identifier"
644
+ # Extract just the identifier from the value
645
+ # Use the fact that we are after some identifer, which is always at the start of the string
646
+ OLD_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$APP_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
647
+ NEW_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
648
+
649
+ # Get the old and the new team ID
650
+ # Old team ID is not part of app entitlements, have to get it from old embedded provisioning profile
651
+ security cms -D -i "$TEMP_DIR/old-embedded.mobileprovision" > "$TEMP_DIR/old-embedded-profile.plist"
652
+ OLD_TEAM_ID=$(PlistBuddy -c "Print :TeamIdentifier:0" "$TEMP_DIR/old-embedded-profile.plist")
653
+ # New team ID is part of profile entitlements
654
+ NEW_TEAM_ID=$(PlistBuddy -c "Print com.apple.developer.team-identifier" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
655
+
639
656
  log "Patching profile entitlements with values from app entitlements"
640
657
  PATCHED_ENTITLEMENTS="$TEMP_DIR/patchedEntitlements"
641
658
  # Start with using what comes in provisioning profile entitlements before patching
@@ -654,20 +671,14 @@ function resign {
654
671
  "com.apple.developer.icloud-container-development-container-identifiers" \
655
672
  # This key has an invalid generic value in PP (actual value is set by Xcode during export), see dedicated processing a few blocks below
656
673
  "com.apple.developer.icloud-container-environment" \
657
- # PP list identifiers inconsistent with app-defined ones, must use App entitlements value
658
- "com.apple.developer.icloud-container-identifiers" \
659
674
  # PP enable all available services and not app-defined ones, must use App entitlements value
660
675
  "com.apple.developer.icloud-services" \
661
676
  # Was already denylisted in previous version, but has someone ever seen this key in a PP?
662
677
  "com.apple.developer.restricted-resource-mode" \
663
678
  # If actually used by the App, this value will be set in its entitlements
664
679
  "com.apple.developer.nfc.readersession.formats" \
665
- # PP list a single TeamID.* identifier and not app-defined ones, must use App entitlements value
666
- "com.apple.developer.pass-type-identifiers" \
667
680
  # If actually used by the App, this value will be set in its entitlements
668
681
  "com.apple.developer.siri" \
669
- # PP list identifiers inconsistent with app-defined ones, must use App entitlements value
670
- "com.apple.developer.ubiquity-container-identifiers" \
671
682
  # PP define a generic TeamID.* identifier and not the app-defined one, must use App entitlements value
672
683
  "com.apple.developer.ubiquity-kvstore-identifier" \
673
684
  # If actually used by the App, this value will be set in its entitlements
@@ -680,8 +691,6 @@ function resign {
680
691
  "com.apple.developer.healthkit" \
681
692
  # If actually used by the App, this value will be set in its entitlements
682
693
  "com.apple.developer.healthkit.access" \
683
- # PP list identifiers inconsistent with app-defined ones, must use App entitlements value
684
- "com.apple.developer.in-app-payments" \
685
694
  # If actually used by the App, this value will be set in its entitlements
686
695
  "com.apple.developer.networking.vpn.api" \
687
696
  # If actually used by the App, this value will be set in its entitlements
@@ -694,40 +703,45 @@ function resign {
694
703
  "com.apple.developer.associated-domains" \
695
704
  # If actually used by the App, this value will be set in its entitlements
696
705
  "com.apple.developer.default-data-protection" \
697
- # PP seem to list the same groups as the App, but use App entitlements value to be sure
698
- "com.apple.security.application-groups" \
699
706
  # Was already denylisted in previous version, seems to be an artifact from an old Xcode release
700
707
  "com.apple.developer.maps" \
701
708
  # If actually used by the App, this value will be set in its entitlements
702
709
  "com.apple.external-accessory.wireless-configuration"
703
710
  )
704
711
 
712
+ # If we change team while resigning, we have no other choice than to use the following entitlements from the PP instead of the App
713
+ # because they are based on unique identifiers (defined in the developer portal) that can't be shared between teams
714
+ if [[ "$OLD_TEAM_ID" != "$NEW_TEAM_ID" ]]; then
715
+ warning "WARNING: Changing team while resigning"
716
+ warning "WARNING: Using these entitlements from the provisioning profile instead of the existing app:"
717
+ warning "WARNING: App Groups, Merchant IDs (Apple Pay In-App Payments), iCloud Containers, Pass Type IDs (Wallet)"
718
+ warning "WARNING: If these capabilities are enabled, make sure AppID and provisioning profile are properly configured"
719
+ # For Pass Types, PP only list a single TeamID.* identifier and not the potential restricted list defined in the existing App
720
+ # but we can't guess the new identifiers to be used, so this generic value is better than nothing and should be fine for most apps
721
+ warning "WARNING: Resigned app will allow all pass types from the new team, even if old app only allowed a restricted list"
722
+ else
723
+ DENYLISTED_KEYS+=(\
724
+ "com.apple.security.application-groups" \
725
+ "com.apple.developer.in-app-payments" \
726
+ "com.apple.developer.ubiquity-container-identifiers" \
727
+ "com.apple.developer.icloud-container-identifiers" \
728
+ "com.apple.developer.pass-type-identifiers" \
729
+ )
730
+ fi
731
+
705
732
  # Denylisted keys must not be included into new profile, so remove them from patched profile
706
733
  for KEY in "${DENYLISTED_KEYS[@]}"; do
707
734
  log "Removing denylisted key: $KEY"
708
735
  PlistBuddy -c "Delete $KEY" "$PATCHED_ENTITLEMENTS" 2>/dev/null
709
736
  done
710
737
 
711
- # Get the old and new app identifier (prefix)
712
- APP_ID_KEY="application-identifier"
713
- # Extract just the identifier from the value
714
- # Use the fact that we are after some identifier, which is always at the start of the string
715
- OLD_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$APP_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
716
- NEW_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
717
-
718
- # Get the old and the new team ID
719
- # Old team ID is not part of app entitlements, have to get it from old embedded provisioning profile
720
- security cms -D -i "$TEMP_DIR/old-embedded.mobileprovision" > "$TEMP_DIR/old-embedded-profile.plist"
721
- OLD_TEAM_ID=$(PlistBuddy -c "Print :TeamIdentifier:0" "$TEMP_DIR/old-embedded-profile.plist")
722
- # New team ID is part of profile entitlements
723
- NEW_TEAM_ID=$(PlistBuddy -c "Print com.apple.developer.team-identifier" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n')
724
-
725
738
  # List of rules for transferring entitlements from app to profile plist
726
739
  # The format for each enty is "KEY[|ID_TYPE]"
727
740
  # Where KEY is the plist key, e.g. "keychain-access-groups"
728
741
  # and ID_TYPE is optional part separated by '|' that specifies what value to patch:
729
742
  # TEAM_ID - patch the TeamIdentifierPrefix
730
743
  # APP_ID - patch the AppIdentifierPrefix
744
+ # ICLOUD_ENV - patch the target iCloud Environment
731
745
  # Patching means replacing old value from app entitlements with new value from provisioning profile
732
746
  # For example, for KEY=keychain-access-groups the ID_TYPE=APP_ID
733
747
  # Which means that old app ID prefix in keychain-access-groups will be replaced with new app ID prefix
@@ -740,23 +754,32 @@ function resign {
740
754
  "com.apple.developer.healthkit" \
741
755
  "com.apple.developer.healthkit.access" \
742
756
  "com.apple.developer.homekit" \
743
- "com.apple.developer.icloud-container-environment" \
744
- "com.apple.developer.icloud-container-identifiers" \
757
+ "com.apple.developer.icloud-container-environment|ICLOUD_ENV" \
745
758
  "com.apple.developer.icloud-services" \
746
- "com.apple.developer.in-app-payments" \
747
759
  "com.apple.developer.networking.HotspotConfiguration" \
748
760
  "com.apple.developer.networking.multipath" \
749
761
  "com.apple.developer.networking.networkextension" \
750
762
  "com.apple.developer.networking.vpn.api" \
751
763
  "com.apple.developer.nfc.readersession.formats" \
752
- "com.apple.developer.pass-type-identifiers|TEAM_ID" \
753
764
  "com.apple.developer.siri" \
754
- "com.apple.developer.ubiquity-container-identifiers" \
755
765
  "com.apple.developer.ubiquity-kvstore-identifier|TEAM_ID" \
756
766
  "com.apple.external-accessory.wireless-configuration" \
757
- "com.apple.security.application-groups" \
758
767
  "inter-app-audio" \
759
- "keychain-access-groups|APP_ID")
768
+ "keychain-access-groups|APP_ID" \
769
+ )
770
+
771
+ # If we change team while resigning, we have no other choice than to use the following entitlements from the PP instead of the App
772
+ # because they are based on unique identifiers (defined in the developer portal) that can't be shared between teams
773
+ # If we don't change team while resigning, we should use the following entitlements from the existing App and not from the PP
774
+ if [[ "$OLD_TEAM_ID" == "$NEW_TEAM_ID" ]]; then
775
+ ENTITLEMENTS_TRANSFER_RULES+=(\
776
+ "com.apple.security.application-groups" \
777
+ "com.apple.developer.in-app-payments" \
778
+ "com.apple.developer.ubiquity-container-identifiers" \
779
+ "com.apple.developer.icloud-container-identifiers" \
780
+ "com.apple.developer.pass-type-identifiers|TEAM_ID" \
781
+ )
782
+ fi
760
783
 
761
784
  # Loop over all the entitlement keys that need to be transferred from app entitlements
762
785
  for RULE in "${ENTITLEMENTS_TRANSFER_RULES[@]}"; do
@@ -771,7 +794,19 @@ function resign {
771
794
  continue
772
795
  fi
773
796
 
774
- if [[ "$KEY" == "com.apple.developer.icloud-container-environment" ]]; then
797
+ log "App entitlements value for key '$KEY':"
798
+ log "$ENTITLEMENTS_VALUE"
799
+
800
+ # Patch the ID value if specified
801
+ if [[ "$ID_TYPE" == "APP_ID" ]]; then
802
+ # Replace old value with new value in patched entitlements
803
+ log "Replacing old app ID '$OLD_APP_ID' with new app ID '$NEW_APP_ID'"
804
+ ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | sed "s/$OLD_APP_ID/$NEW_APP_ID/g")
805
+ elif [[ "$ID_TYPE" == "TEAM_ID" ]]; then
806
+ # Replace old team identifier with new value
807
+ log "Replacing old team ID '$OLD_TEAM_ID' with new team ID '$NEW_TEAM_ID'"
808
+ ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | sed "s/$OLD_TEAM_ID/$NEW_TEAM_ID/g")
809
+ elif [[ "$ID_TYPE" == "ICLOUD_ENV" ]]; then
775
810
  # Add specific iCloud Environment key to patched entitlements
776
811
  # This value is set by Xcode during export (manually selected for Development and AdHoc, automatically set to Production for Store)
777
812
  # Would need an additional dedicated option to specify the iCloud environment to be used (Development or Production)
@@ -788,20 +823,16 @@ function resign {
788
823
  fi
789
824
  fi
790
825
 
826
+ OLD_ICLOUD_ENV=$(echo "$ENTITLEMENTS_VALUE" | sed -e 's,<string>\(.*\)</string>,\1,g')
791
827
  if [[ "$certificate_name" =~ "Distribution:" ]]; then
792
- ICLOUD_ENV="Production"
828
+ NEW_ICLOUD_ENV="Production"
793
829
  else
794
- ICLOUD_ENV="Development"
830
+ NEW_ICLOUD_ENV="Development"
795
831
  fi
796
- log "Overriding value for $KEY"
797
- log "Old value: $ENTITLEMENTS_VALUE"
798
- log "New value: $ICLOUD_ENV"
799
- ENTITLEMENTS_VALUE="$ICLOUD_ENV"
832
+ log "Replacing iCloud environment '$OLD_ICLOUD_ENV' with '$NEW_ICLOUD_ENV'"
833
+ ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | sed "s/$OLD_ICLOUD_ENV/$NEW_ICLOUD_ENV/g")
800
834
  fi
801
835
 
802
- log "App entitlements value for key '$KEY':"
803
- log "$ENTITLEMENTS_VALUE"
804
-
805
836
  # Remove the entry for current key from profisioning profile entitlements (if exists)
806
837
  PlistBuddy -c "Delete $KEY" "$PATCHED_ENTITLEMENTS" 2>/dev/null
807
838
 
@@ -830,7 +861,7 @@ function resign {
830
861
  # Replace old bundle ID with new bundle ID in patched entitlements
831
862
  # Read old bundle ID from the old Info.plist which was saved for this purpose
832
863
  OLD_BUNDLE_ID="$(PlistBuddy -c "Print :CFBundleIdentifier" "$TEMP_DIR/oldInfo.plist")"
833
- NEW_BUNDLE_ID="$(bundle_id_for_provison "$NEW_PROVISION")"
864
+ NEW_BUNDLE_ID="$(bundle_id_for_provision "$NEW_PROVISION")"
834
865
  log "Replacing old bundle ID '$OLD_BUNDLE_ID' with new bundle ID '$NEW_BUNDLE_ID' in patched entitlements"
835
866
  # Note: ideally we'd match against the opening <string> tag too, but this isn't possible
836
867
  # because $OLD_BUNDLE_ID and $NEW_BUNDLE_ID do not include the team ID prefix which is