fastlane 2.131.0 → 2.132.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.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +76 -76
  3. data/cert/lib/cert/module.rb +2 -0
  4. data/cert/lib/cert/options.rb +6 -0
  5. data/cert/lib/cert/runner.rb +17 -11
  6. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +10 -2
  7. data/fastlane/lib/fastlane/actions/copy_artifacts.rb +1 -1
  8. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +23 -4
  9. data/fastlane/lib/fastlane/actions/ensure_env_vars.rb +58 -0
  10. data/fastlane/lib/fastlane/actions/get_version_number.rb +3 -0
  11. data/fastlane/lib/fastlane/actions/onesignal.rb +59 -29
  12. data/fastlane/lib/fastlane/actions/pod_push.rb +10 -1
  13. data/fastlane/lib/fastlane/actions/register_devices.rb +1 -1
  14. data/fastlane/lib/fastlane/fast_file.rb +7 -2
  15. data/fastlane/lib/fastlane/setup/setup_android.rb +1 -1
  16. data/fastlane/lib/fastlane/version.rb +1 -1
  17. data/fastlane/swift/Deliverfile.swift +1 -1
  18. data/fastlane/swift/Fastlane.swift +33 -7
  19. data/fastlane/swift/Gymfile.swift +1 -1
  20. data/fastlane/swift/Matchfile.swift +1 -1
  21. data/fastlane/swift/MatchfileProtocol.swift +5 -1
  22. data/fastlane/swift/Precheckfile.swift +1 -1
  23. data/fastlane/swift/Scanfile.swift +1 -1
  24. data/fastlane/swift/Screengrabfile.swift +1 -1
  25. data/fastlane/swift/Snapshotfile.swift +1 -1
  26. data/fastlane/swift/SnapshotfileProtocol.swift +3 -1
  27. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +1 -3
  28. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +3 -2
  29. data/frameit/lib/frameit/screenshot.rb +4 -0
  30. data/match/lib/match/generator.rb +1 -0
  31. data/match/lib/match/module.rb +2 -0
  32. data/match/lib/match/nuke.rb +5 -5
  33. data/match/lib/match/options.rb +12 -0
  34. data/match/lib/match/runner.rb +2 -0
  35. data/match/lib/match/storage/git_storage.rb +8 -2
  36. data/match/lib/match/storage/google_cloud_storage.rb +82 -33
  37. data/produce/lib/produce/service.rb +7 -1
  38. data/sigh/lib/sigh/runner.rb +13 -5
  39. data/snapshot/lib/snapshot/options.rb +5 -0
  40. data/snapshot/lib/snapshot/reports_generator.rb +3 -0
  41. data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
  42. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +1 -1
  43. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +16 -1
  44. data/spaceship/lib/spaceship/connect_api/models/app.rb +6 -6
  45. data/spaceship/lib/spaceship/connect_api/models/build.rb +3 -3
  46. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +1 -1
  47. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +1 -1
  48. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +1 -1
  49. data/spaceship/lib/spaceship/connect_api/models/device.rb +1 -1
  50. data/spaceship/lib/spaceship/connect_api/models/profile.rb +1 -1
  51. data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
  52. data/spaceship/lib/spaceship/portal/provisioning_profile.rb +1 -1
  53. data/spaceship/lib/spaceship/tunes/app_version.rb +4 -0
  54. data/spaceship/lib/spaceship/tunes/application.rb +4 -0
  55. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +10 -2
  56. data/spaceship/lib/spaceship/tunes/tunes_client.rb +25 -0
  57. metadata +48 -45
@@ -1,6 +1,7 @@
1
1
  protocol MatchfileProtocol: class {
2
2
  var type: String { get }
3
3
  var readonly: Bool { get }
4
+ var generateAppleCerts: Bool { get }
4
5
  var skipProvisioningProfiles: Bool { get }
5
6
  var appIdentifier: [String] { get }
6
7
  var username: String { get }
@@ -13,6 +14,7 @@ protocol MatchfileProtocol: class {
13
14
  var gitUserEmail: String? { get }
14
15
  var shallowClone: Bool { get }
15
16
  var cloneBranchDirectly: Bool { get }
17
+ var gitBasicAuthorization: String? { get }
16
18
  var googleCloudBucketName: String? { get }
17
19
  var googleCloudKeysFile: String? { get }
18
20
  var googleCloudProjectId: String? { get }
@@ -31,6 +33,7 @@ protocol MatchfileProtocol: class {
31
33
  extension MatchfileProtocol {
32
34
  var type: String { return "development" }
33
35
  var readonly: Bool { return false }
36
+ var generateAppleCerts: Bool { return true }
34
37
  var skipProvisioningProfiles: Bool { return false }
35
38
  var appIdentifier: [String] { return [] }
36
39
  var username: String { return "" }
@@ -43,6 +46,7 @@ extension MatchfileProtocol {
43
46
  var gitUserEmail: String? { return nil }
44
47
  var shallowClone: Bool { return false }
45
48
  var cloneBranchDirectly: Bool { return false }
49
+ var gitBasicAuthorization: String? { return nil }
46
50
  var googleCloudBucketName: String? { return nil }
47
51
  var googleCloudKeysFile: String? { return nil }
48
52
  var googleCloudProjectId: String? { return nil }
@@ -60,4 +64,4 @@ extension MatchfileProtocol {
60
64
 
61
65
  // Please don't remove the lines below
62
66
  // They are used to detect outdated files
63
- // FastlaneRunnerAPIVersion [0.9.6]
67
+ // FastlaneRunnerAPIVersion [0.9.7]
@@ -18,4 +18,4 @@ class Precheckfile: PrecheckfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.131.0
21
+ // Generated with fastlane 2.132.0
@@ -18,4 +18,4 @@ class Scanfile: ScanfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.131.0
21
+ // Generated with fastlane 2.132.0
@@ -18,4 +18,4 @@ class Screengrabfile: ScreengrabfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.131.0
21
+ // Generated with fastlane 2.132.0
@@ -18,4 +18,4 @@ class Snapshotfile: SnapshotfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.131.0
21
+ // Generated with fastlane 2.132.0
@@ -15,6 +15,7 @@ protocol SnapshotfileProtocol: class {
15
15
  var reinstallApp: Bool { get }
16
16
  var eraseSimulator: Bool { get }
17
17
  var localizeSimulator: Bool { get }
18
+ var darkMode: Bool? { get }
18
19
  var appIdentifier: String? { get }
19
20
  var addPhotos: [String]? { get }
20
21
  var addVideos: [String]? { get }
@@ -51,6 +52,7 @@ extension SnapshotfileProtocol {
51
52
  var reinstallApp: Bool { return false }
52
53
  var eraseSimulator: Bool { return false }
53
54
  var localizeSimulator: Bool { return false }
55
+ var darkMode: Bool? { return nil }
54
56
  var appIdentifier: String? { return nil }
55
57
  var addPhotos: [String]? { return nil }
56
58
  var addVideos: [String]? { return nil }
@@ -72,4 +74,4 @@ extension SnapshotfileProtocol {
72
74
 
73
75
  // Please don't remove the lines below
74
76
  // They are used to detect outdated files
75
- // FastlaneRunnerAPIVersion [0.9.4]
77
+ // FastlaneRunnerAPIVersion [0.9.5]
@@ -154,7 +154,7 @@ module FastlaneCore
154
154
  # As there was no communication from Apple, we don't know if this is a temporary
155
155
  # server outage, or something they changed without giving a heads-up
156
156
  if ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"].to_s.length == 0
157
- ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"] = "-t DAV"
157
+ ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"] = "-t DAV,Signiant"
158
158
  end
159
159
  return ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"]
160
160
  end
@@ -170,7 +170,6 @@ module FastlaneCore
170
170
  "-p #{shell_escaped_password(password)}",
171
171
  "-f \"#{source}\"",
172
172
  additional_upload_parameters, # that's here, because the user might overwrite the -t option
173
- "-t Signiant",
174
173
  "-k 100000",
175
174
  ("-WONoPause true" if Helper.windows?), # Windows only: process instantly returns instead of waiting for key press
176
175
  ("-itc_provider #{provider_short_name}" unless provider_short_name.to_s.empty?)
@@ -255,7 +254,6 @@ module FastlaneCore
255
254
  "-p #{password.shellescape}",
256
255
  "-f #{source.shellescape}",
257
256
  additional_upload_parameters, # that's here, because the user might overwrite the -t option
258
- '-t Signiant',
259
257
  '-k 100000',
260
258
  ("-itc_provider #{provider_short_name}" unless provider_short_name.to_s.empty?),
261
259
  '2>&1' # cause stderr to be written to stdout
@@ -30,12 +30,13 @@ module FastlaneCore
30
30
  end
31
31
 
32
32
  def format_string(datetime = Time.now, severity = "")
33
+ timezone_string = !FastlaneCore::Env.truthy?('FASTLANE_SHOW_TIMEZONE') ? '' : ' %z'
33
34
  if FastlaneCore::Globals.verbose?
34
- return "#{severity} [#{datetime.strftime('%Y-%m-%d %H:%M:%S.%2N')}]: "
35
+ return "#{severity} [#{datetime.strftime('%Y-%m-%d %H:%M:%S.%2N' + timezone_string)}]: "
35
36
  elsif FastlaneCore::Env.truthy?("FASTLANE_HIDE_TIMESTAMP")
36
37
  return ""
37
38
  else
38
- return "[#{datetime.strftime('%H:%M:%S')}]: "
39
+ return "[#{datetime.strftime('%H:%M:%S' + timezone_string)}]: "
39
40
  end
40
41
  end
41
42
 
@@ -45,6 +45,10 @@ module Frameit
45
45
  return 'iPhone 4'
46
46
  when sizes::IOS_IPAD
47
47
  return 'iPad Air 2'
48
+ when sizes::IOS_IPAD_10_5
49
+ return 'iPad Pro (10.5-inch)'
50
+ when sizes::IOS_IPAD_11
51
+ return 'iPad Pro (11-inch)'
48
52
  when sizes::IOS_IPAD_PRO
49
53
  return 'iPad Pro'
50
54
  when sizes::IOS_IPAD_PRO_12_9
@@ -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],
@@ -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
 
@@ -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
 
@@ -32,6 +32,12 @@ 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),
35
41
  FastlaneCore::ConfigItem.new(key: :skip_provisioning_profiles,
36
42
  env_name: "MATCH_SKIP_PROVISIONING_PROFILES",
37
43
  description: "Skip syncing provisioning profiles",
@@ -115,6 +121,12 @@ module Match
115
121
  description: "Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail",
116
122
  is_string: false,
117
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),
118
130
 
119
131
  # Storage: Google Cloud
120
132
  FastlaneCore::ConfigItem.new(key: :google_cloud_bucket_name,
@@ -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,
@@ -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,122 @@ 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. First, open the following website")
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 enter once you're logged in")
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/apis/credentials".cyan)
254
+ UI.message("\t\thttps://console.cloud.google.com/projectcreate".cyan)
255
255
  UI.message("")
256
- UI.input("Ensure the right project is selected on top of the page and confirm with enter")
256
+ UI.input("Press [Enter] once you selected the right project")
257
257
 
258
- UI.message("Now create a new JSON auth file by clicking on")
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. Create credentials".cyan)
261
- UI.message("\t\t 2. Service account key".cyan)
262
- UI.message("\t\t 3. App Engine default service account".cyan)
263
- UI.message("\t\t 4. JSON".cyan)
264
- UI.message("\t\t 5. Create".cyan)
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 enter once you created and download the JSON file")
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 enter")
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.input("Confirm with enter")
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 .gitignore")
280
- UI.input("Confirm with enter")
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
- # In case the user didn't provide a bucket name yet, they will
287
- # be asked to provide one here
296
+ created_bucket = UI.confirm("Did you already create a Google Cloud Storage bucket?")
288
297
  while self.bucket_name.to_s.length == 0
289
- # Have a nice selection of the available buckets here
290
- # This can only happen after we went through auth of Google Cloud
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")
298
+ unless created_bucket
299
+ UI.message("Create a bucket at the following URL:")
297
300
  UI.message("")
298
301
  UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
299
302
  UI.message("")
300
- UI.message("and make sure to have the right project selected on top of the page")
301
- UI.message("click on " + "Create Bucket".cyan + ", choose a name and confirm")
303
+ UI.message("Make sure to select the right project at the top of the page!")
304
+ UI.message("")
305
+ UI.message("\t\t 1. Click 'Create bucket'".cyan)
306
+ UI.message("\t\t 2. Enter a unique name".cyan)
307
+ UI.message("\t\t 3. Select a geographic location for your bucket".cyan)
308
+ UI.message("\t\t 4. Make sure the storage class is set to 'Standard'".cyan)
309
+ UI.message("\t\t 5. Click 'Create' to create the bucket".cyan)
302
310
  UI.message("")
303
- UI.input("Once you're finished, please confirm with enter")
311
+ UI.input("Press [Enter] once you created a bucket")
312
+ end
313
+ bucket_name = UI.input("Enter the name of your bucket: ")
314
+
315
+ # Verify if the bucket exists
316
+ begin
317
+ bucket_exists = !self.gc_storage.bucket(bucket_name).nil?
318
+ rescue Google::Cloud::PermissionDeniedError
319
+ bucket_exists = true
320
+ end
321
+ created_bucket = bucket_exists
322
+ if bucket_exists
323
+ @bucket_name = bucket_name
324
+ else
325
+ UI.error("It looks like the bucket '#{bucket_name}' doesn't exist. Make sure to create it first.")
326
+ end
327
+ end
328
+ end
329
+
330
+ def check_bucket_permissions
331
+ bucket = nil
332
+ while bucket.nil?
333
+ begin
334
+ bucket = self.gc_storage.bucket(self.bucket_name)
335
+ rescue Google::Cloud::PermissionDeniedError
336
+ bucket = nil
304
337
  end
338
+ return if bucket.nil? == false
339
+ UI.error("Looks like your Google Cloud account for the project ID '#{self.google_cloud_project_id}' doesn't")
340
+ UI.error("have access to the storage bucket '#{self.bucket_name}'. Please visit the following URL:")
341
+ UI.message("")
342
+ UI.message("\t\thttps://console.cloud.google.com/storage/browser".cyan)
343
+ UI.message("")
344
+ UI.message("You need to give your account the correct permissions:")
345
+ UI.message("")
346
+ UI.message("\t\t 1. Click on your bucket to open it".cyan)
347
+ UI.message("\t\t 2. Click 'Permissions'".cyan)
348
+ UI.message("\t\t 3. Click 'Add members'".cyan)
349
+ UI.message("\t\t 4. Enter the email of your service account".cyan)
350
+ UI.message("\t\t 5. Set the role to 'Storage Admin'".cyan)
351
+ UI.message("\t\t 6. Click 'Save'".cyan)
352
+ UI.message("")
353
+ UI.input("Confirm with [Enter] once you're finished")
305
354
  end
306
355
  end
307
356
  end
@@ -229,7 +229,13 @@ module Produce
229
229
  UI.message("\tPush Notifications")
230
230
 
231
231
  if on
232
- app.update_service(Spaceship.app_service.push_notification.on)
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