fastlane 2.168.0 → 2.173.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +68 -68
  3. data/cert/lib/cert/options.rb +2 -2
  4. data/deliver/lib/deliver/app_screenshot.rb +5 -7
  5. data/deliver/lib/deliver/app_screenshot_validator.rb +108 -0
  6. data/deliver/lib/deliver/commands_generator.rb +1 -1
  7. data/deliver/lib/deliver/loader.rb +123 -21
  8. data/deliver/lib/deliver/setup.rb +8 -3
  9. data/deliver/lib/deliver/upload_metadata.rb +6 -10
  10. data/deliver/lib/deliver/upload_screenshots.rb +1 -64
  11. data/fastlane/lib/fastlane/actions/add_git_tag.rb +12 -3
  12. data/fastlane/lib/fastlane/actions/artifactory.rb +36 -3
  13. data/fastlane/lib/fastlane/actions/build_app.rb +3 -1
  14. data/fastlane/lib/fastlane/actions/create_pull_request.rb +16 -1
  15. data/fastlane/lib/fastlane/actions/create_xcframework.rb +118 -0
  16. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +1 -1
  17. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +1 -1
  18. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +4 -0
  19. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +5 -1
  20. data/fastlane/lib/fastlane/actions/download_app_privacy_details_from_app_store.rb +142 -0
  21. data/fastlane/lib/fastlane/actions/download_dsyms.rb +0 -1
  22. data/fastlane/lib/fastlane/actions/git_commit.rb +6 -2
  23. data/fastlane/lib/fastlane/actions/github_api.rb +14 -3
  24. data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
  25. data/fastlane/lib/fastlane/actions/onesignal.rb +13 -3
  26. data/fastlane/lib/fastlane/actions/pod_push.rb +9 -0
  27. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -1
  28. data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
  29. data/fastlane/lib/fastlane/actions/register_devices.rb +2 -1
  30. data/fastlane/lib/fastlane/actions/set_github_release.rb +21 -8
  31. data/fastlane/lib/fastlane/actions/slack.rb +4 -5
  32. data/fastlane/lib/fastlane/actions/spm.rb +2 -2
  33. data/fastlane/lib/fastlane/actions/swiftlint.rb +4 -4
  34. data/fastlane/lib/fastlane/actions/upload_app_privacy_details_to_app_store.rb +291 -0
  35. data/fastlane/lib/fastlane/actions/xcode_install.rb +8 -5
  36. data/fastlane/lib/fastlane/cli_tools_distributor.rb +3 -0
  37. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -1
  38. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +3 -0
  39. data/fastlane/lib/fastlane/version.rb +1 -1
  40. data/fastlane/swift/Deliverfile.swift +2 -2
  41. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  42. data/fastlane/swift/Fastlane.swift +267 -45
  43. data/fastlane/swift/Gymfile.swift +2 -2
  44. data/fastlane/swift/GymfileProtocol.swift +15 -3
  45. data/fastlane/swift/Matchfile.swift +2 -2
  46. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  47. data/fastlane/swift/Precheckfile.swift +2 -2
  48. data/fastlane/swift/PrecheckfileProtocol.swift +6 -2
  49. data/fastlane/swift/Scanfile.swift +2 -2
  50. data/fastlane/swift/ScanfileProtocol.swift +18 -2
  51. data/fastlane/swift/Screengrabfile.swift +2 -2
  52. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  53. data/fastlane/swift/Snapshotfile.swift +2 -2
  54. data/fastlane/swift/SnapshotfileProtocol.swift +15 -3
  55. data/fastlane_core/lib/fastlane_core/helper.rb +2 -2
  56. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +41 -16
  57. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +3 -4
  58. data/fastlane_core/lib/fastlane_core/project.rb +19 -6
  59. data/frameit/lib/frameit/device_types.rb +7 -1
  60. data/gym/lib/gym/error_handler.rb +8 -0
  61. data/gym/lib/gym/generators/build_command_generator.rb +3 -0
  62. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +2 -2
  63. data/gym/lib/gym/options.rb +19 -3
  64. data/match/lib/match/encryption/openssl.rb +4 -2
  65. data/match/lib/match/runner.rb +1 -1
  66. data/match/lib/match/storage/git_storage.rb +14 -10
  67. data/precheck/lib/precheck/options.rb +6 -1
  68. data/precheck/lib/precheck/rule_processor.rb +1 -1
  69. data/precheck/lib/precheck/runner.rb +1 -1
  70. data/scan/lib/scan/options.rb +22 -1
  71. data/scan/lib/scan/runner.rb +6 -1
  72. data/scan/lib/scan/slack_poster.rb +4 -1
  73. data/scan/lib/scan/test_command_generator.rb +3 -0
  74. data/screengrab/lib/screengrab/runner.rb +2 -0
  75. data/sigh/lib/sigh/runner.rb +1 -1
  76. data/snapshot/lib/assets/SnapshotHelper.swift +6 -2
  77. data/snapshot/lib/snapshot/options.rb +17 -2
  78. data/snapshot/lib/snapshot/update.rb +1 -1
  79. data/spaceship/lib/spaceship/client.rb +28 -1
  80. data/spaceship/lib/spaceship/connect_api.rb +6 -0
  81. data/spaceship/lib/spaceship/connect_api/api_client.rb +1 -1
  82. data/spaceship/lib/spaceship/connect_api/models/app.rb +19 -4
  83. data/spaceship/lib/spaceship/connect_api/models/app_data_usage.rb +59 -0
  84. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_category.rb +65 -0
  85. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_data_protection.rb +27 -0
  86. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_grouping.rb +18 -0
  87. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_purposes.rb +37 -0
  88. data/spaceship/lib/spaceship/connect_api/models/app_data_usages_publish_state.rb +36 -0
  89. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +1 -0
  90. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +2 -0
  91. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +8 -1
  92. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +9 -0
  93. data/spaceship/lib/spaceship/connect_api/models/device.rb +30 -0
  94. data/spaceship/lib/spaceship/connect_api/response.rb +3 -1
  95. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +12 -0
  96. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +103 -0
  97. data/spaceship/lib/spaceship/errors.rb +19 -0
  98. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +19 -6
  99. data/spaceship/lib/spaceship/upgrade_2fa_later_client.rb +91 -0
  100. metadata +44 -23
  101. data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
  102. data/spaceship/lib/spaceship/connect_api/models/.app.rb.swp +0 -0
  103. data/spaceship/lib/spaceship/connect_api/models/.app_screenshot.rb.swp +0 -0
  104. data/spaceship/lib/spaceship/connect_api/models/.build.rb.swp +0 -0
@@ -46,7 +46,7 @@ module Deliver
46
46
  v = app.get_latest_app_store_version(platform: platform)
47
47
 
48
48
  metadata_path = options[:metadata_path] || File.join(deliver_path, 'metadata')
49
- generate_metadata_files(app, v, metadata_path)
49
+ generate_metadata_files(app, v, metadata_path, options)
50
50
 
51
51
  # Generate the final Deliverfile here
52
52
  return File.read(deliverfile_path)
@@ -60,9 +60,14 @@ module Deliver
60
60
  end
61
61
  end
62
62
 
63
- def generate_metadata_files(app, version, path)
63
+ def generate_metadata_files(app, version, path, options)
64
64
  # App info localizations
65
- app_info = app.fetch_live_app_info || app.fetch_edit_app_info
65
+ if options[:use_live_version]
66
+ app_info = app.fetch_live_app_info
67
+ UI.user_error!("The option `use_live_version` was set to `true`, however no live app was found on App Store Connect.") unless app_info
68
+ else
69
+ app_info = app.fetch_edit_app_info || app.fetch_live_app_info
70
+ end
66
71
  app_info_localizations = app_info.get_app_info_localizations
67
72
  app_info_localizations.each do |localization|
68
73
  language = localization.locale
@@ -1,3 +1,5 @@
1
+ require 'spaceship'
2
+
1
3
  require_relative 'module'
2
4
  require_relative 'queue_worker'
3
5
 
@@ -375,9 +377,7 @@ module Deliver
375
377
  # Check folder list (an empty folder signifies a language is required)
376
378
  ignore_validation = options[:ignore_language_directory_validation]
377
379
  Loader.language_folders(options[:metadata_path], ignore_validation).each do |lang_folder|
378
- next unless File.directory?(lang_folder) # We don't want to read txt as they are non localised
379
- language = File.basename(lang_folder)
380
- enabled_languages << language unless enabled_languages.include?(language)
380
+ enabled_languages << lang_folder.basename unless enabled_languages.include?(lang_folder.basename)
381
381
  end
382
382
 
383
383
  return unless enabled_languages.include?("default")
@@ -416,10 +416,7 @@ module Deliver
416
416
  # Check folder list (an empty folder signifies a language is required)
417
417
  ignore_validation = options[:ignore_language_directory_validation]
418
418
  Loader.language_folders(options[:metadata_path], ignore_validation).each do |lang_folder|
419
- next unless File.directory?(lang_folder) # We don't want to read txt as they are non localised
420
-
421
- language = File.basename(lang_folder)
422
- enabled_languages << language unless enabled_languages.include?(language)
419
+ enabled_languages << lang_folder.basename unless enabled_languages.include?(lang_folder.basename)
423
420
  end
424
421
 
425
422
  # Mapping to strings because :default symbol can be passed in
@@ -530,14 +527,13 @@ module Deliver
530
527
  # Load localised data
531
528
  ignore_validation = options[:ignore_language_directory_validation]
532
529
  Loader.language_folders(options[:metadata_path], ignore_validation).each do |lang_folder|
533
- language = File.basename(lang_folder)
534
530
  (LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
535
- path = File.join(lang_folder, "#{key}.txt")
531
+ path = File.join(lang_folder.path, "#{key}.txt")
536
532
  next unless File.exist?(path)
537
533
 
538
534
  UI.message("Loading '#{path}'...")
539
535
  options[key] ||= {}
540
- options[key][language] ||= File.read(path)
536
+ options[key][lang_folder.basename] ||= File.read(path)
541
537
  end
542
538
  end
543
539
 
@@ -251,70 +251,7 @@ module Deliver
251
251
 
252
252
  def collect_screenshots(options)
253
253
  return [] if options[:skip_screenshots]
254
- return collect_screenshots_for_languages(options[:screenshots_path], options[:ignore_language_directory_validation])
255
- end
256
-
257
- def collect_screenshots_for_languages(path, ignore_validation)
258
- screenshots = []
259
- extensions = '{png,jpg,jpeg}'
260
-
261
- available_languages = UploadScreenshots.available_languages.each_with_object({}) do |lang, lang_hash|
262
- lang_hash[lang.downcase] = lang
263
- end
264
-
265
- Loader.language_folders(path, ignore_validation).each do |lng_folder|
266
- language = File.basename(lng_folder)
267
-
268
- # Check to see if we need to traverse multiple platforms or just a single platform
269
- if language == Loader::APPLE_TV_DIR_NAME || language == Loader::IMESSAGE_DIR_NAME
270
- screenshots.concat(collect_screenshots_for_languages(File.join(path, language), ignore_validation))
271
- next
272
- end
273
-
274
- files = Dir.glob(File.join(lng_folder, "*.#{extensions}"), File::FNM_CASEFOLD).sort
275
- next if files.count == 0
276
-
277
- framed_screenshots_found = Dir.glob(File.join(lng_folder, "*_framed.#{extensions}"), File::FNM_CASEFOLD).count > 0
278
-
279
- UI.important("Framed screenshots are detected! 🖼 Non-framed screenshot files may be skipped. 🏃") if framed_screenshots_found
280
-
281
- language_dir_name = File.basename(lng_folder)
282
-
283
- if available_languages[language_dir_name.downcase].nil?
284
- UI.user_error!("#{language_dir_name} is not an available language. Please verify that your language codes are available in iTunesConnect. See https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/AppStoreTerritories.html for more information.")
285
- end
286
-
287
- language = available_languages[language_dir_name.downcase]
288
-
289
- files.each do |file_path|
290
- is_framed = file_path.downcase.include?("_framed.")
291
- is_watch = file_path.downcase.include?("watch")
292
-
293
- if framed_screenshots_found && !is_framed && !is_watch
294
- UI.important("🏃 Skipping screenshot file: #{file_path}")
295
- next
296
- end
297
-
298
- screenshots << AppScreenshot.new(file_path, language)
299
- end
300
- end
301
-
302
- # Checking if the device type exists in spaceship
303
- # Ex: iPhone 6.1 inch isn't supported in App Store Connect but need
304
- # to have it in there for frameit support
305
- unaccepted_device_shown = false
306
- screenshots.select! do |screenshot|
307
- exists = !screenshot.device_type.nil?
308
- unless exists
309
- UI.important("Unaccepted device screenshots are detected! 🚫 Screenshot file will be skipped. 🏃") unless unaccepted_device_shown
310
- unaccepted_device_shown = true
311
-
312
- UI.important("🏃 Skipping screenshot file: #{screenshot.path} - Not an accepted App Store Connect device...")
313
- end
314
- exists
315
- end
316
-
317
- return screenshots
254
+ return Loader.load_app_screenshots(options[:screenshots_path], options[:ignore_language_directory_validation])
318
255
  end
319
256
 
320
257
  # helper method so Spaceship::Tunes.client.available_languages is easier to test
@@ -9,7 +9,10 @@ module Fastlane
9
9
  if options[:tag]
10
10
  tag = options[:tag]
11
11
  elsif options[:build_number]
12
- tag = "#{options[:grouping]}/#{lane_name}/#{options[:prefix]}#{options[:build_number]}#{options[:postfix]}"
12
+ tag_components = [options[:grouping]]
13
+ tag_components << lane_name if options[:includes_lane]
14
+ tag_components << "#{options[:prefix]}#{options[:build_number]}#{options[:postfix]}"
15
+ tag = tag_components.join('/')
13
16
  else
14
17
  UI.user_error!("No value found for 'tag' or 'build_number'. At least one of them must be provided. Note that if you do specify a tag, all other arguments are ignored.")
15
18
  end
@@ -34,14 +37,14 @@ module Fastlane
34
37
  def self.details
35
38
  list = <<-LIST.markdown_list
36
39
  `grouping` is just to keep your tags organised under one 'folder', defaults to 'builds'
37
- `lane` is the name of the current fastlane lane
40
+ `lane` is the name of the current fastlane lane, if chosen to be included via 'includes_lane' option, which defaults to 'true'
38
41
  `prefix` is anything you want to stick in front of the version number, e.g. 'v'
39
42
  `postfix` is anything you want to stick at the end of the version number, e.g. '-RC1'
40
43
  `build_number` is the build number, which defaults to the value emitted by the `increment_build_number` action
41
44
  LIST
42
45
 
43
46
  [
44
- "This will automatically tag your build with the following format: `<grouping>/<lane>/<prefix><build_number>`, where:".markdown_preserve_newlines,
47
+ "This will automatically tag your build with the following format: `<grouping>/<lane>/<prefix><build_number><postfix>`, where:".markdown_preserve_newlines,
45
48
  list,
46
49
  "For example, for build 1234 in the 'appstore' lane, it will tag the commit with `builds/appstore/1234`."
47
50
  ].join("\n")
@@ -57,6 +60,11 @@ module Fastlane
57
60
  env_name: "FL_GIT_TAG_GROUPING",
58
61
  description: "Is used to keep your tags organised under one 'folder'",
59
62
  default_value: 'builds'),
63
+ FastlaneCore::ConfigItem.new(key: :includes_lane,
64
+ env_name: "FL_GIT_TAG_INCLUDES_LANE",
65
+ description: "Whether the current lane should be included in the tag and message composition, e.g. '<grouping>/<lane>/<prefix><build_number><postfix>'",
66
+ is_string: false,
67
+ default_value: true),
60
68
  FastlaneCore::ConfigItem.new(key: :prefix,
61
69
  env_name: "FL_GIT_TAG_PREFIX",
62
70
  description: "Anything you want to put in front of the version number (e.g. 'v')",
@@ -102,6 +110,7 @@ module Fastlane
102
110
  'add_git_tag # simple tag with default values',
103
111
  'add_git_tag(
104
112
  grouping: "fastlane-builds",
113
+ includes_lane: true,
105
114
  prefix: "v",
106
115
  postfix: "-RC1",
107
116
  build_number: 123
@@ -10,7 +10,12 @@ module Fastlane
10
10
  Actions.verify_gem!('artifactory')
11
11
 
12
12
  require 'artifactory'
13
+
14
+ UI.user_error!("Cannot connect to Artifactory - 'username' was provided but it's missing 'password'") if params[:username] && !params[:password]
15
+ UI.user_error!("Cannot connect to Artifactory - 'password' was provided but it's missing 'username'") if !params[:username] && params[:password]
16
+ UI.user_error!("Cannot connect to Artifactory - either 'api_key', or 'username' and 'password' must be provided") if !params[:api_key] && !params[:username]
13
17
  file_path = File.absolute_path(params[:file])
18
+
14
19
  if File.exist?(file_path)
15
20
  client = connect_to_artifactory(params)
16
21
  artifact = Artifactory::Resource::Artifact.new
@@ -37,7 +42,7 @@ module Fastlane
37
42
  end
38
43
 
39
44
  def self.connect_to_artifactory(params)
40
- config_keys = [:endpoint, :username, :password, :ssl_pem_file, :ssl_verify, :proxy_username, :proxy_password, :proxy_address, :proxy_port, :read_timeout]
45
+ config_keys = [:endpoint, :username, :password, :api_key, :ssl_pem_file, :ssl_verify, :proxy_username, :proxy_password, :proxy_address, :proxy_port, :read_timeout]
41
46
  config = params.values.select do |key|
42
47
  config_keys.include?(key)
43
48
  end
@@ -48,6 +53,10 @@ module Fastlane
48
53
  'This action uploads an artifact to artifactory'
49
54
  end
50
55
 
56
+ def self.details
57
+ 'Connect to the artifactory server using either a username/password or an api_key'
58
+ end
59
+
51
60
  def self.is_supported?(platform)
52
61
  true
53
62
  end
@@ -72,6 +81,13 @@ module Fastlane
72
81
  file: "example.ipa", # File to upload
73
82
  repo: "mobile_artifacts", # Artifactory repo
74
83
  repo_path: "/ios/appname/example-major.minor.ipa" # Path to place the artifact including its filename
84
+ )',
85
+ 'artifactory(
86
+ api_key: "api_key",
87
+ endpoint: "https://artifactory.example.com/artifactory/",
88
+ file: "example.ipa", # File to upload
89
+ repo: "mobile_artifacts", # Artifactory repo
90
+ repo_path: "/ios/appname/example-major.minor.ipa" # Path to place the artifact including its filename
75
91
  )'
76
92
  ]
77
93
  end
@@ -101,12 +117,29 @@ module Fastlane
101
117
  FastlaneCore::ConfigItem.new(key: :username,
102
118
  env_name: "FL_ARTIFACTORY_USERNAME",
103
119
  description: "Artifactory username",
104
- optional: false),
120
+ optional: true,
121
+ conflicting_options: [:api_key],
122
+ conflict_block: proc do |value|
123
+ UI.user_error!("You can't use option '#{value.key}' along with 'username'")
124
+ end),
105
125
  FastlaneCore::ConfigItem.new(key: :password,
106
126
  env_name: "FL_ARTIFACTORY_PASSWORD",
107
127
  description: "Artifactory password",
108
128
  sensitive: true,
109
- optional: false),
129
+ optional: true,
130
+ conflicting_options: [:api_key],
131
+ conflict_block: proc do |value|
132
+ UI.user_error!("You can't use option '#{value.key}' along with 'password'")
133
+ end),
134
+ FastlaneCore::ConfigItem.new(key: :api_key,
135
+ env_name: "FL_ARTIFACTORY_API_KEY",
136
+ description: "Artifactory API key",
137
+ sensitive: true,
138
+ optional: true,
139
+ conflicting_options: [:username, :password],
140
+ conflict_block: proc do |value|
141
+ UI.user_error!("You can't use option '#{value.key}' along with 'api_key'")
142
+ end),
110
143
  FastlaneCore::ConfigItem.new(key: :properties,
111
144
  env_name: "FL_ARTIFACTORY_PROPERTIES",
112
145
  description: "Artifact properties hash",
@@ -8,6 +8,7 @@ module Fastlane
8
8
  end
9
9
 
10
10
  class BuildAppAction < Action
11
+ # rubocop:disable Metrics/PerceivedComplexity
11
12
  def self.run(values)
12
13
  require 'gym'
13
14
 
@@ -50,7 +51,8 @@ module Fastlane
50
51
  begin
51
52
  profile = FastlaneCore::ProvisioningProfile.parse(profile_path)
52
53
  app_id_prefix = profile["ApplicationIdentifierPrefix"].first
53
- bundle_id = profile["Entitlements"]["application-identifier"].gsub("#{app_id_prefix}.", "")
54
+ entitlements = profile["Entitlements"]
55
+ bundle_id = (entitlements["application-identifier"] || entitlements["com.apple.application-identifier"]).gsub("#{app_id_prefix}.", "")
54
56
  values[:export_options][:provisioningProfiles][bundle_id] = profile["Name"]
55
57
  rescue => ex
56
58
  UI.error("Couldn't load profile at path: #{profile_path}")
@@ -20,6 +20,7 @@ module Fastlane
20
20
  GithubApiAction.run(
21
21
  server_url: params[:api_url],
22
22
  api_token: params[:api_token],
23
+ api_bearer: params[:api_bearer],
23
24
  http_method: 'POST',
24
25
  path: "repos/#{params[:repo]}/pulls",
25
26
  body: payload,
@@ -60,6 +61,7 @@ module Fastlane
60
61
  GithubApiAction.run(
61
62
  server_url: params[:api_url],
62
63
  api_token: params[:api_token],
64
+ api_bearer: params[:api_bearer],
63
65
  http_method: 'PATCH',
64
66
  path: "repos/#{params[:repo]}/issues/#{number}",
65
67
  body: payload,
@@ -79,6 +81,7 @@ module Fastlane
79
81
  GithubApiAction.run(
80
82
  server_url: params[:api_url],
81
83
  api_token: params[:api_token],
84
+ api_bearer: params[:api_bearer],
82
85
  http_method: 'POST',
83
86
  path: "repos/#{params[:repo]}/issues/#{number}/assignees",
84
87
  body: payload,
@@ -103,6 +106,7 @@ module Fastlane
103
106
  GithubApiAction.run(
104
107
  server_url: params[:api_url],
105
108
  api_token: params[:api_token],
109
+ api_bearer: params[:api_bearer],
106
110
  http_method: 'POST',
107
111
  path: "repos/#{params[:repo]}/pulls/#{number}/requested_reviewers",
108
112
  body: payload,
@@ -124,6 +128,7 @@ module Fastlane
124
128
  GithubApiAction.run(
125
129
  server_url: params[:api_url],
126
130
  api_token: params[:api_token],
131
+ api_bearer: params[:api_bearer],
127
132
  http_method: 'PATCH',
128
133
  path: "repos/#{params[:repo]}/issues/#{number}",
129
134
  body: payload,
@@ -161,7 +166,17 @@ module Fastlane
161
166
  default_value: ENV["GITHUB_API_TOKEN"],
162
167
  default_value_dynamic: true,
163
168
  is_string: true,
164
- optional: false),
169
+ conflicting_options: [:api_bearer],
170
+ optional: true),
171
+ FastlaneCore::ConfigItem.new(key: :api_bearer,
172
+ env_name: "GITHUB_PULL_REQUEST_API_BEARER",
173
+ description: "Use a Bearer authorization token. Usually generated by Github Apps, e.g. GitHub Actions GITHUB_TOKEN environment variable",
174
+ sensitive: true,
175
+ code_gen_sensitive: true,
176
+ is_string: true,
177
+ conflicting_options: [:api_token],
178
+ optional: true,
179
+ default_value: nil),
165
180
  FastlaneCore::ConfigItem.new(key: :repo,
166
181
  env_name: "GITHUB_PULL_REQUEST_REPO",
167
182
  description: "The name of the repository you want to submit the pull request to",
@@ -0,0 +1,118 @@
1
+ module Fastlane
2
+ module Actions
3
+ module SharedValues
4
+ XCFRAMEWORK_PATH ||= :XCFRAMEWORK_PATH
5
+ end
6
+
7
+ class CreateXcframeworkAction < Action
8
+ def self.run(params)
9
+ UI.user_error!("Please provide either :frameworks or :libraries to be packaged into the xcframework") unless params[:frameworks] || params[:libraries]
10
+
11
+ create_command = ['xcodebuild', '-create-xcframework']
12
+ create_command << params[:frameworks].map { |framework| ['-framework', "\"#{framework}\""] }.flatten if params[:frameworks]
13
+ create_command << params[:libraries].map { |library, headers| ['-library', "\"#{library}\""] + (headers.empty? ? [] : ['-headers', "\"#{headers}\""]) } if params[:libraries]
14
+ create_command << ['-output', "\"#{params[:output]}\""]
15
+ create_command << ['-allow-internal-distribution'] if params[:allow_internal_distribution]
16
+
17
+ Actions.lane_context[SharedValues::XCFRAMEWORK_PATH] = params[:output]
18
+
19
+ sh(create_command)
20
+ end
21
+
22
+ #####################################################
23
+ # @!group Documentation
24
+ #####################################################
25
+
26
+ def self.description
27
+ "Package multiple build configs of a library/framework into a single xcframework"
28
+ end
29
+
30
+ def self.details
31
+ <<~DETAILS
32
+ Utility for packaging multiple build configurations of a given library
33
+ or framework into a single xcframework.
34
+
35
+ If you want to package several frameworks just provide an array containing
36
+ the list of frameworks to be packaged using the :frameworks parameter.
37
+
38
+ If you want to package several libraries with their corresponding headers
39
+ provide a hash containing the library as the key and the directory containing
40
+ its headers as the value (or an empty string if there are no headers associated
41
+ with the provided library).
42
+
43
+ Finally specify the location of the xcframework to be generated using the :output
44
+ parameter.
45
+ DETAILS
46
+ end
47
+
48
+ def self.available_options
49
+ [
50
+ FastlaneCore::ConfigItem.new(key: :frameworks,
51
+ env_name: "FL_CREATE_XCFRAMEWORK_FRAMEWORKS",
52
+ description: "Frameworks to add to the target xcframework",
53
+ type: Array,
54
+ optional: true,
55
+ conflicting_options: [:libraries],
56
+ verify_block: proc do |value|
57
+ value.each do |framework|
58
+ UI.user_error!("#{framework} doesn't end with '.framework'. Is this really a framework?") unless framework.end_with?('.framework')
59
+ UI.user_error!("Couldn't find framework at #{framework}") unless File.exist?(framework)
60
+ UI.user_error!("#{framework} doesn't seem to be a framework") unless File.directory?(framework)
61
+ end
62
+ end),
63
+ FastlaneCore::ConfigItem.new(key: :libraries,
64
+ env_name: "FL_CREATE_XCFRAMEWORK_LIBRARIES",
65
+ description: "Libraries to add to the target xcframework, with their corresponding headers",
66
+ type: Hash,
67
+ optional: true,
68
+ conflicting_options: [:frameworks],
69
+ verify_block: proc do |value|
70
+ value.each do |library, headers|
71
+ UI.user_error!("Couldn't find library at #{library}") unless File.exist?(library)
72
+ UI.user_error!("#{headers} doesn't exist or is not a directory") unless headers.empty? || File.directory?(headers)
73
+ end
74
+ end),
75
+ FastlaneCore::ConfigItem.new(key: :output,
76
+ env_name: "FL_CREATE_XCFRAMEWORK_OUTPUT",
77
+ description: "The path to write the xcframework to",
78
+ type: String,
79
+ optional: false),
80
+ FastlaneCore::ConfigItem.new(key: :allow_internal_distribution,
81
+ env_name: "FL_CREATE_XCFRAMEWORK_ALLOW_INTERNAL_DISTRIBUTION",
82
+ description: "Specifies that the created xcframework contains information not suitable for public distribution",
83
+ type: Boolean,
84
+ optional: true,
85
+ default_value: false)
86
+ ]
87
+ end
88
+
89
+ def self.output
90
+ [
91
+ ['XCFRAMEWORK_PATH', 'Location of the generated xcframework']
92
+ ]
93
+ end
94
+
95
+ def self.return_value
96
+ end
97
+
98
+ def self.example_code
99
+ [
100
+ "create_xcframework(frameworks: ['FrameworkA.framework', 'FrameworkB.framework'], output: 'UniversalFramework.xcframework')",
101
+ "create_xcframework(libraries: { 'LibraryA.so' => '', 'LibraryB.so' => 'LibraryBHeaders'}, output: 'UniversalFramework.xcframework')"
102
+ ]
103
+ end
104
+
105
+ def self.category
106
+ :building
107
+ end
108
+
109
+ def self.authors
110
+ ["jgongo"]
111
+ end
112
+
113
+ def self.is_supported?(platform)
114
+ [:ios, :mac].include?(platform)
115
+ end
116
+ end
117
+ end
118
+ end