fastlane 2.131.0 → 2.132.0

Sign up to get free protection for your applications and to get access to all the features.
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