spaceship 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9452203d446ab2eb76810e8ee4a50d7b838ad91
4
- data.tar.gz: f90ffe947881c20f13fc1186dede47bbeb26d2f2
3
+ metadata.gz: 8a0aa9495ff354e1c5b95d9e37c3d4bbe3fdd78a
4
+ data.tar.gz: 4cb03238dd2e3c63d807b8b15e989b818845f6b0
5
5
  SHA512:
6
- metadata.gz: 27ee1ad437139635ca1b28356482cd7127c9f4ef314c2822c5554518d1cc18dfba3ccf171eaaf9085609b13d6038a300b104628b13d53d2a857588132d9e4c63
7
- data.tar.gz: 849de99bac3737816bf33ca79854786bfc5a21d7e57793f6f0f5d4ea69d2a52c520cca5dbd4f7901b53757e388f9700becbf758f2d12646401665216364f7cd9
6
+ metadata.gz: 178f2df3b4200629861bccb40f34ad30c6abb5510caa70eb7d55b4a5a670b2b60fa3d7edc1d1a104b884f30fc735e7ec22c09d564887be0c5d77a033ad5ed0e4
7
+ data.tar.gz: e3a7a94c04cdb8c41a1545b6e477306befe94d8007c1f567a9a9391ad9422af66f649b87719afa46244ee8a3adfe4e739ead4b8c20f99f8c4307609404083b0d
@@ -28,19 +28,47 @@ module Spaceship
28
28
  # /tmp/spaceship[time]_[pid].log by default
29
29
  attr_accessor :logger
30
30
 
31
+ # Base class for errors that want to present their message as
32
+ # preferred error info for fastlane error handling. See:
33
+ # fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb
34
+ class BasicPreferredInfoError < StandardError
35
+ TITLE = 'The request could not be completed because:'.freeze
36
+
37
+ def preferred_error_info
38
+ message ? [TITLE, message] : nil
39
+ end
40
+ end
41
+
31
42
  # Invalid user credentials were provided
32
- class InvalidUserCredentialsError < StandardError; end
43
+ class InvalidUserCredentialsError < BasicPreferredInfoError; end
33
44
 
34
45
  # Raised when no user credentials were passed at all
35
- class NoUserCredentialsError < StandardError; end
46
+ class NoUserCredentialsError < BasicPreferredInfoError; end
36
47
 
37
- class UnexpectedResponse < StandardError; end
48
+ class UnexpectedResponse < StandardError
49
+ attr_reader :error_info
50
+
51
+ def initialize(error_info = nil)
52
+ super(error_info)
53
+ @error_info = error_info
54
+ end
55
+
56
+ def preferred_error_info
57
+ return nil unless @error_info.kind_of?(Hash) && @error_info['resultString']
58
+
59
+ [
60
+ "Apple provided the following error info:",
61
+ @error_info['resultString'],
62
+ @error_info['userString']
63
+ ].compact.uniq # sometimes 'resultString' and 'userString' are the same value
64
+ end
65
+ end
38
66
 
39
67
  # Raised when 302 is received from portal request
40
- class AppleTimeoutError < StandardError; end
68
+ class AppleTimeoutError < BasicPreferredInfoError; end
41
69
 
42
70
  # Raised when 401 is received from portal request
43
- class UnauthorizedAccessError < StandardError; end
71
+ class UnauthorizedAccessError < BasicPreferredInfoError; end
44
72
 
45
73
  # Authenticates with Apple's web services. This method has to be called once
46
74
  # to generate a valid session. The session will automatically be used from then
@@ -238,7 +266,7 @@ module Spaceship
238
266
 
239
267
  def request(method, url_or_path = nil, params = nil, headers = {}, &block)
240
268
  headers.merge!(csrf_tokens)
241
- headers.merge!({ 'User-Agent' => USER_AGENT })
269
+ headers['User-Agent'] = USER_AGENT
242
270
 
243
271
  # Before encoding the parameters, log them
244
272
  log_request(method, url_or_path, params)
@@ -297,7 +325,7 @@ module Spaceship
297
325
  end
298
326
 
299
327
  if content.nil?
300
- raise UnexpectedResponse.new, response.body
328
+ raise UnexpectedResponse.new(response.body)
301
329
  else
302
330
  store_csrf_tokens(response)
303
331
  content
@@ -62,7 +62,7 @@ module Spaceship
62
62
  req.headers['X-Apple-Upload-ContentProviderId'] = content_provider_id
63
63
  req.headers['X-Original-Filename'] = upload_file.file_name
64
64
  req.headers['X-Apple-Upload-Validation-RuleSets'] = du_validation_rule_set if du_validation_rule_set
65
- req.headers['Content-Length'] = "#{upload_file.file_size}"
65
+ req.headers['Content-Length'] = upload_file.file_size.to_s
66
66
  req.headers['Connection'] = "keep-alive"
67
67
  end
68
68
 
@@ -12,7 +12,7 @@ module Spaceship
12
12
  class << self
13
13
  def from_path(path)
14
14
  raise "Image must exists at path: #{path}" unless File.exist?(path)
15
- path = remove_alpha_channel(path) if File.extname(path).downcase == '.png'
15
+ path = remove_alpha_channel(path) if File.extname(path).casecmp('.png').zero?
16
16
 
17
17
  content_type = Utilities.content_type(path)
18
18
  self.new(
@@ -193,8 +193,8 @@ module Spaceship
193
193
  csr = OpenSSL::X509::Request.new
194
194
  csr.version = 0
195
195
  csr.subject = OpenSSL::X509::Name.new([
196
- ['CN', 'PEM', OpenSSL::ASN1::UTF8STRING]
197
- ])
196
+ ['CN', 'PEM', OpenSSL::ASN1::UTF8STRING]
197
+ ])
198
198
  csr.public_key = key.public_key
199
199
  csr.sign(key, OpenSSL::Digest::SHA1.new)
200
200
  return [csr, key]
@@ -98,14 +98,14 @@ module Spaceship
98
98
  def factory(attrs)
99
99
  # fill content rights section if iTC returns nil
100
100
  if attrs["contentRights"].nil?
101
- attrs.merge!("contentRights" => {
101
+ attrs["contentRights"] = {
102
102
  "containsThirdPartyContent" => {
103
103
  "value" => nil
104
104
  },
105
105
  "hasRights" => {
106
106
  "value" => nil
107
107
  }
108
- })
108
+ }
109
109
  end
110
110
 
111
111
  obj = self.new(attrs)
@@ -115,8 +115,8 @@ module Spaceship
115
115
  # @param application (Spaceship::Tunes::Application) The app this submission is for
116
116
  def create(application, version)
117
117
  attrs = client.prepare_app_submissions(application.apple_id, application.edit_version.version_id)
118
- attrs.merge!(application: application)
119
- attrs.merge!(version: version)
118
+ attrs[:application] = application
119
+ attrs[:version] = version
120
120
 
121
121
  return self.factory(attrs)
122
122
  end
@@ -40,8 +40,7 @@ module Spaceship
40
40
  end
41
41
 
42
42
  def reset!(attrs = {})
43
- update_raw_data!
44
- ({
43
+ update_raw_data!({
45
44
  video_asset_token: nil,
46
45
  picture_asset_token: nil,
47
46
  descriptionXML: nil,
@@ -54,8 +53,7 @@ module Spaceship
54
53
  video_status: nil,
55
54
  device_type: nil,
56
55
  language: nil
57
- }.merge(attrs)
58
- )
56
+ }.merge(attrs))
59
57
  end
60
58
 
61
59
  private
@@ -168,8 +168,8 @@ module Spaceship
168
168
  attrs = client.app_version(app_id, is_live)
169
169
  return nil unless attrs
170
170
 
171
- attrs.merge!(application: application)
172
- attrs.merge!(is_live: is_live)
171
+ attrs[:application] = application
172
+ attrs[:is_live] = is_live
173
173
 
174
174
  return self.factory(attrs)
175
175
  end
@@ -429,7 +429,7 @@ module Spaceship
429
429
 
430
430
  trailer.merge!({
431
431
  "pictureAssetToken" => video_preview_data["token"],
432
- "previewFrameTimeCode" => "#{ts}",
432
+ "previewFrameTimeCode" => ts.to_s,
433
433
  "isPortrait" => Utilities.portrait?(video_preview_path)
434
434
  })
435
435
  else # removing trailer
@@ -130,7 +130,7 @@ module Spaceship
130
130
 
131
131
  def details
132
132
  attrs = client.app_details(apple_id)
133
- attrs.merge!(application: self)
133
+ attrs[:application] = self
134
134
  Tunes::AppDetails.factory(attrs)
135
135
  end
136
136
 
@@ -138,7 +138,7 @@ module Spaceship
138
138
  ensure_not_a_bundle
139
139
  versions = client.versions_history(apple_id, platform)
140
140
  versions.map do |attrs|
141
- attrs.merge!(application: self)
141
+ attrs[:application] = self
142
142
  Tunes::AppVersionHistory.factory(attrs)
143
143
  end
144
144
  end
@@ -193,12 +193,31 @@ module Spaceship
193
193
  # @!group Builds
194
194
  #####################################################
195
195
 
196
- # A reference to all the build trains
196
+ # TestFlight: A reference to all the build trains
197
197
  # @return [Hash] a hash, the version number being the key
198
198
  def build_trains
199
199
  Tunes::BuildTrain.all(self, self.apple_id)
200
200
  end
201
201
 
202
+ # The numbers of all build trains that were uploaded
203
+ # @return [Array] An array of train version numbers
204
+ def all_build_train_numbers
205
+ client.all_build_trains(app_id: self.apple_id).fetch("trains").collect do |current|
206
+ current["versionString"]
207
+ end
208
+ end
209
+
210
+ # Receive the build details for a specific build
211
+ # useful if the app is not listed in the TestFlight build list
212
+ # which might happen if you don't use TestFlight
213
+ # This is used to receive dSYM files from Apple
214
+ def all_builds_for_train(train: nil)
215
+ client.all_builds_for_train(app_id: self.apple_id, train: train).fetch("items", []).collect do |attrs|
216
+ attrs[:apple_id] = self.apple_id
217
+ Tunes::Build.factory(attrs)
218
+ end
219
+ end
220
+
202
221
  # @return [Array]A list of binaries which are not even yet processing based on the version
203
222
  # These are all build that have no information except the upload date
204
223
  # Those builds can also be the builds that are stuck on iTC.
@@ -206,7 +225,7 @@ module Spaceship
206
225
  data = client.build_trains(apple_id, 'internal') # we need to fetch all trains here to get the builds
207
226
 
208
227
  builds = data.fetch('processingBuilds', []).collect do |attrs|
209
- attrs.merge!(build_train: self)
228
+ attrs[:build_train] = self
210
229
  Tunes::ProcessingBuild.factory(attrs)
211
230
  end
212
231
 
@@ -220,7 +239,7 @@ module Spaceship
220
239
  data = client.build_trains(apple_id, 'internal') # we need to fetch all trains here to get the builds
221
240
 
222
241
  builds = data.fetch('processingBuilds', []).collect do |attrs|
223
- attrs.merge!(build_train: self)
242
+ attrs[:build_train] = self
224
243
  Tunes::ProcessingBuild.factory(attrs)
225
244
  end
226
245
 
@@ -6,6 +6,11 @@ module Spaceship
6
6
  # @!group General metadata
7
7
  #####################################################
8
8
 
9
+ # @return (String) The App identifier of this app, provided by iTunes Connect
10
+ # @example
11
+ # "1013943394"
12
+ attr_accessor :apple_id
13
+
9
14
  # @return (Spaceship::Tunes::BuildTrain) A reference to the build train this build is contained in
10
15
  attr_accessor :build_train
11
16
 
@@ -112,12 +117,25 @@ module Spaceship
112
117
  self.internal_expiry_date ||= 0
113
118
  end
114
119
 
120
+ def details
121
+ response = client.build_details(app_id: self.apple_id,
122
+ train: self.train_version,
123
+ build_number: self.build_version)
124
+ response['apple_id'] = self.apple_id
125
+ BuildDetails.factory(response)
126
+ end
127
+
128
+ def apple_id
129
+ return @apple_id if @apple_id
130
+ return self.build_train.application.apple_id
131
+ end
132
+
115
133
  def update_build_information!(whats_new: nil,
116
134
  description: nil,
117
135
  feedback_email: nil)
118
136
  parameters = {
119
- app_id: self.build_train.application.apple_id,
120
- train: self.build_train.version_string,
137
+ app_id: self.apple_id,
138
+ train: self.train_version,
121
139
  build_number: self.build_version,
122
140
  platform: self.platform
123
141
  }.merge({
@@ -150,8 +168,8 @@ module Spaceship
150
168
  # }
151
169
  def submit_for_beta_review!(metadata)
152
170
  parameters = {
153
- app_id: self.build_train.application.apple_id,
154
- train: self.build_train.version_string,
171
+ app_id: self.apple_id,
172
+ train: self.train_version,
155
173
  build_number: self.build_version,
156
174
  platform: self.platform,
157
175
 
@@ -199,8 +217,8 @@ module Spaceship
199
217
 
200
218
  # This will cancel the review process for this TestFlight build
201
219
  def cancel_beta_review!
202
- client.remove_testflight_build_from_review!(app_id: self.build_train.application.apple_id,
203
- train: self.build_train.version_string,
220
+ client.remove_testflight_build_from_review!(app_id: self.apple_id,
221
+ train: self.train_version,
204
222
  build_number: self.build_version,
205
223
  platform: self.platform)
206
224
  end
@@ -0,0 +1,48 @@
1
+ module Spaceship
2
+ module Tunes
3
+ # Represents the details of a build
4
+ class BuildDetails < TunesBase
5
+ # @return (String) The App identifier of this app, provided by iTunes Connect
6
+ # @example
7
+ # "1013943394"
8
+ attr_accessor :apple_id
9
+
10
+ # @return (String) Link to the dSYM file (not always available)
11
+ # lol, it's unencrypted http
12
+ attr_accessor :dsym_url
13
+
14
+ # @return [Bool]
15
+ attr_accessor :include_symbols
16
+
17
+ # @return [Integer]
18
+ attr_accessor :number_of_asset_packs
19
+
20
+ # @return [Bool]
21
+ attr_accessor :contains_odr
22
+
23
+ # e.g. "13A340"
24
+ attr_accessor :build_sdk
25
+
26
+ # @return [String] e.g. "MyApp.ipa"
27
+ attr_accessor :file_name
28
+
29
+ attr_mapping(
30
+ 'apple_id' => :apple_id,
31
+ 'dsymurl' => :dsym_url,
32
+ 'includesSymbols' => :include_symbols,
33
+ 'numberOfAssetPacks' => :number_of_asset_packs,
34
+ 'containsODR' => :contains_odr,
35
+ 'buildSdk' => :build_sdk,
36
+ 'fileName' => :file_name
37
+ )
38
+
39
+ class << self
40
+ # Create a new object based on a hash.
41
+ # This is used to create a new object based on the server response.
42
+ def factory(attrs)
43
+ self.new(attrs)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -49,7 +49,7 @@ module Spaceship
49
49
 
50
50
  result = {}
51
51
  trains.each do |attrs|
52
- attrs.merge!(application: application)
52
+ attrs[:application] = application
53
53
  current = self.factory(attrs)
54
54
  result[current.version_string] = current
55
55
  end
@@ -62,12 +62,12 @@ module Spaceship
62
62
  super
63
63
 
64
64
  @builds = (self.raw_data['builds'] || []).collect do |attrs|
65
- attrs.merge!(build_train: self)
65
+ attrs[:build_train] = self
66
66
  Tunes::Build.factory(attrs)
67
67
  end
68
68
 
69
69
  @processing_builds = (self.raw_data['buildsInProcessing'] || []).collect do |attrs|
70
- attrs.merge!(build_train: self)
70
+ attrs[:build_train] = self
71
71
  Tunes::Build.factory(attrs)
72
72
  end
73
73
 
@@ -26,7 +26,7 @@ module Spaceship
26
26
  end
27
27
  return result if result
28
28
 
29
- raise "Language '#{lang}' is not activated for this app version."
29
+ raise "Language '#{lang}' is not activated / available for this app version."
30
30
  end
31
31
 
32
32
  # @return (Array) An array containing all languages that are already available
@@ -15,6 +15,7 @@ require 'spaceship/tunes/user_detail'
15
15
  require 'spaceship/tunes/app_screenshot'
16
16
  require 'spaceship/tunes/language_converter'
17
17
  require 'spaceship/tunes/build'
18
+ require 'spaceship/tunes/build_details'
18
19
  require 'spaceship/tunes/processing_build'
19
20
  require 'spaceship/tunes/build_train'
20
21
  require 'spaceship/tunes/device_type'
@@ -2,7 +2,7 @@ module Spaceship
2
2
  # rubocop:disable Metrics/ClassLength
3
3
  class TunesClient < Spaceship::Client
4
4
  # ITunesConnectError is only thrown when iTunes Connect raises an exception
5
- class ITunesConnectError < StandardError
5
+ class ITunesConnectError < BasicPreferredInfoError
6
6
  end
7
7
 
8
8
  # raised if the server failed to save temporarily
@@ -80,7 +80,7 @@ module Spaceship
80
80
 
81
81
  if t_name.length > 0
82
82
  teams.each do |t|
83
- t_id = t['contentProvider']['contentProviderId'].to_s if t['contentProvider']['name'].downcase == t_name.downcase
83
+ t_id = t['contentProvider']['contentProviderId'].to_s if t['contentProvider']['name'].casecmp(t_name.downcase).zero?
84
84
  end
85
85
  end
86
86
 
@@ -574,6 +574,22 @@ module Spaceship
574
574
  handle_itc_response(r.body)
575
575
  end
576
576
 
577
+ # All build trains, even if there is no TestFlight
578
+ def all_build_trains(app_id: nil)
579
+ r = request(:get, "ra/apps/#{app_id}/buildHistory?platform=ios")
580
+ handle_itc_response(r.body)
581
+ end
582
+
583
+ def all_builds_for_train(app_id: nil, train: nil)
584
+ r = request(:get, "ra/apps/#{app_id}/trains/#{train}/buildHistory?platform=ios")
585
+ handle_itc_response(r.body)
586
+ end
587
+
588
+ def build_details(app_id: nil, train: nil, build_number: nil)
589
+ r = request(:get, "ra/apps/#{app_id}/platforms/ios/trains/#{train}/builds/#{build_number}/details")
590
+ handle_itc_response(r.body)
591
+ end
592
+
577
593
  def update_build_information!(app_id: nil,
578
594
  train: nil,
579
595
  build_number: nil,
@@ -1,3 +1,3 @@
1
1
  module Spaceship
2
- VERSION = "0.23.0"
2
+ VERSION = "0.24.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spaceship
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-03-09 00:00:00.000000000 Z
12
+ date: 2016-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: credentials_manager
@@ -241,14 +241,14 @@ dependencies:
241
241
  requirements:
242
242
  - - "~>"
243
243
  - !ruby/object:Gem::Version
244
- version: 0.32.1
244
+ version: 0.38.0
245
245
  type: :development
246
246
  prerelease: false
247
247
  version_requirements: !ruby/object:Gem::Requirement
248
248
  requirements:
249
249
  - - "~>"
250
250
  - !ruby/object:Gem::Version
251
- version: 0.32.1
251
+ version: 0.38.0
252
252
  description: Because you would rather spend your time building stuff than fighting
253
253
  provisioning
254
254
  email:
@@ -297,6 +297,7 @@ files:
297
297
  - lib/spaceship/tunes/app_version_states_history.rb
298
298
  - lib/spaceship/tunes/application.rb
299
299
  - lib/spaceship/tunes/build.rb
300
+ - lib/spaceship/tunes/build_details.rb
300
301
  - lib/spaceship/tunes/build_train.rb
301
302
  - lib/spaceship/tunes/device_type.rb
302
303
  - lib/spaceship/tunes/language_converter.rb
@@ -332,7 +333,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
332
333
  version: '0'
333
334
  requirements: []
334
335
  rubyforge_project:
335
- rubygems_version: 2.5.1
336
+ rubygems_version: 2.4.5.1
336
337
  signing_key:
337
338
  specification_version: 4
338
339
  summary: Because you would rather spend your time building stuff than fighting provisioning