deliver 0.5.0 → 0.6.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.
@@ -0,0 +1,61 @@
1
+ module Deliver
2
+ # Login code
3
+ class ItunesConnect
4
+ # Loggs in a user with the given login data on the iTC Frontend.
5
+ # You don't need to pass a username and password. It will
6
+ # Automatically be fetched using the {CredentialsManager::PasswordManager}.
7
+ # This method will also automatically be called when triggering other
8
+ # actions like {#open_app_page}
9
+ # @param user (String) (optional) The username/email address
10
+ # @param password (String) (optional) The password
11
+ # @return (bool) true if everything worked fine
12
+ # @raise [ItunesConnectGeneralError] General error while executing
13
+ # this action
14
+ # @raise [ItunesConnectLoginError] Login data is wrong
15
+ def login(user = nil, password = nil)
16
+ Helper.log.info "Logging into iTunesConnect"
17
+
18
+ user ||= CredentialsManager::PasswordManager.shared_manager.username
19
+ password ||= CredentialsManager::PasswordManager.shared_manager.password
20
+
21
+ result = visit ITUNESCONNECT_URL
22
+ raise "Could not open iTunesConnect" unless result['status'] == 'success'
23
+
24
+ sleep 3
25
+
26
+ if page.has_content?"My Apps"
27
+ # Already logged in
28
+ return true
29
+ end
30
+
31
+ begin
32
+ wait_for_elements('#accountpassword')
33
+ rescue => ex
34
+ # when the user is already logged in, this will raise an exception
35
+ end
36
+
37
+ fill_in "accountname", with: user
38
+ fill_in "accountpassword", with: password
39
+
40
+ begin
41
+ (wait_for_elements(".enabled").first.click rescue nil) # Login Button
42
+ wait_for_elements('.homepageWrapper.ng-scope')
43
+
44
+ if page.has_content?"My Apps"
45
+ # Everything looks good
46
+ else
47
+ raise ItunesConnectLoginError.new("Looks like your login data was correct, but you do not have access to the apps.")
48
+ end
49
+ rescue => ex
50
+ Helper.log.debug(ex)
51
+ raise ItunesConnectLoginError.new("Error logging in user #{user} with the given password. Make sure you entered them correctly.")
52
+ end
53
+
54
+ Helper.log.info "Successfully logged into iTunesConnect"
55
+
56
+ true
57
+ rescue => ex
58
+ error_occured(ex)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,57 @@
1
+ module Deliver
2
+ class ItunesConnect
3
+ # This method creates a new version of your app using the
4
+ # iTunesConnect frontend. This will happen directly after calling
5
+ # this method.
6
+ # @param app (Deliver::App) the app you want to modify
7
+ # @param version_number (String) the version number as string for
8
+ # the new version that should be created
9
+ def create_new_version!(app, version_number)
10
+ begin
11
+ current_version = get_live_version(app)
12
+
13
+ verify_app(app)
14
+ open_app_page(app)
15
+
16
+ if page.has_content?BUTTON_STRING_NEW_VERSION
17
+
18
+ if current_version == version_number
19
+ # This means, this version is already live on the App Store
20
+ raise "Version #{version_number} is already created, submitted and released on iTC. Please verify you're using a new version number."
21
+ end
22
+
23
+ click_on BUTTON_STRING_NEW_VERSION
24
+
25
+ Helper.log.info "Creating a new version (#{version_number})"
26
+
27
+ all(".fullWidth.nobottom.ng-isolate-scope.ng-pristine").last.set(version_number.to_s)
28
+ click_on "Create"
29
+
30
+ while not page.has_content?"Prepare for Submission"
31
+ sleep 1
32
+ Helper.log.debug("Waiting for 'Prepare for Submission'")
33
+ end
34
+ else
35
+ Helper.log.warn "Can not create version #{version_number} on iTunesConnect. Maybe it was already created."
36
+ Helper.log.info "Check out '#{current_url}' what's the latest version."
37
+
38
+ begin
39
+ created_version = first(".status.waiting").text.split(" ").first
40
+ if created_version != version_number
41
+ raise "Some other version ('#{created_version}') was created instead of the one you defined ('#{version_number}')"
42
+ end
43
+ rescue => ex
44
+ # Can not fetch the version number of the new version (this happens, when it's e.g. 'Developer Rejected')
45
+ unless page.has_content?version_number
46
+ raise "Some other version was created instead of the one you defined ('#{version_number}')."
47
+ end
48
+ end
49
+ end
50
+
51
+ true
52
+ rescue => ex
53
+ error_occured(ex)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,60 @@
1
+ module Deliver
2
+ # For all the information reading (e.g. version number)
3
+ class ItunesConnect
4
+ # This method will fetch the current status ({Deliver::App::AppStatus})
5
+ # of your app and return it. This method uses a headless browser
6
+ # under the hood, so it might take some time until you get the result
7
+ # @param app (Deliver::App) the app you want this information from
8
+ # @raise [ItunesConnectGeneralError] General error while executing
9
+ # this action
10
+ # @raise [ItunesConnectLoginError] Login data is wrong
11
+ def get_app_status(app)
12
+ begin
13
+ verify_app(app)
14
+
15
+ open_app_page(app)
16
+
17
+ if page.has_content?WAITING_FOR_REVIEW
18
+ # That's either Upload Received or Waiting for Review
19
+ if page.has_content?"To submit a new build, you must remove this version from review"
20
+ return App::AppStatus::WAITING_FOR_REVIEW
21
+ else
22
+ return App::AppStatus::UPLOAD_RECEIVED
23
+ end
24
+ elsif page.has_content?BUTTON_STRING_NEW_VERSION
25
+ return App::AppStatus::READY_FOR_SALE
26
+ elsif page.has_content?BUTTON_STRING_SUBMIT_FOR_REVIEW
27
+ return App::AppStatus::PREPARE_FOR_SUBMISSION
28
+ else
29
+ raise "App status not yet implemented"
30
+ end
31
+ rescue Exception => ex
32
+ error_occured(ex)
33
+ end
34
+ end
35
+
36
+ # This method will fetch the version number of the currently live version
37
+ # of your app and return it. This method uses a headless browser
38
+ # under the hood, so it might take some time until you get the result
39
+ # @param app (Deliver::App) the app you want this information from
40
+ # @raise [ItunesConnectGeneralError] General error while executing
41
+ # this action
42
+ # @raise [ItunesConnectLoginError] Login data is wrong
43
+ def get_live_version(app)
44
+ begin
45
+ verify_app(app)
46
+
47
+ open_app_page(app)
48
+
49
+ begin
50
+ return first(".status.ready").text.split(" ").first
51
+ rescue
52
+ Helper.log.debug "Could not fetch version number of the live version for app #{app}."
53
+ return nil
54
+ end
55
+ rescue => ex
56
+ error_occured(ex)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,222 @@
1
+ module Deliver
2
+ # Everything related to submitting the app
3
+ class ItunesConnect
4
+
5
+ # This will put the latest uploaded build as a new beta build
6
+ def put_build_into_beta_testing!(app, version_number)
7
+ begin
8
+ verify_app(app)
9
+ open_app_page(app)
10
+
11
+ Helper.log.info("Choosing the latest build on iTunesConnect for beta distribution")
12
+
13
+ click_on "Prerelease"
14
+
15
+ wait_for_preprocessing
16
+
17
+ if all(".switcher.ng-binding").count == 0
18
+ raise "Could not find beta build on '#{current_url}'. Make sure it is available there"
19
+ end
20
+
21
+ if first(".switcher.ng-binding")['class'].include?"checked"
22
+ Helper.log.warn("Beta Build seems to be already active. Take a look at '#{current_url}'")
23
+ return true
24
+ end
25
+
26
+ first(".switcher.ng-binding").click
27
+ if page.has_content?"Are you sure you want to start testing"
28
+ click_on "Start"
29
+ end
30
+
31
+
32
+ return true
33
+ rescue => ex
34
+ error_occured(ex)
35
+ end
36
+ end
37
+
38
+ # This will choose the latest uploaded build on iTunesConnect as the production one
39
+ # After this method, you still have to call submit_for_review to actually submit the
40
+ # whole update
41
+ # @param app (Deliver::App) the app you want to choose the build for
42
+ # @param version_number (String) the version number as string for
43
+ def put_build_into_production!(app, version_number)
44
+ begin
45
+ verify_app(app)
46
+ open_app_page(app)
47
+
48
+ Helper.log.info("Choosing the latest build on iTunesConnect for release")
49
+
50
+ click_on "Prerelease"
51
+
52
+ wait_for_preprocessing
53
+
54
+ ################# Apple is finished processing the ipa file #################
55
+
56
+ Helper.log.info("Apple finally finished processing the ipa file")
57
+ open_app_page(app)
58
+
59
+ begin
60
+ first('a', :text => BUTTON_ADD_NEW_BUILD).click
61
+ wait_for_elements(".buildModalList")
62
+ sleep 5
63
+ rescue
64
+ if page.has_content?"Upload Date"
65
+ # That's fine, the ipa was already selected
66
+ return true
67
+ else
68
+ raise "Could not find Build Button. It looks like the ipa file was not properly uploaded."
69
+ end
70
+ end
71
+
72
+ if page.all('td', :text => version_number).count > 1
73
+ Helper.log.fatal "There were multiple submitted builds found. Don't know which one to choose. Just choosing the top one for now"
74
+ end
75
+
76
+ result = page.first('td', :text => version_number).first(:xpath,"./..").first(:css, ".small").click
77
+ click_on "Done" # Save the modal dialog
78
+ click_on "Save" # on the top right to save everything else
79
+
80
+ error = page.has_content?BUTTON_ADD_NEW_BUILD
81
+ raise "Could not put build itself onto production. Try opening '#{current_url}'" if error
82
+
83
+ return true
84
+ rescue => ex
85
+ error_occured(ex)
86
+ end
87
+ end
88
+
89
+ # Submits the update itself to Apple, this includes the app metadata and the ipa file
90
+ # This can easily cause exceptions, which will be shown on iTC.
91
+ # @param app (Deliver::App) the app you want to submit
92
+ # @param perms (Hash) information about content rights, ...
93
+ def submit_for_review!(app, perms = nil)
94
+ begin
95
+ verify_app(app)
96
+ open_app_page(app)
97
+
98
+ Helper.log.info("Submitting app for Review")
99
+
100
+ if not page.has_content?BUTTON_STRING_SUBMIT_FOR_REVIEW
101
+ if page.has_content?WAITING_FOR_REVIEW
102
+ Helper.log.info("App is already Waiting For Review")
103
+ return true
104
+ else
105
+ raise "Couldn't find button with name '#{BUTTON_STRING_SUBMIT_FOR_REVIEW}'"
106
+ end
107
+ end
108
+
109
+ click_on BUTTON_STRING_SUBMIT_FOR_REVIEW
110
+ sleep 4
111
+
112
+ errors = (all(".pagemessage.error") || []).count > 0
113
+ raise "Some error occured when submitting the app for review: '#{current_url}'" if errors
114
+
115
+ wait_for_elements(".savingWrapper.ng-scope.ng-pristine")
116
+ wait_for_elements(".radiostyle")
117
+ sleep 3
118
+
119
+ if page.has_content?"Content Rights"
120
+ # Looks good.. just a few more steps
121
+
122
+ perms ||= {
123
+ export_compliance: {
124
+ encryption_updated: false,
125
+ cryptography_enabled: false,
126
+ is_exempt: false
127
+ },
128
+ third_party_content: {
129
+ contains_third_party_content: false,
130
+ has_rights: false
131
+ },
132
+ advertising_identifier: {
133
+ use_idfa: false,
134
+ serve_advertisement: false,
135
+ attribute_advertisement: false,
136
+ attribute_actions: false,
137
+ limit_ad_tracking: false
138
+ }
139
+ }
140
+
141
+ basic = "//*[@itc-radio='submitForReviewAnswers"
142
+ checkbox = "//*[@itc-checkbox='submitForReviewAnswers"
143
+
144
+ #####################
145
+ # Export Compliance #
146
+ #####################
147
+ if page.has_content?"Export"
148
+
149
+ if not perms[:export_compliance][:encryption_updated] and perms[:export_compliance][:cryptography_enabled]
150
+ raise "encryption_updated must be enabled if cryptography_enabled is enabled!"
151
+ end
152
+
153
+ begin
154
+ encryption_updated_control = all(:xpath, "#{basic}.exportCompliance.encryptionUpdated.value' and @radio-value='#{perms[:export_compliance][:encryption_updated]}']//input")
155
+ encryption_updated_control[0].trigger('click') if encryption_updated_control.count > 0
156
+ first(:xpath, "#{basic}.exportCompliance.usesEncryption.value' and @radio-value='#{perms[:export_compliance][:cryptography_enabled]}']//input").trigger('click')
157
+ first(:xpath, "#{basic}.exportCompliance.isExempt.value' and @radio-value='#{perms[:export_compliance][:is_exempt]}']//input").trigger('click')
158
+ rescue
159
+ end
160
+ end
161
+
162
+ ##################
163
+ # Content Rights #
164
+ ##################
165
+ if page.has_content?"Content Rights"
166
+ if not perms[:third_party_content][:contains_third_party_content] and perms[:third_party_content][:has_rights]
167
+ raise "contains_third_party_content must be enabled if has_rights is enabled".red
168
+ end
169
+
170
+ begin
171
+ first(:xpath, "#{basic}.contentRights.containsThirdPartyContent.value' and @radio-value='#{perms[:third_party_content][:contains_third_party_content]}']//input").trigger('click')
172
+ first(:xpath, "#{basic}.contentRights.hasRights.value' and @radio-value='#{perms[:third_party_content][:has_rights]}']//input").trigger('click')
173
+ rescue
174
+ end
175
+ end
176
+
177
+ ##########################
178
+ # Advertising Identifier #
179
+ ##########################
180
+ if page.has_content?"Advertising Identifier"
181
+ first(:xpath, "#{basic}.adIdInfo.usesIdfa.value' and @radio-value='#{perms[:advertising_identifier][:use_idfa]}']//a").click rescue nil
182
+
183
+ if perms[:advertising_identifier][:use_idfa]
184
+ if perms[:advertising_identifier][:serve_advertisement]
185
+ first(:xpath, "#{checkbox}.adIdInfo.servesAds.value']//a").click
186
+ end
187
+ if perms[:advertising_identifier][:attribute_advertisement]
188
+ first(:xpath, "#{checkbox}.adIdInfo.tracksInstall.value']//a").click
189
+ end
190
+ if perms[:advertising_identifier][:attribute_actions]
191
+ first(:xpath, "#{checkbox}.adIdInfo.tracksAction.value']//a").click
192
+ end
193
+ if perms[:advertising_identifier][:limit_ad_tracking]
194
+ first(:xpath, "#{checkbox}.adIdInfo.limitsTracking.value']//a").click
195
+ end
196
+ end
197
+ end
198
+
199
+
200
+ Helper.log.info("Filled out the export compliance and other information on iTC".green)
201
+
202
+ click_on "Submit"
203
+ sleep 5
204
+
205
+ if page.has_content?WAITING_FOR_REVIEW
206
+ # Everything worked :)
207
+ Helper.log.info("Successfully submitted App for Review".green)
208
+ return true
209
+ else
210
+ raise "So close, it looks like there went something wrong with the actual deployment. Checkout '#{current_url}'".red
211
+ end
212
+ else
213
+ raise "Something is missing here.".red
214
+ end
215
+ return false
216
+ rescue => ex
217
+ error_occured(ex)
218
+ end
219
+ end
220
+
221
+ end
222
+ end
@@ -1,3 +1,3 @@
1
1
  module Deliver
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deliver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-15 00:00:00.000000000 Z
11
+ date: 2015-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -295,10 +295,9 @@ files:
295
295
  - lib/deliver.rb
296
296
  - lib/deliver/app.rb
297
297
  - lib/deliver/app_metadata.rb
298
+ - lib/deliver/app_metadata_screenshots.rb
298
299
  - lib/deliver/app_screenshot.rb
299
300
  - lib/deliver/commands.rb
300
- - lib/deliver/commands/init.rb
301
- - lib/deliver/commands/run.rb
302
301
  - lib/deliver/deliver_process.rb
303
302
  - lib/deliver/deliverer.rb
304
303
  - lib/deliver/deliverfile/deliverfile.rb
@@ -307,7 +306,15 @@ files:
307
306
  - lib/deliver/dependency_checker.rb
308
307
  - lib/deliver/helper.rb
309
308
  - lib/deliver/ipa_uploader.rb
310
- - lib/deliver/itunes_connect.rb
309
+ - lib/deliver/itunes_connect/itunes_connect.rb
310
+ - lib/deliver/itunes_connect/itunes_connect_additional.rb
311
+ - lib/deliver/itunes_connect/itunes_connect_app_icon.rb
312
+ - lib/deliver/itunes_connect/itunes_connect_app_rating.rb
313
+ - lib/deliver/itunes_connect/itunes_connect_helper.rb
314
+ - lib/deliver/itunes_connect/itunes_connect_login.rb
315
+ - lib/deliver/itunes_connect/itunes_connect_new_version.rb
316
+ - lib/deliver/itunes_connect/itunes_connect_reader.rb
317
+ - lib/deliver/itunes_connect/itunes_connect_submission.rb
311
318
  - lib/deliver/itunes_search_api.rb
312
319
  - lib/deliver/itunes_transporter.rb
313
320
  - lib/deliver/languages.rb