fastlane 2.29.0 → 2.29.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2d6217752222539765f18e46a3582ad5a321161
4
- data.tar.gz: 221fa664a19e757b4afea97366750538d5a93c1a
3
+ metadata.gz: 4df803cb7188d41a48f3d759d9c163b6ba0727f9
4
+ data.tar.gz: b85c21bdcbf222cf50d54cc090b8c8e4e9b7fd8f
5
5
  SHA512:
6
- metadata.gz: 526b2ce145766d25900135abb2167722cf2a2d11570fed52b03d345262dceabbf231a91f0e062923b4efeb3b8cbb7124b2d2cff7a27eeef8589df981524c87b7
7
- data.tar.gz: 27ac8cc060cd9968f0ec44c291bd99b28934d8b1cd4782088fd00b61c6f4cb8e124c153b0107d19901dfd64c4f327c9f6827501f97fc5767de608a5fc2712f4f
6
+ metadata.gz: 447d8827823088b25927f9013be1b6c2013722981a599556848fc83c4b2e0b50a4879deede3f592940f603cb6aab7dde33ba84aa364bef795e67b11cee7271fb
7
+ data.tar.gz: dbd5145ed06f18ada1d6efd993ffc1821753c52c7b4e515ef865c4dcbb863d82545c79b893fdc770048cbd0f5059c24cd3fd15aab434a86dc4c4a606fb92b002
@@ -118,13 +118,13 @@
118
118
  margin-right: 20px;
119
119
  }
120
120
 
121
- .app-review-information {
121
+ .app-minor-information {
122
122
  margin-left: 15px;
123
123
  margin-right: 15px;
124
124
  margin-top: 22px;
125
125
  }
126
126
 
127
- .app-review-information-key {
127
+ .app-minor-information-key {
128
128
  font-weight: 700;
129
129
  }
130
130
  </style>
@@ -241,20 +241,37 @@
241
241
 
242
242
  <hr />
243
243
  <% end # end data %>
244
+ <% if @options[:trade_representative_contact_information] %>
245
+ <div class="app-minor-information">
246
+ <div class="cat-headline">Trade Representative Contact Information</div>
247
+ <dl class="app-minor-information">
248
+ <% @options[:trade_representative_contact_information].each do |key, value| %>
249
+ <dt class="app-minor-information-key">
250
+ <%= key.to_s.capitalize.gsub("_", " ") %>
251
+ </dt>
252
+ <dd class="app-minor-information-text">
253
+ <%= (value || '').gsub("\n", "<br />") %>
254
+ </dd>
255
+ <% end %>
256
+ </dl>
257
+ </div>
258
+ <hr />
259
+ <% end %>
260
+
244
261
  <% if @options[:app_review_information] %>
245
- <div class="app-review-information">
262
+ <div class="app-minor-information">
246
263
  <div class="cat-headline">Review Information</div>
247
- <dl class="app-review-information">
264
+ <dl class="app-minor-information">
248
265
  <% @options[:app_review_information].each do |key, value| %>
249
- <dt class="app-review-information-key">
266
+ <dt class="app-minor-information-key">
250
267
  <%= key.to_s.capitalize.gsub("_", " ") %>
251
268
  </dt>
252
- <dd class="app-review-information-text">
269
+ <dd class="app-minor-information-text">
253
270
  <%= (value || '').gsub("\n", "<br />") %>
254
271
  </dd>
255
272
  <% end %>
256
273
  </dl>
257
274
  </div>
258
- <% end %>
275
+ <% end %>
259
276
  </body>
260
277
  </html>
@@ -228,6 +228,10 @@ module Deliver
228
228
  description: "Metadata: The english name of the secondary second sub category(e.g. `Educational`, `Puzzle`)",
229
229
  optional: true,
230
230
  is_string: true),
231
+ FastlaneCore::ConfigItem.new(key: :trade_representative_contact_information,
232
+ description: "Metadata: A hash containing the trade representative contact information",
233
+ optional: true,
234
+ is_string: false),
231
235
  FastlaneCore::ConfigItem.new(key: :app_review_information,
232
236
  description: "Metadata: A hash containing the review information",
233
237
  optional: true,
@@ -66,6 +66,17 @@ module Deliver
66
66
  UI.message("Writing to '#{resulting_path}'")
67
67
  end
68
68
 
69
+ # Trade Representative Contact Information
70
+ UploadMetadata::TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES.each do |key, option_name|
71
+ content = v.send(key).to_s
72
+ content << "\n"
73
+ base_dir = File.join(path, UploadMetadata::TRADE_REPRESENTATIVE_CONTACT_INFORMATION_DIR)
74
+ FileUtils.mkdir_p(base_dir)
75
+ resulting_path = File.join(base_dir, "#{option_name}.txt")
76
+ File.write(resulting_path, content)
77
+ UI.message("Writing to '#{resulting_path}'")
78
+ end
79
+
69
80
  # Review information
70
81
  UploadMetadata::REVIEW_INFORMATION_VALUES.each do |key, option_name|
71
82
  content = v.send(key).to_s
@@ -15,6 +15,23 @@ module Deliver
15
15
  :primary_first_sub_category, :primary_second_sub_category,
16
16
  :secondary_first_sub_category, :secondary_second_sub_category]
17
17
 
18
+ # Trade Representative Contact Information values
19
+ TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES = {
20
+ trade_representative_trade_name: :trade_name,
21
+ trade_representative_first_name: :first_name,
22
+ trade_representative_last_name: :last_name,
23
+ trade_representative_address_line_1: :adderss_line1,
24
+ trade_representative_address_line_2: :adderss_line2,
25
+ trade_representative_address_line_3: :adderss_line3,
26
+ trade_representative_city_name: :city_name,
27
+ trade_representative_state: :state,
28
+ trade_representative_country: :country,
29
+ trade_representative_postal_code: :postal_code,
30
+ trade_representative_phone_number: :phone_number,
31
+ trade_representative_email: :email_address,
32
+ trade_representative_is_displayed_on_app_store: :is_displayed_on_app_store
33
+ }
34
+
18
35
  # Review information values
19
36
  REVIEW_INFORMATION_VALUES = {
20
37
  review_first_name: :first_name,
@@ -32,6 +49,9 @@ module Deliver
32
49
  # Non localized app details values, that are editable in live state
33
50
  NON_LOCALISED_LIVE_VALUES = [:privacy_url]
34
51
 
52
+ # Directory name it contains trade representative contact information
53
+ TRADE_REPRESENTATIVE_CONTACT_INFORMATION_DIR = "trade_representative_contact_information"
54
+
35
55
  # Directory name it contains review information
36
56
  REVIEW_INFORMATION_DIR = "review_information"
37
57
 
@@ -92,6 +112,7 @@ module Deliver
92
112
 
93
113
  v.release_on_approval = options[:automatic_release]
94
114
 
115
+ set_trade_representative_contact_information(v, options)
95
116
  set_review_information(v, options)
96
117
  set_app_rating(v, options)
97
118
 
@@ -198,6 +219,17 @@ module Deliver
198
219
  options[key] ||= File.read(path)
199
220
  end
200
221
 
222
+ # Load trade representative contact information
223
+ options[:trade_representative_contact_information] ||= {}
224
+ TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES.values.each do |option_name|
225
+ path = File.join(options[:metadata_path], TRADE_REPRESENTATIVE_CONTACT_INFORMATION_DIR, "#{option_name}.txt")
226
+ next unless File.exist?(path)
227
+ next if options[:trade_representative_contact_information][option_name].to_s.length > 0
228
+
229
+ UI.message("Loading '#{path}'...")
230
+ options[:trade_representative_contact_information][option_name] ||= File.read(path)
231
+ end
232
+
201
233
  # Load review information
202
234
  options[:app_review_information] ||= {}
203
235
  REVIEW_INFORMATION_VALUES.values.each do |option_name|
@@ -212,6 +244,16 @@ module Deliver
212
244
 
213
245
  private
214
246
 
247
+ def set_trade_representative_contact_information(v, options)
248
+ return unless options[:trade_representative_contact_information]
249
+ info = options[:trade_representative_contact_information]
250
+ UI.user_error!("`trade_representative_contact_information` must be a hash", show_github_issues: true) unless info.kind_of?(Hash)
251
+
252
+ TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES.each do |key, option_name|
253
+ v.send("#{key}=", info[option_name].chomp) if info[option_name].chomp
254
+ end
255
+ end
256
+
215
257
  def set_review_information(v, options)
216
258
  return unless options[:app_review_information]
217
259
  info = options[:app_review_information]
@@ -57,8 +57,7 @@ module Fastlane
57
57
  update_needed.each do |tool_info|
58
58
  tool = tool_info[0]
59
59
  local_version = Gem::Version.new(highest_versions[tool].version)
60
- update_url = FastlaneCore::UpdateChecker.generate_fetch_url(tool)
61
- latest_version = FastlaneCore::UpdateChecker.fetch_latest(update_url)
60
+ latest_version = FastlaneCore::UpdateChecker.fetch_latest(tool)
62
61
  UI.message("Updating #{tool} from #{local_version} to #{latest_version} ... 🚀")
63
62
 
64
63
  # Approximate_recommendation will create a string like "~> 0.10" from a version 0.10.0, e.g. one that is valid for versions >= 0.10 and <1.0
@@ -73,7 +73,29 @@ module Fastlane
73
73
  else
74
74
  puts "Couldn't find action for the given filter.".red
75
75
  puts "==========================================\n".red
76
+
76
77
  print_all # show all available actions instead
78
+ print_suggestions(filter)
79
+ end
80
+ end
81
+
82
+ def self.print_suggestions(filter)
83
+ if !filter.nil? && filter.length > 1
84
+ action_names = []
85
+ all_actions(nil) do |action_ref, action_name|
86
+ action_names << action_name
87
+ end
88
+
89
+ corrections = []
90
+
91
+ if !Gem.loaded_specs["did_you_mean"].nil? && Gem.loaded_specs["did_you_mean"].version >= Gem::Version.new('1.1.0')
92
+ spell_checker = DidYouMean::SpellChecker.new(dictionary: action_names)
93
+ corrections << spell_checker.correct(filter).compact
94
+ end
95
+
96
+ corrections << action_names.select { |name| name.include? filter }
97
+
98
+ puts "Did you mean: #{corrections.flatten.uniq.join(', ')}?".green unless corrections.flatten.empty?
77
99
  end
78
100
  end
79
101
 
@@ -62,17 +62,16 @@ module Fastlane
62
62
  table << "|--------|---------|\n"
63
63
  plugin_manager.available_plugins.each do |plugin|
64
64
  begin
65
- installed_version = Fastlane::ActionCollector.determine_version(plugin)
66
- update_url = FastlaneCore::UpdateChecker.generate_fetch_url(plugin)
67
- latest_version = FastlaneCore::UpdateChecker.fetch_latest(update_url)
68
- if Gem::Version.new(installed_version) == Gem::Version.new(latest_version)
69
- update_status = "✅ Up-To-Date"
70
- else
71
- update_status = "🚫 Update available"
65
+ installed_version = Fastlane::ActionCollector.determine_version(plugin)
66
+ latest_version = FastlaneCore::UpdateChecker.fetch_latest(plugin)
67
+ if Gem::Version.new(installed_version) == Gem::Version.new(latest_version)
68
+ update_status = "✅ Up-To-Date"
69
+ else
70
+ update_status = "🚫 Update available"
71
+ end
72
+ rescue
73
+ update_status = "💥 Check failed"
72
74
  end
73
- rescue
74
- update_status = "💥 Check failed"
75
- end
76
75
  table << "| #{plugin} | #{installed_version} | #{update_status} |\n"
77
76
  end
78
77
 
@@ -107,9 +106,8 @@ module Fastlane
107
106
 
108
107
  next unless fastlane_tools.include?(current_gem.name.to_sym)
109
108
  begin
110
- update_url = FastlaneCore::UpdateChecker.generate_fetch_url(current_gem.name)
111
- latest_version = FastlaneCore::UpdateChecker.fetch_latest(update_url)
112
- if Gem::Version.new(current_gem.version) == Gem::Version.new(latest_version)
109
+ latest_version = FastlaneCore::UpdateChecker.fetch_latest(current_gem.name)
110
+ if Gem::Version.new(current_gem.version) >= Gem::Version.new(latest_version)
113
111
  update_status = "✅ Up-To-Date"
114
112
  else
115
113
  update_status = "🚫 Update available"
@@ -33,6 +33,7 @@ module Fastlane
33
33
  UI.verbose(caller.join("\n"))
34
34
  UI.user_error!("The action '#{action}' is no longer bundled with fastlane. You can install it using `fastlane add_plugin #{action}`")
35
35
  else
36
+ Fastlane::ActionsList.print_suggestions(action)
36
37
  UI.user_error!("Action '#{action}' not available, run `fastlane actions` to get a full list")
37
38
  end
38
39
  end
@@ -1,4 +1,4 @@
1
1
  module Fastlane
2
- VERSION = '2.29.0'.freeze
2
+ VERSION = '2.29.1'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  end
@@ -112,7 +112,11 @@ module FastlaneCore
112
112
  end
113
113
 
114
114
  def self.fetch_latest(gem_name)
115
- JSON.parse(Excon.get("https://rubygems.org/api/v1/gems/#{gem_name}.json").body)["version"]
115
+ JSON.parse(Excon.get(generate_fetch_url(gem_name)).body)["version"]
116
+ end
117
+
118
+ def self.generate_fetch_url(gem_name)
119
+ "https://rubygems.org/api/v1/gems/#{gem_name}.json"
116
120
  end
117
121
 
118
122
  # (optional) Returns the app identifier for the current tool
@@ -16,7 +16,9 @@ module Match
16
16
 
17
17
  unless password
18
18
  if !UI.interactive?
19
- UI.error "No password found neither in environment nor in local keychain. Bailing out as in non interactive mode."
19
+ UI.error "Neither the MATCH_PASSWORD environment variable nor the local keychain contained a password."
20
+ UI.error "Bailing out instead of asking for a password, since this is non-interactive mode."
21
+ UI.error "Try setting the MATCH_PASSWORD environment variable, or temporarily enable interactive mode to store a password."
20
22
  else
21
23
  UI.important "Enter the passphrase that should be used to encrypt/decrypt your certificates"
22
24
  UI.important "This passphrase is specific per repository and will be stored in your local keychain"
@@ -6,19 +6,28 @@ module Pilot
6
6
  class TesterManager < Manager
7
7
  def add_tester(options)
8
8
  start(options)
9
-
10
9
  app = find_app(app_filter: config[:apple_id] || config[:app_identifier])
11
10
  UI.user_error!("You must provide either a Apple ID for the app (with the `:apple_id` option) or app identifier (with the `:app_identifier` option)") unless app
12
11
 
13
- tester = find_or_create_tester(email: config[:email], first_name: config[:first_name], last_name: config[:last_name])
14
-
12
+ tester = find_app_tester(email: config[:email], app: app)
13
+ tester ||= create_tester(
14
+ email: config[:email],
15
+ first_name: config[:first_name],
16
+ last_name: config[:last_name],
17
+ app: app
18
+ )
15
19
  begin
16
20
  groups = Spaceship::TestFlight::Group.add_tester_to_groups!(tester: tester, app: app, groups: config[:groups])
17
21
  if tester.kind_of?(Spaceship::Tunes::Tester::Internal)
18
22
  UI.success("Successfully added tester to app #{app.name}")
19
23
  else
20
- group_names = groups.map(&:name).join(", ")
21
- UI.success("Successfully added tester to app #{app.name} in group(s) #{group_names}")
24
+ # tester was added to the group(s) in the above add_tester_to_groups() call, now we need to let the user know which group(s)
25
+ if config[:groups]
26
+ group_names = groups.map(&:name).join(", ")
27
+ UI.success("Successfully added tester to group(s): #{group_names} in app: #{app.name}")
28
+ else
29
+ UI.success("Successfully added tester to the default tester group in app: #{app.name}")
30
+ end
22
31
  end
23
32
  rescue => ex
24
33
  UI.error("Could not add #{tester.email} to app: #{app.name}")
@@ -91,21 +100,51 @@ module Pilot
91
100
  nil
92
101
  end
93
102
 
94
- def find_or_create_tester(email: nil, first_name: nil, last_name: nil)
95
- tester = Spaceship::Tunes::Tester::Internal.find(config[:email])
96
- tester ||= Spaceship::Tunes::Tester::External.find(config[:email])
103
+ def find_app_tester(email: nil, app: nil)
104
+ current_user = Spaceship::Members.find(Spaceship::Tunes.client.user)
105
+ if current_user.admin?
106
+ tester = Spaceship::Tunes::Tester::Internal.find(email)
107
+ tester ||= Spaceship::Tunes::Tester::External.find(email)
108
+ elsif current_user.app_manager?
109
+ unless app
110
+ UI.user_error!("Account #{current_user.email_address} is only an 'App Manager' and therefore you must also define what app this tester (#{email}) should be added to")
111
+ end
112
+ tester = Spaceship::Tunes::Tester::Internal.find_by_app(app.apple_id, email)
113
+ tester ||= Spaceship::Tunes::Tester::External.find_by_app(app.apple_id, email)
114
+ else
115
+ UI.user_error!("Account #{current_user.email} doesn't have a role that is allowed to administer app testers, current roles: #{current_user.roles}")
116
+ tester = nil
117
+ end
97
118
 
98
119
  if tester
99
- UI.success("Existing tester #{tester.email}")
120
+ UI.success("Found existing tester #{email}")
121
+ end
122
+
123
+ return tester
124
+ end
125
+
126
+ def create_tester(email: nil, first_name: nil, last_name: nil, app: nil)
127
+ current_user = Spaceship::Members.find(Spaceship::Tunes.client.user)
128
+ if current_user.admin?
129
+ tester = Spaceship::Tunes::Tester::External.create!(email: email,
130
+ first_name: first_name,
131
+ last_name: last_name)
132
+ UI.success("Successfully added tester: #{email} to your account")
133
+ elsif current_user.app_manager?
134
+
135
+ Spaceship::TestFlight::Tester.create_app_level_tester(app_id: app.apple_id,
136
+ first_name: first_name,
137
+ last_name: last_name,
138
+ email: email)
139
+ tester = Spaceship::Tunes::Tester::External.find_by_app(app.apple_id, email)
140
+ UI.success("Successfully added tester: #{email} to app: #{app.name}")
100
141
  else
101
- tester = Spaceship::Tunes::Tester::External.create!(email: config[:email],
102
- first_name: config[:first_name],
103
- last_name: config[:last_name])
104
- UI.success("Successfully added tester: #{tester.email} to your account")
142
+ UI.user_error!("Current account doesn't have permission to create a tester")
105
143
  end
144
+
106
145
  return tester
107
146
  rescue => ex
108
- UI.error("Could not create tester #{config[:email]}")
147
+ UI.error("Could not create tester #{email}")
109
148
  raise ex
110
149
  end
111
150
 
@@ -176,7 +176,12 @@ module Snapshot
176
176
  FastlaneCore::ConfigItem.new(key: :test_target_name,
177
177
  env_name: "SNAPSHOT_TEST_TARGET_NAME",
178
178
  description: "The name of the target you want to test (if you desire to override the Target Application from Xcode)",
179
- optional: true)
179
+ optional: true),
180
+ FastlaneCore::ConfigItem.new(key: :namespace_log_files,
181
+ env_name: "SNAPSHOT_NAMESPACE_LOG_FILES",
182
+ description: "Separate the log files per device and per language",
183
+ optional: true,
184
+ is_string: false)
180
185
  ]
181
186
  end
182
187
  end
@@ -171,7 +171,7 @@ module Snapshot
171
171
 
172
172
  open_simulator_for_device(device_type)
173
173
 
174
- command = TestCommandGenerator.generate(device_type: device_type)
174
+ command = TestCommandGenerator.generate(device_type: device_type, language: language, locale: locale)
175
175
 
176
176
  if locale
177
177
  UI.header("#{device_type} - #{language} (#{locale})")
@@ -208,7 +208,7 @@ module Snapshot
208
208
  end
209
209
  end)
210
210
 
211
- raw_output = File.read(TestCommandGenerator.xcodebuild_log_path)
211
+ raw_output = File.read(TestCommandGenerator.xcodebuild_log_path(device_type: device_type, language: language, locale: locale))
212
212
 
213
213
  dir_name = locale || language
214
214
 
@@ -2,7 +2,7 @@ module Snapshot
2
2
  # Responsible for building the fully working xcodebuild command
3
3
  class TestCommandGenerator
4
4
  class << self
5
- def generate(device_type: nil)
5
+ def generate(device_type: nil, language: nil, locale: nil)
6
6
  parts = prefix
7
7
  parts << "xcodebuild"
8
8
  parts += options
@@ -10,7 +10,7 @@ module Snapshot
10
10
  parts += build_settings
11
11
  parts += actions
12
12
  parts += suffix
13
- parts += pipe
13
+ parts += pipe(device_type, language, locale)
14
14
 
15
15
  parts
16
16
  end
@@ -62,8 +62,9 @@ module Snapshot
62
62
  []
63
63
  end
64
64
 
65
- def pipe
66
- ["| tee #{xcodebuild_log_path.shellescape} | xcpretty #{Snapshot.config[:xcpretty_args]}"]
65
+ def pipe(device_type, language, locale)
66
+ log_path = xcodebuild_log_path(device_type: device_type, language: language, locale: locale)
67
+ ["| tee #{log_path.shellescape} | xcpretty #{Snapshot.config[:xcpretty_args]}"]
67
68
  end
68
69
 
69
70
  def find_device(device_name, os_version = Snapshot.config[:ios_version])
@@ -108,8 +109,17 @@ module Snapshot
108
109
  return ["-destination '#{value}'"]
109
110
  end
110
111
 
111
- def xcodebuild_log_path
112
- file_name = "#{Snapshot.project.app_name}-#{Snapshot.config[:scheme]}.log"
112
+ def xcodebuild_log_path(device_type: nil, language: nil, locale: nil)
113
+ name_components = [Snapshot.project.app_name, Snapshot.config[:scheme]]
114
+
115
+ if Snapshot.config[:namespace_log_files]
116
+ name_components << device_type if device_type
117
+ name_components << language if language
118
+ name_components << locale if locale
119
+ end
120
+
121
+ file_name = "#{name_components.join('-')}.log"
122
+
113
123
  containing = File.expand_path(Snapshot.config[:buildlog_path])
114
124
  FileUtils.mkdir_p(containing)
115
125
 
@@ -111,16 +111,15 @@ module Spaceship::TestFlight
111
111
  handle_response(response)
112
112
  end
113
113
 
114
- def post_tester(app_id: nil, tester: nil)
114
+ def create_app_level_tester(app_id: nil, first_name: nil, last_name: nil, email: nil)
115
115
  assert_required_params(__method__, binding)
116
-
117
116
  url = "providers/#{team_id}/apps/#{app_id}/testers"
118
117
  response = request(:post) do |req|
119
118
  req.url url
120
119
  req.body = {
121
- "email" => tester.email,
122
- "firstName" => tester.first_name,
123
- "lastName" => tester.last_name
120
+ "email" => email,
121
+ "firstName" => first_name,
122
+ "lastName" => last_name
124
123
  }.to_json
125
124
  req.headers['Content-Type'] = 'application/json'
126
125
  end
@@ -46,8 +46,12 @@ module Spaceship::TestFlight
46
46
  # is not enough to add the tester to a group. If this isn't done the next request would fail.
47
47
  # This is a bug we reported to the iTunes Connect team, as it also happens on the iTunes Connect UI on 18. April 2017
48
48
  def add_tester!(tester)
49
- # This post request makes the account-level tester available to the app
50
- tester_data = client.post_tester(app_id: self.app_id, tester: tester)
49
+ # This post request creates an account-level tester and then makes it available to the app, or just makes
50
+ # it available to the app if it already exists
51
+ tester_data = client.create_app_level_tester(app_id: self.app_id,
52
+ first_name: tester.first_name,
53
+ last_name: tester.last_name,
54
+ email: tester.email)
51
55
  # This put request adds the tester to the group
52
56
  client.put_tester_to_group(group_id: self.id, tester_id: tester_data['id'], app_id: self.app_id)
53
57
  end
@@ -27,6 +27,13 @@ module Spaceship::TestFlight
27
27
  self.all(app_id: app_id).find { |tester| tester.email == email }
28
28
  end
29
29
 
30
+ def self.create_app_level_tester(app_id: nil, first_name: nil, last_name: nil, email: nil)
31
+ client.create_app_level_tester(app_id: app_id,
32
+ first_name: first_name,
33
+ last_name: last_name,
34
+ email: email)
35
+ end
36
+
30
37
  def remove_from_app!(app_id: nil)
31
38
  client.delete_tester_from_app(app_id: app_id, tester_id: self.tester_id)
32
39
  end
@@ -71,6 +71,48 @@ module Spaceship
71
71
  # @return (Spaceship::Tunes::TransitAppFile) the structure containing information about the geo json. Can be nil
72
72
  attr_accessor :transit_app_file
73
73
 
74
+ ####
75
+ # Trade Representative Contact Information
76
+ ####
77
+ # @return (String) Trade Representative Contact Information Trade Name. This attribute isn't editable
78
+ attr_accessor :trade_representative_trade_name
79
+
80
+ # @return (String) Trade Representative Contact Information First Name
81
+ attr_accessor :trade_representative_first_name
82
+
83
+ # @return (String) Trade Representative Contact Information Last Name
84
+ attr_accessor :trade_representative_last_name
85
+
86
+ # @return (String) Trade Representative Contact Information Address Line 1
87
+ attr_accessor :trade_representative_address_line_1
88
+
89
+ # @return (String) Trade Representative Contact Information Address Line 2
90
+ attr_accessor :trade_representative_address_line_2
91
+
92
+ # @return (String) Trade Representative Contact Information Address Line 3
93
+ attr_accessor :trade_representative_address_line_3
94
+
95
+ # @return (String) Trade Representative Contact Information City Name
96
+ attr_accessor :trade_representative_city_name
97
+
98
+ # @return (String) Trade Representative Contact Information State
99
+ attr_accessor :trade_representative_state
100
+
101
+ # @return (String) Trade Representative Contact Information Country
102
+ attr_accessor :trade_representative_country
103
+
104
+ # @return (String) Trade Representative Contact Information Postal Code
105
+ attr_accessor :trade_representative_postal_code
106
+
107
+ # @return (String) Trade Representative Contact Information Phone Number
108
+ attr_accessor :trade_representative_phone_number
109
+
110
+ # @return (String) Trade Representative Contact Information Email Address
111
+ attr_accessor :trade_representative_email
112
+
113
+ # @return (Boolean) Display Trade Representative Contact Information on the Korean App Store or not
114
+ attr_accessor :trade_representative_is_displayed_on_app_store
115
+
74
116
  ####
75
117
  # App Review Information
76
118
  ####
@@ -150,6 +192,22 @@ module Spaceship
150
192
  # GeoJson
151
193
  # 'transitAppFile.value' => :transit_app_file
152
194
 
195
+ # Trade Representative Contact Information
196
+
197
+ 'appStoreInfo.tradeName.value' => :trade_representative_trade_name,
198
+ 'appStoreInfo.firstName.value' => :trade_representative_first_name,
199
+ 'appStoreInfo.lastName.value' => :trade_representative_last_name,
200
+ 'appStoreInfo.addressLine1.value' => :trade_representative_address_line_1,
201
+ 'appStoreInfo.addressLine2.value' => :trade_representative_address_line_2,
202
+ 'appStoreInfo.addressLine3.value' => :trade_representative_address_line_3,
203
+ 'appStoreInfo.cityName.value' => :trade_representative_city_name,
204
+ 'appStoreInfo.state.value' => :trade_representative_state,
205
+ 'appStoreInfo.country.value' => :trade_representative_country,
206
+ 'appStoreInfo.postalCode.value' => :trade_representative_postal_code,
207
+ 'appStoreInfo.phoneNumber.value' => :trade_representative_phone_number,
208
+ 'appStoreInfo.emailAddress.value' => :trade_representative_email,
209
+ 'appStoreInfo.shouldDisplayInStore.value' => :trade_representative_is_displayed_on_app_store,
210
+
153
211
  # App Review Information
154
212
  'appReviewInfo.firstName.value' => :review_first_name,
155
213
  'appReviewInfo.lastName.value' => :review_last_name,
@@ -16,6 +16,15 @@ module Spaceship
16
16
  'dsId' => :user_id
17
17
  )
18
18
 
19
+ ROLES = {
20
+ admin: 'admin',
21
+ app_manager: 'appmanager',
22
+ sales: 'sales',
23
+ developer: 'developer',
24
+ marketing: 'marketing',
25
+ reports: 'reports'
26
+ }
27
+
19
28
  def roles
20
29
  parsed_roles = []
21
30
  raw_data["roles"].each do |role|
@@ -24,6 +33,14 @@ module Spaceship
24
33
  return parsed_roles
25
34
  end
26
35
 
36
+ def admin?
37
+ roles.include?(ROLES[:admin])
38
+ end
39
+
40
+ def app_manager?
41
+ roles.include?(ROLES[:app_manager])
42
+ end
43
+
27
44
  def preferred_currency
28
45
  currency_base = raw_data["preferredCurrency"]["value"]
29
46
  return {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.29.0
4
+ version: 2.29.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2017-05-09 00:00:00.000000000 Z
18
+ date: 2017-05-11 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: slack-notifier
@@ -1257,6 +1257,7 @@ files:
1257
1257
  - spaceship/lib/assets/languageMapping.json
1258
1258
  - spaceship/lib/assets/languageMappingReadable.json
1259
1259
  - spaceship/lib/spaceship.rb
1260
+ - spaceship/lib/spaceship/.DS_Store
1260
1261
  - spaceship/lib/spaceship/babosa_fix.rb
1261
1262
  - spaceship/lib/spaceship/base.rb
1262
1263
  - spaceship/lib/spaceship/client.rb
@@ -1386,7 +1387,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1386
1387
  version: '0'
1387
1388
  requirements: []
1388
1389
  rubyforge_project:
1389
- rubygems_version: 2.5.1
1390
+ rubygems_version: 2.2.5
1390
1391
  signing_key:
1391
1392
  specification_version: 4
1392
1393
  summary: The easiest way to automate beta deployments and releases for your iOS and