fastlane 2.129.0 → 2.134.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +66 -66
- data/cert/lib/cert/module.rb +2 -0
- data/cert/lib/cert/options.rb +6 -0
- data/cert/lib/cert/runner.rb +17 -11
- data/fastlane/lib/fastlane.rb +4 -1
- data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/actions_helper.rb +4 -0
- data/fastlane/lib/fastlane/actions/app_store_build_number.rb +11 -3
- data/fastlane/lib/fastlane/actions/carthage.rb +11 -3
- data/fastlane/lib/fastlane/actions/cocoapods.rb +24 -2
- data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
- data/fastlane/lib/fastlane/actions/danger.rb +7 -0
- data/fastlane/lib/fastlane/actions/deploygate.rb +1 -1
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +23 -4
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +59 -10
- data/fastlane/lib/fastlane/actions/ensure_env_vars.rb +58 -0
- data/fastlane/lib/fastlane/actions/get_version_number.rb +12 -3
- data/fastlane/lib/fastlane/actions/gradle.rb +11 -1
- data/fastlane/lib/fastlane/actions/onesignal.rb +59 -29
- data/fastlane/lib/fastlane/actions/pod_push.rb +10 -1
- data/fastlane/lib/fastlane/actions/register_devices.rb +38 -22
- data/fastlane/lib/fastlane/actions/resign.rb +2 -2
- data/fastlane/lib/fastlane/actions/slather.rb +1 -0
- data/fastlane/lib/fastlane/actions/sonar.rb +16 -0
- data/fastlane/lib/fastlane/actions/testfairy.rb +1 -1
- data/fastlane/lib/fastlane/actions/update_fastlane.rb +9 -49
- data/fastlane/lib/fastlane/actions/update_keychain_access_groups.rb +94 -0
- data/fastlane/lib/fastlane/commands_generator.rb +16 -0
- data/fastlane/lib/fastlane/environment_printer.rb +7 -1
- data/fastlane/lib/fastlane/fast_file.rb +10 -4
- data/fastlane/lib/fastlane/helper/crashlytics_helper.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +2 -0
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +3 -0
- data/fastlane/lib/fastlane/setup/setup_android.rb +1 -1
- data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +122 -34
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +72 -3
- data/fastlane/lib/fastlane/swift_runner_upgrader.rb +4 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Actions.swift +15 -0
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +121 -1
- data/fastlane/swift/Fastlane.swift +3925 -30
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +9 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +91 -9
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +65 -1
- data/fastlane/swift/Plugins.swift +15 -0
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +15 -2
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +109 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +39 -2
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +71 -1
- data/fastlane/swift/upgrade_manifest.json +1 -1
- data/fastlane_core/lib/fastlane_core/command_executor.rb +1 -1
- data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
- data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +1 -3
- data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +3 -2
- data/frameit/lib/frameit/screenshot.rb +4 -0
- data/gym/lib/gym/generators/build_command_generator.rb +5 -1
- data/gym/lib/gym/options.rb +16 -16
- data/gym/lib/gym/runner.rb +33 -5
- data/match/lib/match/generator.rb +1 -0
- data/match/lib/match/importer.rb +2 -2
- data/match/lib/match/module.rb +2 -0
- data/match/lib/match/nuke.rb +5 -5
- data/match/lib/match/options.rb +17 -0
- data/match/lib/match/runner.rb +10 -6
- data/match/lib/match/storage/git_storage.rb +8 -2
- data/match/lib/match/storage/google_cloud_storage.rb +85 -33
- data/produce/lib/produce/service.rb +7 -1
- data/scan/lib/scan/error_handler.rb +9 -4
- data/scan/lib/scan/runner.rb +1 -1
- data/sigh/lib/sigh/download_all.rb +48 -8
- data/sigh/lib/sigh/runner.rb +13 -5
- data/snapshot/lib/snapshot/commands_generator.rb +2 -2
- data/snapshot/lib/snapshot/options.rb +5 -0
- data/snapshot/lib/snapshot/reports_generator.rb +3 -0
- data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +1 -1
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +16 -1
- data/snapshot/lib/snapshot/update.rb +4 -2
- data/spaceship/lib/spaceship/client.rb +3 -3
- data/spaceship/lib/spaceship/connect_api/models/app.rb +6 -6
- data/spaceship/lib/spaceship/connect_api/models/build.rb +3 -3
- data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/device.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +1 -1
- data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
- data/spaceship/lib/spaceship/portal/provisioning_profile.rb +1 -1
- data/spaceship/lib/spaceship/tunes/app_version.rb +4 -0
- data/spaceship/lib/spaceship/tunes/application.rb +4 -0
- data/spaceship/lib/spaceship/tunes/availability.rb +40 -8
- data/spaceship/lib/spaceship/tunes/b2b_organization.rb +50 -0
- data/spaceship/lib/spaceship/tunes/iap_family_details.rb +10 -2
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +26 -1
- metadata +55 -46
@@ -11,6 +11,7 @@ module Match
|
|
11
11
|
|
12
12
|
arguments = FastlaneCore::Configuration.create(Cert::Options.available_options, {
|
13
13
|
development: params[:type] == "development",
|
14
|
+
generate_apple_certs: params[:generate_apple_certs],
|
14
15
|
output_path: output_path,
|
15
16
|
force: true, # we don't need a certificate without its private key, we only care about a new certificate
|
16
17
|
username: params[:username],
|
data/match/lib/match/importer.rb
CHANGED
@@ -17,7 +17,7 @@ module Match
|
|
17
17
|
UI.user_error!("Certificate does not exist at path: #{cert_path}") unless File.exist?(cert_path)
|
18
18
|
UI.user_error!("Private key does not exist at path: #{p12_path}") unless File.exist?(p12_path)
|
19
19
|
|
20
|
-
# Base64
|
20
|
+
# Base64 encode contents to find match from API to find a cert ID
|
21
21
|
cert_contents_base_64 = Base64.strict_encode64(File.open(cert_path).read)
|
22
22
|
|
23
23
|
# Storage
|
@@ -72,7 +72,7 @@ module Match
|
|
72
72
|
cert.certificate_content == cert_contents_base_64
|
73
73
|
end
|
74
74
|
|
75
|
-
UI.
|
75
|
+
UI.user_error!("This certificate cannot be imported - the certificate contents did not match with any available on the Developer Portal") if matching_cert.nil?
|
76
76
|
|
77
77
|
# Make dir if doesn't exist
|
78
78
|
FileUtils.mkdir_p(output_dir)
|
data/match/lib/match/module.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'fastlane_core/helper'
|
2
|
+
require 'fastlane/boolean'
|
2
3
|
|
3
4
|
module Match
|
4
5
|
Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
|
5
6
|
UI = FastlaneCore::UI
|
7
|
+
Boolean = Fastlane::Boolean
|
6
8
|
ROOT = Pathname.new(File.expand_path('../../..', __FILE__))
|
7
9
|
DESCRIPTION = "Easily sync your certificates and profiles across your team"
|
8
10
|
|
data/match/lib/match/nuke.rb
CHANGED
@@ -100,7 +100,7 @@ module Match
|
|
100
100
|
prov_types = [:enterprise] if cert_type == :enterprise
|
101
101
|
|
102
102
|
Spaceship.login(params[:username])
|
103
|
-
Spaceship.select_team
|
103
|
+
Spaceship.select_team(team_id: params[:team_id], team_name: params[:team_name])
|
104
104
|
|
105
105
|
if Spaceship.client.in_house? && (type == "distribution" || type == "enterprise")
|
106
106
|
UI.error("---")
|
@@ -112,7 +112,7 @@ module Match
|
|
112
112
|
UI.user_error!("Enterprise account nuke cancelled") unless UI.confirm("Do you really want to nuke your Enterprise account?")
|
113
113
|
end
|
114
114
|
|
115
|
-
self.certs = certificate_type(cert_type).all
|
115
|
+
self.certs = certificate_type(cert_type).flat_map(&:all)
|
116
116
|
self.profiles = []
|
117
117
|
prov_types.each do |prov_type|
|
118
118
|
self.profiles += profile_type(prov_type).all
|
@@ -241,9 +241,9 @@ module Match
|
|
241
241
|
# The kind of certificate we're interested in
|
242
242
|
def certificate_type(type)
|
243
243
|
{
|
244
|
-
distribution: Spaceship.certificate.production,
|
245
|
-
development: Spaceship.certificate.development,
|
246
|
-
enterprise: Spaceship.certificate.in_house
|
244
|
+
distribution: [Spaceship.certificate.production, Spaceship.certificate.apple_distribution],
|
245
|
+
development: [Spaceship.certificate.development, Spaceship.certificate.apple_development],
|
246
|
+
enterprise: [Spaceship.certificate.in_house]
|
247
247
|
}[type] ||= raise "Unknown type '#{type}'"
|
248
248
|
end
|
249
249
|
|
data/match/lib/match/options.rb
CHANGED
@@ -32,6 +32,17 @@ module Match
|
|
32
32
|
description: "Only fetch existing certificates and profiles, don't generate new ones",
|
33
33
|
is_string: false,
|
34
34
|
default_value: false),
|
35
|
+
FastlaneCore::ConfigItem.new(key: :generate_apple_certs,
|
36
|
+
env_name: "MATCH_GENERATE_APPLE_CERTS",
|
37
|
+
description: "Create a certificate type for Xcode 11 and later (Apple Development or Apple Distribution)",
|
38
|
+
type: Boolean,
|
39
|
+
default_value: FastlaneCore::Helper.mac? && FastlaneCore::Helper.xcode_at_least?('11'),
|
40
|
+
default_value_dynamic: true),
|
41
|
+
FastlaneCore::ConfigItem.new(key: :skip_provisioning_profiles,
|
42
|
+
env_name: "MATCH_SKIP_PROVISIONING_PROFILES",
|
43
|
+
description: "Skip syncing provisioning profiles",
|
44
|
+
is_string: false,
|
45
|
+
default_value: false),
|
35
46
|
|
36
47
|
# app
|
37
48
|
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
@@ -110,6 +121,12 @@ module Match
|
|
110
121
|
description: "Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail",
|
111
122
|
is_string: false,
|
112
123
|
default_value: false),
|
124
|
+
FastlaneCore::ConfigItem.new(key: :git_basic_authorization,
|
125
|
+
env_name: "MATCH_GIT_BASIC_AUTHORIZATION",
|
126
|
+
sensitive: true,
|
127
|
+
description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64",
|
128
|
+
optional: true,
|
129
|
+
default_value: nil),
|
113
130
|
|
114
131
|
# Storage: Google Cloud
|
115
132
|
FastlaneCore::ConfigItem.new(key: :google_cloud_bucket_name,
|
data/match/lib/match/runner.rb
CHANGED
@@ -37,7 +37,9 @@ module Match
|
|
37
37
|
git_full_name: params[:git_full_name],
|
38
38
|
git_user_email: params[:git_user_email],
|
39
39
|
clone_branch_directly: params[:clone_branch_directly],
|
40
|
+
git_basic_authorization: params[:git_basic_authorization],
|
40
41
|
type: params[:type].to_s,
|
42
|
+
generate_apple_certs: params[:generate_apple_certs],
|
41
43
|
platform: params[:platform].to_s,
|
42
44
|
google_cloud_bucket_name: params[:google_cloud_bucket_name].to_s,
|
43
45
|
google_cloud_keys_file: params[:google_cloud_keys_file].to_s,
|
@@ -85,12 +87,14 @@ module Match
|
|
85
87
|
spaceship.certificate_exists(username: params[:username], certificate_id: cert_id) if spaceship
|
86
88
|
|
87
89
|
# Provisioning Profiles
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
unless params[:skip_provisioning_profiles]
|
91
|
+
app_identifiers.each do |app_identifier|
|
92
|
+
loop do
|
93
|
+
break if fetch_provisioning_profile(params: params,
|
94
|
+
certificate_id: cert_id,
|
95
|
+
app_identifier: app_identifier,
|
96
|
+
working_directory: storage.working_directory)
|
97
|
+
end
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -17,6 +17,7 @@ module Match
|
|
17
17
|
attr_accessor :clone_branch_directly
|
18
18
|
attr_accessor :type
|
19
19
|
attr_accessor :platform
|
20
|
+
attr_accessor :git_basic_authorization
|
20
21
|
|
21
22
|
def self.configure(params)
|
22
23
|
return self.new(
|
@@ -28,7 +29,8 @@ module Match
|
|
28
29
|
branch: params[:git_branch],
|
29
30
|
git_full_name: params[:git_full_name],
|
30
31
|
git_user_email: params[:git_user_email],
|
31
|
-
clone_branch_directly: params[:clone_branch_directly]
|
32
|
+
clone_branch_directly: params[:clone_branch_directly],
|
33
|
+
git_basic_authorization: params[:git_basic_authorization]
|
32
34
|
)
|
33
35
|
end
|
34
36
|
|
@@ -40,7 +42,8 @@ module Match
|
|
40
42
|
branch: "master",
|
41
43
|
git_full_name: nil,
|
42
44
|
git_user_email: nil,
|
43
|
-
clone_branch_directly: false
|
45
|
+
clone_branch_directly: false,
|
46
|
+
git_basic_authorization: nil)
|
44
47
|
self.git_url = git_url
|
45
48
|
self.shallow_clone = shallow_clone
|
46
49
|
self.skip_docs = skip_docs
|
@@ -48,6 +51,7 @@ module Match
|
|
48
51
|
self.git_full_name = git_full_name
|
49
52
|
self.git_user_email = git_user_email
|
50
53
|
self.clone_branch_directly = clone_branch_directly
|
54
|
+
self.git_basic_authorization = git_basic_authorization
|
51
55
|
|
52
56
|
self.type = type if type
|
53
57
|
self.platform = platform if platform
|
@@ -65,6 +69,8 @@ module Match
|
|
65
69
|
self.working_directory = Dir.mktmpdir
|
66
70
|
|
67
71
|
command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
|
72
|
+
command << " -c http.extraheader='AUTHORIZATION: basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
|
73
|
+
|
68
74
|
if self.shallow_clone
|
69
75
|
command << " --depth 1 --no-single-branch"
|
70
76
|
elsif self.clone_branch_directly
|
@@ -97,6 +97,7 @@ module Match
|
|
97
97
|
end
|
98
98
|
|
99
99
|
ensure_bucket_is_selected
|
100
|
+
check_bucket_permissions
|
100
101
|
end
|
101
102
|
|
102
103
|
def currently_used_team_id
|
@@ -234,74 +235,125 @@ module Match
|
|
234
235
|
end
|
235
236
|
end
|
236
237
|
|
237
|
-
# User doesn't seem to have provided a keys file
|
238
|
-
UI.message("Looks like you don't have a Google Cloud #{DEFAULT_KEYS_FILE_NAME.cyan} file")
|
239
|
-
UI.message("If you have one, make sure to put it into the '#{Dir.pwd}' directory and call it '#{DEFAULT_KEYS_FILE_NAME.cyan}'")
|
238
|
+
# User doesn't seem to have provided a keys file
|
239
|
+
UI.message("Looks like you don't have a Google Cloud #{DEFAULT_KEYS_FILE_NAME.cyan} file yet.")
|
240
|
+
UI.message("If you have one, make sure to put it into the '#{Dir.pwd}' directory and call it '#{DEFAULT_KEYS_FILE_NAME.cyan}'.")
|
240
241
|
unless UI.confirm("Do you want fastlane to help you to create a #{DEFAULT_KEYS_FILE_NAME} file?")
|
241
242
|
UI.user_error!("Process stopped, run fastlane again to start things up again")
|
242
243
|
end
|
243
244
|
|
244
|
-
UI.message("fastlane will help you create a keys file.
|
245
|
+
UI.message("fastlane will help you create a keys file. Start by opening the following website:")
|
245
246
|
UI.message("")
|
246
247
|
UI.message("\t\thttps://console.cloud.google.com".cyan)
|
247
248
|
UI.message("")
|
248
|
-
UI.input("Press
|
249
|
+
UI.input("Press [Enter] once you're logged in")
|
249
250
|
|
250
|
-
UI.message("Now it's time to generate a new JSON auth file for fastlane to access Google Cloud")
|
251
251
|
UI.message("First, switch to the Google Cloud project you want to use.")
|
252
|
-
UI.message("If you don't have one yet, create a new one and switch to it")
|
252
|
+
UI.message("If you don't have one yet, create a new one and switch to it.")
|
253
253
|
UI.message("")
|
254
|
-
UI.message("\t\thttps://console.cloud.google.com/
|
254
|
+
UI.message("\t\thttps://console.cloud.google.com/projectcreate".cyan)
|
255
255
|
UI.message("")
|
256
|
-
UI.input("
|
256
|
+
UI.input("Press [Enter] once you selected the right project")
|
257
257
|
|
258
|
-
UI.message("
|
258
|
+
UI.message("Next fastlane will show you the steps to create a keys file.")
|
259
|
+
UI.message("For this it might be useful to switch the Google Cloud interface to English.")
|
260
|
+
UI.message("Append " + "&hl=en".cyan + " to the URL and the interface should be in English.")
|
261
|
+
UI.input("Press [Enter] to continue")
|
262
|
+
|
263
|
+
UI.message("Now it's time to generate a new JSON auth file for fastlane to access Google Cloud Storage:")
|
259
264
|
UI.message("")
|
260
|
-
UI.message("\t\t 1.
|
261
|
-
UI.message("\t\t 2.
|
262
|
-
UI.message("\t\t 3.
|
263
|
-
UI.message("\t\t 4.
|
264
|
-
UI.message("\t\t 5.
|
265
|
+
UI.message("\t\t 1. From the side menu choose 'APIs & Services' and then 'Credentials'".cyan)
|
266
|
+
UI.message("\t\t 2. Click 'Create credentials'".cyan)
|
267
|
+
UI.message("\t\t 3. Choose 'Service account key'".cyan)
|
268
|
+
UI.message("\t\t 4. Select 'New service account'".cyan)
|
269
|
+
UI.message("\t\t 5. Enter a name and ID for the service account".cyan)
|
270
|
+
UI.message("\t\t 6. Don't give the service account a role just yet!".cyan)
|
271
|
+
UI.message("\t\t 7. Make sure the key type is set to 'JSON'".cyan)
|
272
|
+
UI.message("\t\t 8. Click 'Create'".cyan)
|
265
273
|
UI.message("")
|
266
|
-
UI.input("Confirm with
|
274
|
+
UI.input("Confirm with [Enter] once you created and downloaded the JSON file")
|
267
275
|
|
268
276
|
UI.message("Copy the file to the current directory (#{Dir.pwd})")
|
269
277
|
UI.message("and rename it to `#{DEFAULT_KEYS_FILE_NAME.cyan}`")
|
270
278
|
UI.message("")
|
271
|
-
UI.input("Confirm with
|
279
|
+
UI.input("Confirm with [Enter]")
|
272
280
|
|
273
281
|
until File.exist?(DEFAULT_KEYS_FILE_NAME)
|
274
282
|
UI.message("Make sure to place the file in '#{Dir.pwd.cyan}' and name it '#{DEFAULT_KEYS_FILE_NAME.cyan}'")
|
275
|
-
UI.
|
283
|
+
UI.message("")
|
284
|
+
UI.input("Confirm with [Enter]")
|
276
285
|
end
|
277
286
|
|
278
287
|
UI.important("Please never add the #{DEFAULT_KEYS_FILE_NAME.cyan} file in version control.")
|
279
|
-
UI.important("Instead please add the file to your
|
280
|
-
UI.
|
288
|
+
UI.important("Instead please add the file to your `.gitignore` file")
|
289
|
+
UI.message("")
|
290
|
+
UI.input("Confirm with [Enter]")
|
281
291
|
|
282
292
|
return DEFAULT_KEYS_FILE_NAME
|
283
293
|
end
|
284
294
|
|
285
295
|
def ensure_bucket_is_selected
|
286
|
-
#
|
287
|
-
|
296
|
+
# Skip the instructions if the user provided a bucket name
|
297
|
+
return unless self.bucket_name.to_s.length == 0
|
298
|
+
|
299
|
+
created_bucket = UI.confirm("Did you already create a Google Cloud Storage bucket?")
|
288
300
|
while self.bucket_name.to_s.length == 0
|
289
|
-
|
290
|
-
|
291
|
-
available_bucket_identifiers = self.gc_storage.buckets.collect(&:id)
|
292
|
-
if available_bucket_identifiers.count > 0
|
293
|
-
@bucket_name = UI.select("What Google Cloud Storage bucket do you want to use? (you can define it using the `google_cloud_bucket_name` key)", available_bucket_identifiers)
|
294
|
-
else
|
295
|
-
UI.error("Looks like your Google Cloud account for the project ID '#{self.google_cloud_project_id}' doesn't")
|
296
|
-
UI.error("have any available storage buckets yet. Please visit the following URL")
|
301
|
+
unless created_bucket
|
302
|
+
UI.message("Create a bucket at the following URL:")
|
297
303
|
UI.message("")
|
298
304
|
UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
|
299
305
|
UI.message("")
|
300
|
-
UI.message("
|
301
|
-
UI.message("click on " + "Create Bucket".cyan + ", choose a name and confirm")
|
306
|
+
UI.message("Make sure to select the right project at the top of the page!")
|
302
307
|
UI.message("")
|
303
|
-
UI.
|
308
|
+
UI.message("\t\t 1. Click 'Create bucket'".cyan)
|
309
|
+
UI.message("\t\t 2. Enter a unique name".cyan)
|
310
|
+
UI.message("\t\t 3. Select a geographic location for your bucket".cyan)
|
311
|
+
UI.message("\t\t 4. Make sure the storage class is set to 'Standard'".cyan)
|
312
|
+
UI.message("\t\t 5. Click 'Create' to create the bucket".cyan)
|
313
|
+
UI.message("")
|
314
|
+
UI.input("Press [Enter] once you created a bucket")
|
315
|
+
end
|
316
|
+
bucket_name = UI.input("Enter the name of your bucket: ")
|
317
|
+
|
318
|
+
# Verify if the bucket exists
|
319
|
+
begin
|
320
|
+
bucket_exists = !self.gc_storage.bucket(bucket_name).nil?
|
321
|
+
rescue Google::Cloud::PermissionDeniedError
|
322
|
+
bucket_exists = true
|
323
|
+
end
|
324
|
+
created_bucket = bucket_exists
|
325
|
+
if bucket_exists
|
326
|
+
@bucket_name = bucket_name
|
327
|
+
else
|
328
|
+
UI.error("It looks like the bucket '#{bucket_name}' doesn't exist. Make sure to create it first.")
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def check_bucket_permissions
|
334
|
+
bucket = nil
|
335
|
+
while bucket.nil?
|
336
|
+
begin
|
337
|
+
bucket = self.gc_storage.bucket(self.bucket_name)
|
338
|
+
rescue Google::Cloud::PermissionDeniedError
|
339
|
+
bucket = nil
|
304
340
|
end
|
341
|
+
return if bucket.nil? == false
|
342
|
+
UI.error("Looks like your Google Cloud account for the project ID '#{self.google_cloud_project_id}' doesn't")
|
343
|
+
UI.error("have access to the storage bucket '#{self.bucket_name}'. Please visit the following URL:")
|
344
|
+
UI.message("")
|
345
|
+
UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
|
346
|
+
UI.message("")
|
347
|
+
UI.message("You need to give your account the correct permissions:")
|
348
|
+
UI.message("")
|
349
|
+
UI.message("\t\t 1. Click on your bucket to open it".cyan)
|
350
|
+
UI.message("\t\t 2. Click 'Permissions'".cyan)
|
351
|
+
UI.message("\t\t 3. Click 'Add members'".cyan)
|
352
|
+
UI.message("\t\t 4. Enter the email of your service account".cyan)
|
353
|
+
UI.message("\t\t 5. Set the role to 'Storage Admin'".cyan)
|
354
|
+
UI.message("\t\t 6. Click 'Save'".cyan)
|
355
|
+
UI.message("")
|
356
|
+
UI.input("Confirm with [Enter] once you're finished")
|
305
357
|
end
|
306
358
|
end
|
307
359
|
end
|
@@ -229,7 +229,13 @@ module Produce
|
|
229
229
|
UI.message("\tPush Notifications")
|
230
230
|
|
231
231
|
if on
|
232
|
-
|
232
|
+
# Don't enable push notifications if already enabled
|
233
|
+
# Enabling push notifications when already on revokes certs
|
234
|
+
# https://github.com/fastlane/fastlane/issues/15315
|
235
|
+
# https://github.com/fastlane/fastlane/issues/8883
|
236
|
+
unless app.details.enable_services.include?("push")
|
237
|
+
app.update_service(Spaceship.app_service.push_notification.on)
|
238
|
+
end
|
233
239
|
else
|
234
240
|
app.update_service(Spaceship.app_service.push_notification.off)
|
235
241
|
end
|
@@ -6,8 +6,13 @@ module Scan
|
|
6
6
|
class << self
|
7
7
|
# @param [String] The output of the errored build
|
8
8
|
# This method should raise an exception in any case, as the return code indicated a failed build
|
9
|
-
def handle_build_error(output)
|
10
|
-
# The order of the handling below is
|
9
|
+
def handle_build_error(output, log_path)
|
10
|
+
# The order of the handling below is important
|
11
|
+
|
12
|
+
instruction = 'See the log'
|
13
|
+
location = Scan.config[:suppress_xcode_output] ? "here: '#{log_path}'" : "above"
|
14
|
+
details = "#{instruction} #{location}."
|
15
|
+
|
11
16
|
case output
|
12
17
|
when /US\-ASCII/
|
13
18
|
print("Your shell environment is not correctly configured")
|
@@ -23,7 +28,7 @@ module Scan
|
|
23
28
|
print("For more information visit this stackoverflow answer:")
|
24
29
|
print("https://stackoverflow.com/a/17031697/445598")
|
25
30
|
when /Testing failed/
|
26
|
-
UI.build_failure!("Error building the application
|
31
|
+
UI.build_failure!("Error building the application. #{details}")
|
27
32
|
when /Executed/, /Failing tests:/
|
28
33
|
# this is *really* important:
|
29
34
|
# we don't want to raise an exception here
|
@@ -38,7 +43,7 @@ module Scan
|
|
38
43
|
# followed by a list of tests that failed.
|
39
44
|
return
|
40
45
|
end
|
41
|
-
UI.build_failure!("Error building/testing the application
|
46
|
+
UI.build_failure!("Error building/testing the application. #{details}")
|
42
47
|
end
|
43
48
|
|
44
49
|
private
|
data/scan/lib/scan/runner.rb
CHANGED
@@ -67,7 +67,7 @@ module Scan
|
|
67
67
|
error: proc do |error_output|
|
68
68
|
begin
|
69
69
|
exit_status = $?.exitstatus
|
70
|
-
ErrorHandler.handle_build_error(error_output)
|
70
|
+
ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
|
71
71
|
rescue => ex
|
72
72
|
SlackPoster.new.run({
|
73
73
|
build_errors: 1
|
@@ -12,7 +12,42 @@ module Sigh
|
|
12
12
|
Spaceship.select_team
|
13
13
|
UI.message("Successfully logged in")
|
14
14
|
|
15
|
-
|
15
|
+
case Sigh.config[:platform].to_s
|
16
|
+
when 'ios'
|
17
|
+
download_profiles(Spaceship.provisioning_profile.all(xcode: download_xcode_profiles))
|
18
|
+
xcode_profiles_downloaded?(xcode: download_xcode_profiles, supported: true)
|
19
|
+
when 'macos'
|
20
|
+
download_profiles(Spaceship.provisioning_profile.all(mac: true, xcode: download_xcode_profiles))
|
21
|
+
xcode_profiles_downloaded?(xcode: download_xcode_profiles, supported: true)
|
22
|
+
when 'tvos'
|
23
|
+
download_profiles(Spaceship.provisioning_profile.all_tvos)
|
24
|
+
xcode_profiles_downloaded?(xcode: download_xcode_profiles, supported: false)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param xcode [Bool] Whether or not the user passed the download_xcode_profiles flag
|
29
|
+
# @param supported [Bool] Whether or not this platform supports downloading xcode profiles at all
|
30
|
+
def xcode_profiles_downloaded?(xcode: false, supported: false)
|
31
|
+
if supported
|
32
|
+
if xcode
|
33
|
+
UI.message("This run also included all Xcode managed provisioning profiles, as you used the `--download_xcode_profiles` flag")
|
34
|
+
elsif !xcode
|
35
|
+
UI.message("All Xcode managed provisioning profiles were ignored on this, to include them use the `--download_xcode_profiles` flag")
|
36
|
+
end
|
37
|
+
|
38
|
+
elsif !supported
|
39
|
+
if xcode
|
40
|
+
UI.important("Downloading Xcode managed profiles is not supported for platform #{Sigh.config[:platform]}")
|
41
|
+
return
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param profiles [Array] Array of all the provisioning profiles we want to download
|
47
|
+
def download_profiles(profiles)
|
48
|
+
UI.important("No profiles available for download") if profiles.empty?
|
49
|
+
|
50
|
+
profiles.each do |profile|
|
16
51
|
if profile.valid?
|
17
52
|
UI.message("Downloading profile '#{profile.name}'...")
|
18
53
|
download_profile(profile)
|
@@ -20,19 +55,24 @@ module Sigh
|
|
20
55
|
UI.important("Skipping invalid/expired profile '#{profile.name}'")
|
21
56
|
end
|
22
57
|
end
|
23
|
-
|
24
|
-
if download_xcode_profiles
|
25
|
-
UI.message("This run also included all Xcode managed provisioning profiles, as you used the `--download_xcode_profiles` flag")
|
26
|
-
else
|
27
|
-
UI.message("All Xcode managed provisioning profiles were ignored on this, to include them use the `--download_xcode_profiles` flag")
|
28
|
-
end
|
29
58
|
end
|
30
59
|
|
60
|
+
# @param profile [ProvisioningProfile] A profile we plan to download and store
|
31
61
|
def download_profile(profile)
|
32
62
|
FileUtils.mkdir_p(Sigh.config[:output_path])
|
33
63
|
|
34
64
|
type_name = profile.class.pretty_type
|
35
|
-
profile_name = "#{type_name}_#{profile.uuid}_#{profile.app.bundle_id}
|
65
|
+
profile_name = "#{type_name}_#{profile.uuid}_#{profile.app.bundle_id}"
|
66
|
+
|
67
|
+
if Sigh.config[:platform].to_s == 'tvos'
|
68
|
+
profile_name += "_tvos"
|
69
|
+
end
|
70
|
+
|
71
|
+
if Sigh.config[:platform].to_s == 'macos'
|
72
|
+
profile_name += '.provisionprofile'
|
73
|
+
else
|
74
|
+
profile_name += '.mobileprovision'
|
75
|
+
end
|
36
76
|
|
37
77
|
output_path = File.join(Sigh.config[:output_path], profile_name)
|
38
78
|
File.open(output_path, "wb") do |f|
|