fastlane 2.238.0 → 2.241.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +57 -177
- data/bin/fastlane +4 -2
- data/credentials_manager/README.md +1 -1
- data/credentials_manager/lib/credentials_manager/account_manager.rb +6 -2
- data/deliver/lib/deliver/app_screenshot.rb +0 -4
- data/deliver/lib/deliver/commands_generator.rb +1 -1
- data/deliver/lib/deliver/detect_values.rb +3 -1
- data/deliver/lib/deliver/download_screenshots.rb +8 -1
- data/deliver/lib/deliver/html_generator.rb +1 -1
- data/deliver/lib/deliver/options.rb +8 -0
- data/deliver/lib/deliver/runner.rb +5 -4
- data/deliver/lib/deliver/sync_screenshots.rb +27 -28
- data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +3 -3
- data/deliver/lib/deliver/upload_metadata.rb +34 -16
- data/deliver/lib/deliver/upload_screenshots.rb +24 -18
- data/docs/README.md +25 -0
- data/fastlane/lib/assets/TeamTable.md.erb +28 -0
- data/fastlane/lib/fastlane/actions/appaloosa.rb +2 -1
- data/fastlane/lib/fastlane/actions/appium.rb +1 -1
- data/fastlane/lib/fastlane/actions/apteligent.rb +8 -1
- data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +3 -1
- data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +7 -2
- data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
- data/fastlane/lib/fastlane/actions/danger.rb +5 -5
- data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/get_certificates.md +0 -2
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +7 -3
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +13 -3
- data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +2 -2
- data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -0
- data/fastlane/lib/fastlane/actions/github_api.rb +1 -2
- data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_version_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +16 -6
- data/fastlane/lib/fastlane/actions/lcov.rb +11 -2
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +16 -4
- data/fastlane/lib/fastlane/actions/notification.rb +3 -2
- data/fastlane/lib/fastlane/actions/oclint.rb +8 -8
- data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -4
- data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
- data/fastlane/lib/fastlane/actions/say.rb +2 -4
- data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
- data/fastlane/lib/fastlane/actions/sonar.rb +16 -16
- data/fastlane/lib/fastlane/actions/sourcedocs.rb +8 -8
- data/fastlane/lib/fastlane/actions/spaceship_logs.rb +4 -2
- data/fastlane/lib/fastlane/actions/splunkmint.rb +8 -1
- data/fastlane/lib/fastlane/actions/swiftlint.rb +6 -3
- data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +4 -2
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -2
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +5 -2
- data/fastlane/lib/fastlane/actions/verify_build.rb +1 -4
- data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +3 -1
- data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +20 -19
- data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -6
- data/fastlane/lib/fastlane/actions/zip.rb +2 -1
- data/fastlane/lib/fastlane/auto_complete.rb +1 -1
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +14 -0
- data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +23 -0
- data/fastlane/lib/fastlane/environment_printer.rb +12 -25
- data/fastlane/lib/fastlane/fast_file.rb +2 -1
- data/fastlane/lib/fastlane/fastlane_require.rb +5 -1
- data/fastlane/lib/fastlane/helper/git_helper.rb +4 -2
- data/fastlane/lib/fastlane/helper/sh_helper.rb +25 -7
- data/fastlane/lib/fastlane/new_action.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +36 -4
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
- data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +1 -1
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +7 -7
- data/fastlane/lib/fastlane/swift_lane_manager.rb +22 -4
- data/fastlane/lib/fastlane/version.rb +3 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +8 -1
- data/fastlane/swift/Fastlane.swift +129 -11
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +8 -1
- data/fastlane/swift/MainProcess.swift +190 -20
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +10 -3
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +15 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +8 -1
- data/fastlane/swift/formatting/Rakefile +1 -0
- data/fastlane/swift/main.swift +4 -1
- data/fastlane_core/README.md +1 -1
- data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +1 -17
- data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +23 -8
- data/fastlane_core/lib/fastlane_core/device_manager.rb +2 -2
- data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +20 -7
- data/fastlane_core/lib/fastlane_core/helper.rb +34 -5
- data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +1 -1
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +16 -27
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +31 -28
- data/fastlane_core/lib/fastlane_core/languages.rb +0 -1
- data/fastlane_core/lib/fastlane_core/print_table.rb +5 -2
- data/fastlane_core/lib/fastlane_core/project.rb +19 -0
- data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +10 -19
- data/fastlane_core/lib/fastlane_core/secrets.rb +77 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +3 -3
- data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +1 -1
- data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +2 -1
- data/fastlane_core/lib/fastlane_core.rb +1 -0
- data/frameit/lib/frameit/device.rb +1 -1
- data/frameit/lib/frameit/frame_downloader.rb +2 -0
- data/frameit/lib/frameit/runner.rb +3 -2
- data/frameit/lib/frameit/screenshot.rb +0 -1
- data/gym/lib/gym/generators/build_command_generator.rb +4 -4
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
- data/gym/lib/gym/options.rb +5 -0
- data/gym/lib/gym/runner.rb +1 -1
- data/internal/README.md +1 -1
- data/match/lib/match/encryption/openssl.rb +6 -2
- data/match/lib/match/generator.rb +1 -0
- data/match/lib/match/nuke.rb +2 -2
- data/match/lib/match/options.rb +13 -5
- data/match/lib/match/runner.rb +30 -3
- data/match/lib/match/storage/git_storage.rb +44 -11
- data/match/lib/match/storage/gitlab/secure_file.rb +2 -1
- data/match/lib/match/storage/google_cloud_storage.rb +6 -1
- data/match/lib/match/storage/interface.rb +8 -5
- data/pem/lib/pem/manager.rb +5 -1
- data/pem/lib/pem/module.rb +0 -4
- data/pem/lib/pem/options.rb +6 -0
- data/pilot/lib/pilot/build_manager.rb +32 -0
- data/pilot/lib/pilot/options.rb +8 -0
- data/precheck/lib/precheck/rule_processor.rb +1 -0
- data/produce/lib/produce/developer_center.rb +49 -2
- data/produce/lib/produce/itunes_connect.rb +1 -1
- data/produce/lib/produce/module.rb +21 -0
- data/produce/lib/produce/options.rb +17 -0
- data/produce/lib/produce/service.rb +3 -5
- data/produce/lib/produce.rb +0 -1
- data/scan/lib/scan/options.rb +12 -0
- data/scan/lib/scan/runner.rb +1 -1
- data/scan/lib/scan/test_command_generator.rb +12 -9
- data/scan/lib/scan/test_result_parser.rb +1 -0
- data/scan/lib/scan/xcpretty_reporter_options_generator.rb +2 -2
- data/screengrab/lib/screengrab/page.html.erb +12 -7
- data/screengrab/lib/screengrab/reports_generator.rb +1 -1
- data/sigh/lib/assets/resign.sh +38 -9
- data/sigh/lib/sigh/local_manage.rb +1 -1
- data/sigh/lib/sigh/options.rb +5 -0
- data/sigh/lib/sigh/resign.rb +3 -3
- data/sigh/lib/sigh/runner.rb +6 -1
- data/snapshot/lib/snapshot/options.rb +5 -0
- data/snapshot/lib/snapshot/page.html.erb +17 -12
- data/snapshot/lib/snapshot/reports_generator.rb +1 -1
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
- data/snapshot/lib/snapshot.rb +0 -2
- data/spaceship/README.md +2 -3
- data/spaceship/lib/spaceship/base.rb +3 -1
- data/spaceship/lib/spaceship/client.rb +159 -19
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +16 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +13 -2
- data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +6 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -5
- data/spaceship/lib/spaceship/connect_api/models/routing_app_coverage.rb +75 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +25 -0
- data/spaceship/lib/spaceship/connect_api/token.rb +6 -1
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +45 -0
- data/spaceship/lib/spaceship/connect_api.rb +1 -0
- data/spaceship/lib/spaceship/du/upload_file.rb +4 -3
- data/spaceship/lib/spaceship/errors.rb +7 -1
- data/spaceship/lib/spaceship/globals.rb +2 -2
- data/spaceship/lib/spaceship/portal/merchant.rb +127 -2
- data/spaceship/lib/spaceship/portal/portal_client.rb +58 -0
- data/spaceship/lib/spaceship/portal/ui/select_team.rb +0 -2
- data/spaceship/lib/spaceship/portal/website_push.rb +8 -2
- data/spaceship/lib/spaceship/test_flight/client.rb +0 -22
- data/spaceship/lib/spaceship/test_flight.rb +0 -1
- data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -0
- data/supply/lib/supply/client.rb +6 -0
- data/supply/lib/supply/options.rb +1 -0
- data/supply/lib/supply/reader.rb +15 -0
- data/supply/lib/supply.rb +0 -1
- data/trainer/lib/trainer/xcresult/helper.rb +27 -13
- metadata +80 -64
- data/produce/lib/produce/available_default_languages.rb +0 -62
- data/snapshot/lib/snapshot/screenshot_flatten.rb +0 -20
- data/snapshot/lib/snapshot/screenshot_rotate.rb +0 -36
- data/spaceship/lib/spaceship/test_flight/app_test_info.rb +0 -40
- data/supply/lib/supply/apk_listing.rb +0 -14
- /data/fastlane/lib/assets/{custom_action_template.rb → custom_action_template.rb.template} +0 -0
data/gym/lib/gym/options.rb
CHANGED
|
@@ -321,6 +321,11 @@ module Gym
|
|
|
321
321
|
description: "Skips resolution of Swift Package Manager dependencies",
|
|
322
322
|
type: Boolean,
|
|
323
323
|
default_value: false),
|
|
324
|
+
FastlaneCore::ConfigItem.new(key: :disallow_xcodebuild_settings_lookup,
|
|
325
|
+
env_name: "GYM_DISALLOW_XCODEBUILD_SETTINGS_LOOKUP",
|
|
326
|
+
description: "Raises an error instead of fetching build settings by running `xcodebuild -showBuildSettings`, which can take a long time on large projects. The error names the required build setting, so the corresponding option can be specified manually",
|
|
327
|
+
type: Boolean,
|
|
328
|
+
default_value: false),
|
|
324
329
|
FastlaneCore::ConfigItem.new(key: :disable_package_automatic_updates,
|
|
325
330
|
env_name: "GYM_DISABLE_PACKAGE_AUTOMATIC_UPDATES",
|
|
326
331
|
description: "Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file. This translates in the option `-disableAutomaticPackageResolution` being passed to xcodebuild",
|
data/gym/lib/gym/runner.rb
CHANGED
|
@@ -223,7 +223,7 @@ module Gym
|
|
|
223
223
|
UI.message("Compressing #{available_dsyms.count} dSYM(s)") unless Gym.config[:silent]
|
|
224
224
|
|
|
225
225
|
output_path = File.expand_path(File.join(Gym.config[:output_directory], Gym.config[:output_name] + ".app.dSYM.zip"))
|
|
226
|
-
command = "cd
|
|
226
|
+
command = "cd #{containing_directory.shellescape} && zip -r #{output_path.shellescape} *.dSYM"
|
|
227
227
|
Helper.backticks(command, print: !Gym.config[:silent])
|
|
228
228
|
puts("") # new line
|
|
229
229
|
|
data/internal/README.md
CHANGED
|
@@ -93,8 +93,12 @@ module Match
|
|
|
93
93
|
def fetch_password!
|
|
94
94
|
password = ENV["MATCH_PASSWORD"]
|
|
95
95
|
unless password
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
begin
|
|
97
|
+
item = Security::InternetPassword.find(server: server_name(self.keychain_name))
|
|
98
|
+
password = item.password if item
|
|
99
|
+
rescue Security::Error => ex
|
|
100
|
+
UI.important("Could not read the local keychain: #{ex.message}")
|
|
101
|
+
end
|
|
98
102
|
end
|
|
99
103
|
|
|
100
104
|
unless password
|
|
@@ -92,6 +92,7 @@ module Match
|
|
|
92
92
|
fail_on_name_taken: params[:fail_on_name_taken],
|
|
93
93
|
include_all_certificates: params[:include_all_certificates],
|
|
94
94
|
include_mac_in_profiles: params[:include_mac_in_profiles],
|
|
95
|
+
offline_profile: params[:offline_profile],
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
values[:platform] = params[:platform]
|
data/match/lib/match/nuke.rb
CHANGED
|
@@ -341,9 +341,9 @@ module Match
|
|
|
341
341
|
def filter_profiles_and_files_by_selected_certificates
|
|
342
342
|
# Do profile selection logic
|
|
343
343
|
cert_ids = self.certs.map { |cert| cert.id.to_s }
|
|
344
|
-
self.profiles = self.profiles.
|
|
344
|
+
self.profiles = self.profiles.select do |profile|
|
|
345
345
|
profile_cert_ids = profile.certificates.map { |cert| cert.id.to_s }
|
|
346
|
-
(
|
|
346
|
+
cert_ids.intersect?(profile_cert_ids)
|
|
347
347
|
end
|
|
348
348
|
|
|
349
349
|
profile_uuids = self.profiles.map do |profile|
|
data/match/lib/match/options.rb
CHANGED
|
@@ -160,14 +160,14 @@ module Match
|
|
|
160
160
|
FastlaneCore::ConfigItem.new(key: :git_basic_authorization,
|
|
161
161
|
env_name: "MATCH_GIT_BASIC_AUTHORIZATION",
|
|
162
162
|
sensitive: true,
|
|
163
|
-
description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64",
|
|
163
|
+
description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later",
|
|
164
164
|
conflicting_options: [:git_bearer_authorization, :git_private_key],
|
|
165
165
|
optional: true,
|
|
166
166
|
default_value: nil),
|
|
167
167
|
FastlaneCore::ConfigItem.new(key: :git_bearer_authorization,
|
|
168
168
|
env_name: "MATCH_GIT_BEARER_AUTHORIZATION",
|
|
169
169
|
sensitive: true,
|
|
170
|
-
description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64",
|
|
170
|
+
description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later",
|
|
171
171
|
conflicting_options: [:git_basic_authorization, :git_private_key],
|
|
172
172
|
optional: true,
|
|
173
173
|
default_value: nil),
|
|
@@ -209,7 +209,8 @@ module Match
|
|
|
209
209
|
FastlaneCore::ConfigItem.new(key: :s3_access_key,
|
|
210
210
|
env_name: "MATCH_S3_ACCESS_KEY",
|
|
211
211
|
description: "S3 access key",
|
|
212
|
-
optional: true
|
|
212
|
+
optional: true,
|
|
213
|
+
sensitive: true),
|
|
213
214
|
FastlaneCore::ConfigItem.new(key: :s3_secret_access_key,
|
|
214
215
|
env_name: "MATCH_S3_SECRET_ACCESS_KEY",
|
|
215
216
|
description: "S3 secret access key",
|
|
@@ -247,11 +248,13 @@ module Match
|
|
|
247
248
|
FastlaneCore::ConfigItem.new(key: :job_token,
|
|
248
249
|
env_name: "CI_JOB_TOKEN",
|
|
249
250
|
description: "GitLab CI_JOB_TOKEN",
|
|
250
|
-
optional: true
|
|
251
|
+
optional: true,
|
|
252
|
+
sensitive: true),
|
|
251
253
|
FastlaneCore::ConfigItem.new(key: :private_token,
|
|
252
254
|
env_name: "PRIVATE_TOKEN",
|
|
253
255
|
description: "GitLab Access Token",
|
|
254
|
-
optional: true
|
|
256
|
+
optional: true,
|
|
257
|
+
sensitive: true),
|
|
255
258
|
|
|
256
259
|
# Keychain
|
|
257
260
|
FastlaneCore::ConfigItem.new(key: :keychain_name,
|
|
@@ -374,6 +377,11 @@ module Match
|
|
|
374
377
|
description: "Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions",
|
|
375
378
|
type: Boolean,
|
|
376
379
|
default_value: false),
|
|
380
|
+
FastlaneCore::ConfigItem.new(key: :offline_profile,
|
|
381
|
+
env_name: "MATCH_OFFLINE_PROFILE",
|
|
382
|
+
description: "Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication",
|
|
383
|
+
type: Boolean,
|
|
384
|
+
default_value: false),
|
|
377
385
|
|
|
378
386
|
# other
|
|
379
387
|
FastlaneCore::ConfigItem.new(key: :verbose,
|
data/match/lib/match/runner.rb
CHANGED
|
@@ -24,6 +24,8 @@ module Match
|
|
|
24
24
|
|
|
25
25
|
attr_accessor :storage
|
|
26
26
|
|
|
27
|
+
attr_accessor :encryption
|
|
28
|
+
|
|
27
29
|
attr_accessor :cache
|
|
28
30
|
|
|
29
31
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
@@ -45,14 +47,14 @@ module Match
|
|
|
45
47
|
storage.download
|
|
46
48
|
|
|
47
49
|
# Init the encryption only after the `storage.download` was called to have the right working directory
|
|
48
|
-
encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
|
50
|
+
self.encryption = Encryption.for_storage_mode(params[:storage_mode], {
|
|
49
51
|
git_url: params[:git_url],
|
|
50
52
|
s3_bucket: params[:s3_bucket],
|
|
51
53
|
s3_skip_encryption: params[:s3_skip_encryption],
|
|
52
54
|
working_directory: storage.working_directory,
|
|
53
55
|
force_legacy_encryption: params[:force_legacy_encryption]
|
|
54
56
|
})
|
|
55
|
-
encryption.decrypt_files if encryption
|
|
57
|
+
self.encryption.decrypt_files if self.encryption
|
|
56
58
|
|
|
57
59
|
unless params[:readonly]
|
|
58
60
|
self.spaceship = SpaceshipEnsure.new(params[:username], params[:team_id], params[:team_name], api_token(params))
|
|
@@ -117,7 +119,7 @@ module Match
|
|
|
117
119
|
|
|
118
120
|
has_file_changes = self.files_to_commit.count > 0 || self.files_to_delete.count > 0
|
|
119
121
|
if has_file_changes && !params[:readonly]
|
|
120
|
-
encryption.encrypt_files if encryption
|
|
122
|
+
self.encryption.encrypt_files if self.encryption
|
|
121
123
|
storage.save_changes!(files_to_commit: self.files_to_commit, files_to_delete: self.files_to_delete)
|
|
122
124
|
end
|
|
123
125
|
|
|
@@ -209,6 +211,10 @@ module Match
|
|
|
209
211
|
self.files_to_commit << cert_path
|
|
210
212
|
self.files_to_commit << private_key_path
|
|
211
213
|
|
|
214
|
+
# We pause to upload certs immediatly (or renewals) in case later logic fails, leaving
|
|
215
|
+
# AppStore with a set of files de-synced from match storage. See fastlane/fastlane#30140
|
|
216
|
+
save_changes_immediately!(params)
|
|
217
|
+
|
|
212
218
|
# Reset certificates cache since we have a new cert.
|
|
213
219
|
self.cache.reset_certificates
|
|
214
220
|
else
|
|
@@ -255,6 +261,27 @@ module Match
|
|
|
255
261
|
return File.basename(cert_path).gsub(".cer", "") # Certificate ID
|
|
256
262
|
end
|
|
257
263
|
|
|
264
|
+
# Saves all pending file changes to storage right away, keeping the
|
|
265
|
+
# working directory around so the current run can continue using it
|
|
266
|
+
def save_changes_immediately!(params)
|
|
267
|
+
return if params[:readonly]
|
|
268
|
+
return if self.files_to_commit.empty? && self.files_to_delete.empty?
|
|
269
|
+
|
|
270
|
+
self.encryption.encrypt_files if self.encryption
|
|
271
|
+
begin
|
|
272
|
+
self.storage.save_changes!(files_to_commit: self.files_to_commit,
|
|
273
|
+
files_to_delete: self.files_to_delete,
|
|
274
|
+
clear_working_directory: false)
|
|
275
|
+
ensure
|
|
276
|
+
# Always hand back a decrypted working directory, 2nd upload will hopefully work.
|
|
277
|
+
self.encryption.decrypt_files if self.encryption
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# We may have another upload at end (profiles) so reset our cert file(s).
|
|
281
|
+
self.files_to_commit = []
|
|
282
|
+
self.files_to_delete = []
|
|
283
|
+
end
|
|
284
|
+
|
|
258
285
|
# @return [String] Path to certificate or P12 key
|
|
259
286
|
def select_cert_or_key(paths:, certificate_id: nil)
|
|
260
287
|
return paths.last if certificate_id.to_s.strip.empty?
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'fastlane_core/command_executor'
|
|
2
|
+
require 'open3'
|
|
2
3
|
|
|
3
4
|
require_relative '../module'
|
|
4
5
|
require_relative './interface'
|
|
@@ -7,6 +8,9 @@ module Match
|
|
|
7
8
|
module Storage
|
|
8
9
|
# Store the code signing identities in a git repo
|
|
9
10
|
class GitStorage < Interface
|
|
11
|
+
DEFAULT_BRANCH = "main"
|
|
12
|
+
PRIVATE_KEY_ENV = "MATCH_SSH_ADD_PRIVATE_KEY"
|
|
13
|
+
|
|
10
14
|
# User provided values
|
|
11
15
|
attr_accessor :git_url
|
|
12
16
|
attr_accessor :shallow_clone
|
|
@@ -85,11 +89,6 @@ module Match
|
|
|
85
89
|
self.working_directory = Dir.mktmpdir
|
|
86
90
|
|
|
87
91
|
command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
|
|
88
|
-
# HTTP headers are supposed to be case-insensitive but
|
|
89
|
-
# Bitbucket requires `Authorization: Basic` and `Authorization Bearer` to work
|
|
90
|
-
# https://github.com/fastlane/fastlane/pull/15928
|
|
91
|
-
command << " -c http.extraheader='Authorization: Basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
|
|
92
|
-
command << " -c http.extraheader='Authorization: Bearer #{self.git_bearer_authorization}'" unless self.git_bearer_authorization.nil?
|
|
93
92
|
|
|
94
93
|
if self.shallow_clone
|
|
95
94
|
command << " --depth 1"
|
|
@@ -117,13 +116,10 @@ module Match
|
|
|
117
116
|
print_command: FastlaneCore::Globals.verbose?)
|
|
118
117
|
end
|
|
119
118
|
rescue
|
|
120
|
-
UI.error("Error cloning certificates repo, please make sure you have read access to the repository you want to use")
|
|
121
119
|
if self.branch && self.clone_branch_directly
|
|
122
120
|
UI.error("You passed '#{self.branch}' as branch in combination with the `clone_branch_directly` flag. Please remove `clone_branch_directly` flag on the first run for _match_ to create the branch.")
|
|
123
121
|
end
|
|
124
|
-
UI.
|
|
125
|
-
UI.command(command)
|
|
126
|
-
UI.user_error!("Error cloning certificates git repo, please make sure you have access to the repository - see instructions above")
|
|
122
|
+
UI.user_error!("Error cloning certificates repo, please make sure you have read access to the repository you want to use")
|
|
127
123
|
end
|
|
128
124
|
|
|
129
125
|
add_user_config(self.git_full_name, self.git_user_email)
|
|
@@ -168,8 +164,10 @@ module Match
|
|
|
168
164
|
def generate_matchfile_content
|
|
169
165
|
UI.important("Please create a new, private git repository to store the certificates and profiles there")
|
|
170
166
|
url = UI.input("URL of the Git Repo: ")
|
|
167
|
+
branch = UI.input("Branch of the Git Repo (leave blank to use '#{DEFAULT_BRANCH}'): ").to_s.strip
|
|
168
|
+
branch = DEFAULT_BRANCH if branch.empty?
|
|
171
169
|
|
|
172
|
-
return "git_url(\"#{url}\")"
|
|
170
|
+
return "git_url(\"#{url}\")\ngit_branch(\"#{branch}\")"
|
|
173
171
|
end
|
|
174
172
|
|
|
175
173
|
def list_files(file_name: "", file_ext: "")
|
|
@@ -181,7 +179,8 @@ module Match
|
|
|
181
179
|
ssh_add = File.expand_path(self.git_private_key).shellescape.to_s
|
|
182
180
|
else
|
|
183
181
|
UI.message("Private key file does not exist, will continue by using it as a raw key.")
|
|
184
|
-
|
|
182
|
+
# From the environment (git_env_values), so the key is not on bash's command line
|
|
183
|
+
ssh_add = "- <<< \"$#{PRIVATE_KEY_ENV}\""
|
|
185
184
|
end
|
|
186
185
|
return "ssh-agent bash -c 'ssh-add #{ssh_add}; #{command}'"
|
|
187
186
|
end
|
|
@@ -267,9 +266,43 @@ module Match
|
|
|
267
266
|
def git_env_values
|
|
268
267
|
env_values = { 'GIT_TERMINAL_PROMPT' => '0' }
|
|
269
268
|
env_values['GIT_SSH_COMMAND'] = non_interactive_git_ssh_command
|
|
269
|
+
env_values[PRIVATE_KEY_ENV] = self.git_private_key unless self.git_private_key.nil?
|
|
270
|
+
env_values.merge(authorization_env_values)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# Through git's environment (git 2.31+), so the header is neither on the command line nor stored in .git/config
|
|
274
|
+
def authorization_env_values
|
|
275
|
+
headers = []
|
|
276
|
+
# HTTP headers are supposed to be case-insensitive but
|
|
277
|
+
# Bitbucket requires `Authorization: Basic` and `Authorization Bearer` to work
|
|
278
|
+
# https://github.com/fastlane/fastlane/pull/15928
|
|
279
|
+
headers << "Authorization: Basic #{self.git_basic_authorization}" unless self.git_basic_authorization.nil?
|
|
280
|
+
headers << "Authorization: Bearer #{self.git_bearer_authorization}" unless self.git_bearer_authorization.nil?
|
|
281
|
+
return {} if headers.empty?
|
|
282
|
+
|
|
283
|
+
version = git_version
|
|
284
|
+
UI.user_error!("git_basic_authorization and git_bearer_authorization need git 2.31 or later, found git #{version}") if version && Gem::Version.new(version) < Gem::Version.new('2.31')
|
|
285
|
+
|
|
286
|
+
# Keep pairs the user already passes this way
|
|
287
|
+
first = ENV['GIT_CONFIG_COUNT'].to_i
|
|
288
|
+
env_values = { 'GIT_CONFIG_COUNT' => (first + headers.count).to_s }
|
|
289
|
+
headers.each_with_index do |header, i|
|
|
290
|
+
env_values["GIT_CONFIG_KEY_#{first + i}"] = 'http.extraheader'
|
|
291
|
+
env_values["GIT_CONFIG_VALUE_#{first + i}"] = header
|
|
292
|
+
end
|
|
270
293
|
env_values
|
|
271
294
|
end
|
|
272
295
|
|
|
296
|
+
# nil when git cannot be run: cloning reports that
|
|
297
|
+
def git_version
|
|
298
|
+
@git_version ||= begin
|
|
299
|
+
output, status = Open3.capture2('git', '--version')
|
|
300
|
+
output[/\d+\.\d+(\.\d+)?/] if status.success?
|
|
301
|
+
rescue Errno::ENOENT
|
|
302
|
+
nil
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
273
306
|
def non_interactive_git_ssh_command
|
|
274
307
|
ssh_command = ENV['GIT_SSH_COMMAND']
|
|
275
308
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'open-uri'
|
|
2
|
+
require 'ostruct'
|
|
2
3
|
|
|
3
4
|
require_relative '../../module'
|
|
4
5
|
|
|
@@ -39,7 +40,7 @@ module Match
|
|
|
39
40
|
|
|
40
41
|
create_subfolders(working_directory)
|
|
41
42
|
File.open(destination_file, "wb") do |saved_file|
|
|
42
|
-
|
|
43
|
+
url.open("rb", { @client.authentication_key => @client.authentication_value }) do |data|
|
|
43
44
|
saved_file.write(data.read)
|
|
44
45
|
end
|
|
45
46
|
|
|
@@ -82,7 +82,12 @@ module Match
|
|
|
82
82
|
if self.google_cloud_keys_file.to_s.length > 0
|
|
83
83
|
# Extract the Project ID from the `JSON` file
|
|
84
84
|
# so the user doesn't have to provide it manually
|
|
85
|
-
|
|
85
|
+
begin
|
|
86
|
+
keys_file_content = JSON.parse(File.read(self.google_cloud_keys_file))
|
|
87
|
+
rescue JSON::ParserError
|
|
88
|
+
# Don't dump secret into logs in case a secret (p8) is passed. See fastlane/fastlane#21017
|
|
89
|
+
UI.user_error!("Provided keys file on path #{File.expand_path(self.google_cloud_keys_file)} is not a valid JSON file")
|
|
90
|
+
end
|
|
86
91
|
if google_cloud_project_id.to_s.length > 0 && google_cloud_project_id != keys_file_content["project_id"]
|
|
87
92
|
UI.important("The google_cloud_keys_file's project ID ('#{keys_file_content['project_id']}') doesn't match the google_cloud_project_id ('#{google_cloud_project_id}'). This may be the wrong keys file.")
|
|
88
93
|
end
|
|
@@ -47,11 +47,14 @@ module Match
|
|
|
47
47
|
# given remote server
|
|
48
48
|
# This method is blocking, meaning it might take multiple
|
|
49
49
|
# seconds or longer to run
|
|
50
|
-
# @
|
|
50
|
+
# @param files_to_commit [Array] Array to paths to files
|
|
51
51
|
# that should be committed to the storage provider
|
|
52
|
-
# @
|
|
53
|
-
#
|
|
54
|
-
|
|
52
|
+
# @param custom_message: [String] Custom change message
|
|
53
|
+
# that's optional, is used for commit title
|
|
54
|
+
# @param clear_working_directory: [Bool] Pass `false` to keep
|
|
55
|
+
# the local working directory after saving, so more
|
|
56
|
+
# changes can be made and saved later in the same run
|
|
57
|
+
def save_changes!(files_to_commit: nil, files_to_delete: nil, custom_message: nil, clear_working_directory: true)
|
|
55
58
|
# Custom init to `[]` in case `nil` is passed
|
|
56
59
|
files_to_commit ||= []
|
|
57
60
|
files_to_delete ||= []
|
|
@@ -85,7 +88,7 @@ module Match
|
|
|
85
88
|
end
|
|
86
89
|
end
|
|
87
90
|
ensure # Always clear working_directory after save
|
|
88
|
-
self.clear_changes
|
|
91
|
+
self.clear_changes if clear_working_directory
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
def upload_files(files_to_upload: [], custom_message: nil)
|
data/pem/lib/pem/manager.rb
CHANGED
|
@@ -20,7 +20,7 @@ module PEM
|
|
|
20
20
|
remaining_days = (existing_certificate.expires - Time.now) / 60 / 60 / 24
|
|
21
21
|
|
|
22
22
|
display_platform = ''
|
|
23
|
-
unless PEM.config[:website_push]
|
|
23
|
+
unless PEM.config[:website_push] || PEM.config[:voip_push]
|
|
24
24
|
display_platform = "#{PEM.config[:platform]} "
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -94,6 +94,8 @@ module PEM
|
|
|
94
94
|
def certificate
|
|
95
95
|
if PEM.config[:website_push]
|
|
96
96
|
Spaceship.certificate.website_push
|
|
97
|
+
elsif PEM.config[:voip_push]
|
|
98
|
+
Spaceship.certificate.voip_push
|
|
97
99
|
else
|
|
98
100
|
platform = PEM.config[:platform]
|
|
99
101
|
UI.user_error!('platform parameter is unspecified.') unless platform
|
|
@@ -123,6 +125,8 @@ module PEM
|
|
|
123
125
|
'development'
|
|
124
126
|
elsif PEM.config[:website_push]
|
|
125
127
|
'website'
|
|
128
|
+
elsif PEM.config[:voip_push]
|
|
129
|
+
'voip'
|
|
126
130
|
else
|
|
127
131
|
'production'
|
|
128
132
|
end
|
data/pem/lib/pem/module.rb
CHANGED
data/pem/lib/pem/options.rb
CHANGED
|
@@ -30,6 +30,12 @@ module PEM
|
|
|
30
30
|
is_string: false,
|
|
31
31
|
conflicting_options: [:development],
|
|
32
32
|
default_value: false),
|
|
33
|
+
FastlaneCore::ConfigItem.new(key: :voip_push,
|
|
34
|
+
env_name: "PEM_VOIP_PUSH",
|
|
35
|
+
description: "Create a VoIP Services certificate",
|
|
36
|
+
is_string: false,
|
|
37
|
+
conflicting_options: [:development, :website_push],
|
|
38
|
+
default_value: false),
|
|
33
39
|
FastlaneCore::ConfigItem.new(key: :generate_p12,
|
|
34
40
|
env_name: "PEM_GENERATE_P12_FILE",
|
|
35
41
|
description: "Generate a p12 file additionally to a PEM file",
|
|
@@ -296,6 +296,9 @@ module Pilot
|
|
|
296
296
|
|
|
297
297
|
# Handle beta app clip invocations
|
|
298
298
|
update_app_clip_invocations(options: options, build: build)
|
|
299
|
+
|
|
300
|
+
# Handle routing app coverage file
|
|
301
|
+
update_routing_app_coverage(options)
|
|
299
302
|
end
|
|
300
303
|
|
|
301
304
|
def self.truncate_changelog(changelog)
|
|
@@ -679,6 +682,35 @@ module Pilot
|
|
|
679
682
|
end
|
|
680
683
|
end
|
|
681
684
|
end
|
|
685
|
+
|
|
686
|
+
def update_routing_app_coverage(options)
|
|
687
|
+
# Skip logic entirely if no coverage file passed. So status-quo stays the same.
|
|
688
|
+
return unless options[:routing_app_coverage_file]
|
|
689
|
+
|
|
690
|
+
# We can only attach a coverage file to build upload - so pick the most recent edit.
|
|
691
|
+
platform = Spaceship::ConnectAPI::Platform.map(fetch_app_platform)
|
|
692
|
+
version = app.get_edit_app_store_version(platform: platform)
|
|
693
|
+
unless version
|
|
694
|
+
UI.important("Skipping upload of routing app coverage file - could not find an editable app store version")
|
|
695
|
+
return
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
routing_app_coverage =
|
|
699
|
+
begin
|
|
700
|
+
version.fetch_routing_app_coverage
|
|
701
|
+
rescue => error
|
|
702
|
+
UI.important("Error fetching routing app coverage - #{error.message}")
|
|
703
|
+
nil
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
if routing_app_coverage
|
|
707
|
+
UI.message("Removing previous routing app coverage file from App Store Connect")
|
|
708
|
+
routing_app_coverage.delete!
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
UI.message("Uploading routing app coverage file to App Store Connect")
|
|
712
|
+
version.upload_routing_app_coverage(path: options[:routing_app_coverage_file])
|
|
713
|
+
end
|
|
682
714
|
end
|
|
683
715
|
# rubocop:enable Metrics/ClassLength
|
|
684
716
|
end
|
data/pilot/lib/pilot/options.rb
CHANGED
|
@@ -201,6 +201,14 @@ module Pilot
|
|
|
201
201
|
optional: true,
|
|
202
202
|
type: Boolean,
|
|
203
203
|
default_value: false),
|
|
204
|
+
FastlaneCore::ConfigItem.new(key: :routing_app_coverage_file,
|
|
205
|
+
env_name: "PILOT_ROUTING_APP_COVERAGE_FILE",
|
|
206
|
+
description: "Path to the routing app coverage file (`.geojson`) that is required for routing apps. It will be uploaded to the editable App Store version of the app",
|
|
207
|
+
optional: true,
|
|
208
|
+
verify_block: proc do |value|
|
|
209
|
+
UI.user_error!("Could not find routing app coverage file at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
|
210
|
+
UI.user_error!("Routing app coverage file must be a .geojson file") unless File.extname(value).casecmp(".geojson").zero?
|
|
211
|
+
end),
|
|
204
212
|
|
|
205
213
|
# distribution
|
|
206
214
|
FastlaneCore::ConfigItem.new(key: :distribute_only,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
require 'ostruct'
|
|
1
2
|
require 'spaceship'
|
|
2
3
|
require_relative 'module'
|
|
4
|
+
require_relative 'service'
|
|
3
5
|
|
|
4
6
|
module Produce
|
|
5
7
|
class DeveloperCenter
|
|
@@ -86,6 +88,8 @@ module Produce
|
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
def create_new_app
|
|
91
|
+
return create_new_app_via_connect_api if using_connect_api?
|
|
92
|
+
|
|
89
93
|
ENV["CREATED_NEW_APP_ID"] = Time.now.to_i.to_s
|
|
90
94
|
if app_exists?
|
|
91
95
|
UI.success("[DevCenter] App '#{Produce.config[:app_identifier]}' already exists, nothing to do on the Dev Center")
|
|
@@ -118,6 +122,31 @@ module Produce
|
|
|
118
122
|
return true
|
|
119
123
|
end
|
|
120
124
|
|
|
125
|
+
# App Store Connect API key path — used instead of Spaceship.login.
|
|
126
|
+
def create_new_app_via_connect_api
|
|
127
|
+
config_enabled_services = Produce.config[:enable_services] || Produce.config[:enabled_features]
|
|
128
|
+
|
|
129
|
+
existing = Spaceship::ConnectAPI::BundleId.find(app_identifier)
|
|
130
|
+
if existing
|
|
131
|
+
UI.success("[DevCenter] App '#{Produce.config[:app_identifier]}' already exists, nothing to do on the Dev Center")
|
|
132
|
+
return true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
app_name = Produce.config[:app_name]
|
|
136
|
+
UI.message("Creating new app '#{app_name}' on the Apple Dev Center")
|
|
137
|
+
|
|
138
|
+
connect_api_platform = Spaceship::ConnectAPI::BundleIdPlatform.map(platform)
|
|
139
|
+
bundle_id = Spaceship::ConnectAPI::BundleId.create(name: app_name, platform: connect_api_platform, identifier: app_identifier)
|
|
140
|
+
|
|
141
|
+
UI.crash!("Something went wrong when creating the new app - it's not listed in the apps list") unless bundle_id
|
|
142
|
+
|
|
143
|
+
UI.message("Created app #{bundle_id.id}")
|
|
144
|
+
enable_inline_services(config_enabled_services) if config_enabled_services && !config_enabled_services.empty?
|
|
145
|
+
UI.success("Finished creating new app '#{app_name}' on the Dev Center")
|
|
146
|
+
|
|
147
|
+
return true
|
|
148
|
+
end
|
|
149
|
+
|
|
121
150
|
def enable_services
|
|
122
151
|
app_service = Spaceship.app_service
|
|
123
152
|
enabled_clean_options = {}
|
|
@@ -161,6 +190,17 @@ module Produce
|
|
|
161
190
|
|
|
162
191
|
private
|
|
163
192
|
|
|
193
|
+
# Delegates to Service#update instead of duplicating its ~40-capability mapping.
|
|
194
|
+
# Skips any capability explicitly marked "off" — meaningless on a brand-new app.
|
|
195
|
+
def enable_inline_services(config_enabled_services)
|
|
196
|
+
to_enable = config_enabled_services.reject { |_, v| v == SERVICE_OFF }
|
|
197
|
+
return if to_enable.empty?
|
|
198
|
+
|
|
199
|
+
options = OpenStruct.new(to_enable)
|
|
200
|
+
options.define_singleton_method(:__hash__) { to_enable }
|
|
201
|
+
Produce::Service.new.update(true, options)
|
|
202
|
+
end
|
|
203
|
+
|
|
164
204
|
def platform
|
|
165
205
|
# This was added to support creation of multiple platforms
|
|
166
206
|
# Produce::ItunesConnect can take an array of platforms to create for App Store Connect
|
|
@@ -174,9 +214,16 @@ module Produce
|
|
|
174
214
|
Spaceship.app.find(app_identifier, mac: platform == "osx") != nil
|
|
175
215
|
end
|
|
176
216
|
|
|
217
|
+
def using_connect_api?
|
|
218
|
+
!connect_api_token.nil?
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def connect_api_token
|
|
222
|
+
Spaceship::ConnectAPI::Token.from(hash: Produce.config[:api_key], filepath: Produce.config[:api_key_path])
|
|
223
|
+
end
|
|
224
|
+
|
|
177
225
|
def login
|
|
178
|
-
|
|
179
|
-
Spaceship.select_team
|
|
226
|
+
Produce.authenticate_connect_api!
|
|
180
227
|
end
|
|
181
228
|
end
|
|
182
229
|
end
|
|
@@ -38,7 +38,7 @@ module Produce
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
# Produce.config[:itc_users]
|
|
41
|
-
|
|
41
|
+
Spaceship::ConnectAPI::App.create(
|
|
42
42
|
name: Produce.config[:app_name],
|
|
43
43
|
version_string: Produce.config[:app_version] || "1.0",
|
|
44
44
|
sku: Produce.config[:sku].to_s,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'fastlane_core/helper'
|
|
2
|
+
require 'spaceship'
|
|
2
3
|
|
|
3
4
|
module Produce
|
|
4
5
|
class << self
|
|
@@ -11,4 +12,24 @@ module Produce
|
|
|
11
12
|
|
|
12
13
|
ENV['FASTLANE_TEAM_ID'] ||= ENV["PRODUCE_TEAM_ID"]
|
|
13
14
|
ENV['DELIVER_USER'] ||= ENV["PRODUCE_USERNAME"]
|
|
15
|
+
|
|
16
|
+
# Shared by DeveloperCenter#login and Service#bundle_id. Prefers a configured API key, falls
|
|
17
|
+
# back to a token already set by another lane (e.g. app_store_connect_api_key), then falls
|
|
18
|
+
# back to username-based session login.
|
|
19
|
+
def self.authenticate_connect_api!
|
|
20
|
+
if (token = Spaceship::ConnectAPI::Token.from(hash: Produce.config[:api_key], filepath: Produce.config[:api_key_path]))
|
|
21
|
+
UI.message("Authenticating with App Store Connect API Key")
|
|
22
|
+
|
|
23
|
+
# `current_team_id:` avoids a live, session-based team_id lookup elsewhere in
|
|
24
|
+
# ConnectAPI's provisioning client, which has no session to use here.
|
|
25
|
+
Spaceship::ConnectAPI.client = Spaceship::ConnectAPI::Client.new(token: token, current_team_id: Produce.config[:team_id])
|
|
26
|
+
elsif !Spaceship::ConnectAPI.token.nil?
|
|
27
|
+
UI.message("Using existing authorization token for App Store Connect API")
|
|
28
|
+
else
|
|
29
|
+
UI.message("Starting login with user '#{Produce.config[:username]}'")
|
|
30
|
+
Spaceship.login(Produce.config[:username], nil)
|
|
31
|
+
Spaceship.select_team
|
|
32
|
+
UI.message("Successfully logged in")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
14
35
|
end
|
|
@@ -17,6 +17,23 @@ module Produce
|
|
|
17
17
|
code_gen_sensitive: true,
|
|
18
18
|
default_value: user,
|
|
19
19
|
default_value_dynamic: true),
|
|
20
|
+
|
|
21
|
+
# App Store Connect API
|
|
22
|
+
FastlaneCore::ConfigItem.new(key: :api_key_path,
|
|
23
|
+
env_names: ["PRODUCE_API_KEY_PATH", "APP_STORE_CONNECT_API_KEY_PATH"],
|
|
24
|
+
description: "Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)",
|
|
25
|
+
optional: true,
|
|
26
|
+
conflicting_options: [:api_key],
|
|
27
|
+
verify_block: proc do |value|
|
|
28
|
+
UI.user_error!("Couldn't find API key JSON file at path '#{value}'") unless File.exist?(value)
|
|
29
|
+
end),
|
|
30
|
+
FastlaneCore::ConfigItem.new(key: :api_key,
|
|
31
|
+
env_names: ["PRODUCE_API_KEY", "APP_STORE_CONNECT_API_KEY"],
|
|
32
|
+
description: "Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-hash-option)",
|
|
33
|
+
type: Hash,
|
|
34
|
+
optional: true,
|
|
35
|
+
sensitive: true,
|
|
36
|
+
conflicting_options: [:api_key_path]),
|
|
20
37
|
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
|
21
38
|
env_name: "PRODUCE_APP_IDENTIFIER",
|
|
22
39
|
short_option: "-a",
|