deliver 0.13.5 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -208
  3. data/bin/deliver +1 -1
  4. data/lib/assets/DeliverfileDefault +2 -22
  5. data/lib/assets/summary.html.erb +27 -39
  6. data/lib/deliver.rb +16 -14
  7. data/lib/deliver/app_screenshot.rb +43 -33
  8. data/lib/deliver/commands_generator.rb +30 -108
  9. data/lib/deliver/detect_values.rb +23 -0
  10. data/lib/deliver/download_screenshots.rb +30 -9
  11. data/lib/deliver/html_generator.rb +7 -8
  12. data/lib/deliver/options.rb +126 -0
  13. data/lib/deliver/runner.rb +75 -0
  14. data/lib/deliver/setup.rb +84 -0
  15. data/lib/deliver/submit_for_review.rb +60 -0
  16. data/lib/deliver/upload_assets.rb +22 -0
  17. data/lib/deliver/upload_metadata.rb +100 -0
  18. data/lib/deliver/upload_price_tier.rb +21 -0
  19. data/lib/deliver/upload_screenshots.rb +63 -0
  20. data/lib/deliver/version.rb +2 -1
  21. metadata +37 -62
  22. data/lib/assets/DeliverLanguageMapping.json +0 -187
  23. data/lib/assets/DeliverfileExample +0 -38
  24. data/lib/deliver/app.rb +0 -167
  25. data/lib/deliver/app_metadata.rb +0 -419
  26. data/lib/deliver/app_metadata_screenshots.rb +0 -189
  27. data/lib/deliver/deliver_process.rb +0 -426
  28. data/lib/deliver/deliverer.rb +0 -138
  29. data/lib/deliver/deliverfile/deliverfile.rb +0 -35
  30. data/lib/deliver/deliverfile/deliverfile_creator.rb +0 -135
  31. data/lib/deliver/deliverfile/dsl.rb +0 -142
  32. data/lib/deliver/dependency_checker.rb +0 -19
  33. data/lib/deliver/ipa_file_analyser.rb +0 -44
  34. data/lib/deliver/ipa_uploader.rb +0 -148
  35. data/lib/deliver/itunes_connect/itunes_connect.rb +0 -12
  36. data/lib/deliver/itunes_connect/itunes_connect_additional.rb +0 -105
  37. data/lib/deliver/itunes_connect/itunes_connect_app_icon.rb +0 -41
  38. data/lib/deliver/itunes_connect/itunes_connect_app_rating.rb +0 -90
  39. data/lib/deliver/itunes_connect/itunes_connect_apple_watch_app_icon.rb +0 -42
  40. data/lib/deliver/itunes_connect/itunes_connect_information.rb +0 -34
  41. data/lib/deliver/itunes_connect/itunes_connect_new_version.rb +0 -67
  42. data/lib/deliver/itunes_connect/itunes_connect_reader.rb +0 -46
  43. data/lib/deliver/itunes_connect/itunes_connect_screenshot_fetcher.rb +0 -54
  44. data/lib/deliver/itunes_connect/itunes_connect_submission.rb +0 -282
  45. data/lib/deliver/itunes_transporter.rb +0 -221
  46. data/lib/deliver/metadata_item.rb +0 -94
  47. data/lib/deliver/testflight.rb +0 -27
@@ -1,42 +0,0 @@
1
- require 'fastimage'
2
-
3
- module Deliver
4
- class ItunesConnect < FastlaneCore::ItunesConnect
5
- # Uploading a new full size app icon
6
-
7
- def upload_apple_watch_app_icon!(app, path)
8
- path = File.expand_path(path)
9
- raise "Could not find watch app icon at path '#{path}'".red unless File.exists?path
10
-
11
- size = FastImage.size(path)
12
- raise "Watch App icon must have the resolution of 1024x1024px".red unless (size[0] == 1024 and size[1] == 1024)
13
-
14
- # Remove alpha channel
15
- Helper.log.info "Removing alpha channel from provided Watch App Icon (iTunes Connect requirement)".green
16
-
17
- `sips -s format bmp '#{path}' &> /dev/null ` # &> /dev/null since there is warning because of the extension
18
- `sips -s format png '#{path}'`
19
-
20
- begin
21
- verify_app(app)
22
- open_app_page(app)
23
-
24
- Helper.log.info "Starting upload of new watch app icon".green
25
-
26
- evaluate_script("$('.ico.icon-chevron-animate-open-close.close').click()") # delete button
27
- evaluate_script("$('.appversionicon.watchIcon > .ios7-style-icon').prev().click()") # delete button
28
- evaluate_script("$('[style-class=\"appversionicon watchIcon rounded\"] [itc-launch-filechooser] + input').attr('id', 'deliverFileUploadInputWatch')") # set div
29
- evaluate_script("URL = webkitURL; URL.createObjectURL = function(){return 'blob:abc'}"); # shim URL
30
- page.attach_file("deliverFileUploadInputWatch", path) # add file
31
-
32
- sleep 10
33
-
34
- click_on "Save"
35
-
36
- Helper.log.info "Finished uploading the new watch app icon".green
37
- rescue => ex
38
- error_occured(ex)
39
- end
40
- end
41
- end
42
- end
@@ -1,34 +0,0 @@
1
- require 'open-uri'
2
-
3
- module Deliver
4
- # For all the information reading (e.g. version number)
5
- class ItunesConnect < FastlaneCore::ItunesConnect
6
- ALL_INFORMATION_URL = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/version/"
7
-
8
- # This method will download information for a given app
9
- # @param app (Deliver::App) the app you want this information from
10
- # @raise [ItunesConnectGeneralError] General error while executing
11
- # this action
12
- # @raise [ItunesConnectLoginError] Login data is wrong
13
- def get_app_information(app)
14
- begin
15
- verify_app(app)
16
-
17
- url = ALL_INFORMATION_URL + app.apple_id.to_s
18
-
19
- # Turn off/on the async mode of jQuery
20
- evaluate_script("jQuery.ajaxSetup({async:false});")
21
- response = evaluate_script("$.get('#{url}').responseText")
22
- evaluate_script("jQuery.ajaxSetup({async:true});")
23
-
24
- raise "Could not fetch data for app" unless response
25
-
26
- data = JSON.parse(response)
27
-
28
- return data['data']
29
- rescue Exception => ex
30
- error_occured(ex)
31
- end
32
- end
33
- end
34
- end
@@ -1,67 +0,0 @@
1
- module Deliver
2
- class ItunesConnect < FastlaneCore::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
-
37
- begin
38
- created_version = wait_for_elements("input[ng-model='versionInfo.version.value']").first.value
39
- if created_version != version_number
40
- update_existing_version_number!(app, version_number)
41
- end
42
- rescue => ex
43
- # Can not fetch the version number of the new version (this happens, when it's e.g. 'Developer Rejected')
44
- Helper.log.error ex
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
-
57
- def update_existing_version_number!(app, version_number)
58
- Helper.log.warn "There is already a new version created, which does not match the current version: '#{version_number}'"
59
-
60
- version_input = wait_for_elements("input[ng-model='versionInfo.version.value']").first
61
- version_input.set version_number
62
- click_on "Save"
63
-
64
- Helper.log.warn "Changed the version number of the latest version to '#{version_number}'".green
65
- end
66
- end
67
- end
@@ -1,46 +0,0 @@
1
- module Deliver
2
- # For all the information reading (e.g. version number)
3
- class ItunesConnect < FastlaneCore::ItunesConnect
4
- # This method will fetch the current status ({Deliver::App::AppStatus})
5
- # of your app and return it.
6
- # @param app (Deliver::App) the app you want this information from
7
- # @raise [ItunesConnectGeneralError] General error while executing
8
- # this action
9
- # @raise [ItunesConnectLoginError] Login data is wrong
10
- def get_app_status(app)
11
- begin
12
- verify_app(app)
13
-
14
- status = (get_app_information(app)['status'] rescue nil)
15
-
16
- return Deliver::App::AppStatus::PREPARE_FOR_SUBMISSION if status == 'prepareForUpload'
17
- return Deliver::App::AppStatus::PREPARE_FOR_SUBMISSION if status == 'devRejected' # that's the same thing
18
- return Deliver::App::AppStatus::WAITING_FOR_REVIEW if status == 'waitingForReview'
19
- return Deliver::App::AppStatus::READY_FOR_SALE if status == 'readyForSale'
20
- return Deliver::App::AppStatus::PENDING_DEVELOPER_RELEASE if status == 'pendingDeveloperRelease'
21
-
22
- Helper.log.info "App Status '#{status}' not yet implemented, please submit an issue on GitHub"
23
- return nil
24
- rescue Exception => ex
25
- error_occured(ex)
26
- end
27
- end
28
-
29
- # This method will fetch the version number of the currently live version
30
- # of your app and return it. This method uses a headless browser
31
- # under the hood, so it might take some time until you get the result
32
- # @param app (Deliver::App) the app you want this information from
33
- # @raise [ItunesConnectGeneralError] General error while executing
34
- # this action
35
- # @raise [ItunesConnectLoginError] Login data is wrong
36
- def get_live_version(app)
37
- begin
38
- verify_app(app)
39
-
40
- return (get_app_information(app)['version']['value'] rescue nil)
41
- rescue => ex
42
- error_occured(ex)
43
- end
44
- end
45
- end
46
- end
@@ -1,54 +0,0 @@
1
- require 'open-uri'
2
-
3
- module Deliver
4
- # For all the information reading (e.g. version number)
5
- class ItunesConnect < FastlaneCore::ItunesConnect
6
- # This method will download all existing app screenshots
7
- # @param app (Deliver::App) the app you want this information from
8
- # @param folder_path (String) the path to store the screenshots in
9
- # @raise [ItunesConnectGeneralError] General error while executing
10
- # this action
11
- # @raise [ItunesConnectLoginError] Login data is wrong
12
- def download_existing_screenshots(app, folder_path)
13
- languages = JSON.parse(File.read(File.join(Helper.gem_path('deliver'), "lib", "assets", "DeliverLanguageMapping.json")))
14
-
15
- begin
16
- verify_app(app)
17
-
18
- url = ALL_INFORMATION_URL + app.apple_id.to_s
19
-
20
- # Turn off/on the async mode of jQuery
21
- evaluate_script("jQuery.ajaxSetup({async:false});")
22
- response = evaluate_script("$.get('#{url}').responseText")
23
- evaluate_script("jQuery.ajaxSetup({async:true});")
24
-
25
- raise "Could not fetch previously uploaded screenshots" unless response
26
-
27
- data = JSON.parse(response)
28
- screenshots = data['data']['details']['value'].each do |language_values|
29
- language_code = languages.find { |a| a['name'] == language_values['language'] }
30
- unless language_code
31
- Helper.log.error "Could not find language information for language #{language_values['language']}".red
32
- next
33
- end
34
- language_code = language_code['locale']
35
-
36
- language_values['screenshots']['value'].each do |type, value|
37
- value['value'].each do |screenshot|
38
- url = screenshot['value']['url']
39
- file_name = [screenshot['value']['sortOrder'], type, screenshot['value']['originalFileName']].join("_")
40
- Helper.log.info "Downloading existing screenshot '#{file_name}' of device type: '#{type}'"
41
-
42
- containing_folder = File.join(folder_path, "screenshots", language_code)
43
- FileUtils.mkdir_p containing_folder rescue nil # if it's already there
44
- path = File.join(containing_folder, file_name)
45
- File.write(path, open(url).read)
46
- end
47
- end
48
- end
49
- rescue Exception => ex
50
- error_occured(ex)
51
- end
52
- end
53
- end
54
- end
@@ -1,282 +0,0 @@
1
- module Deliver
2
- # Everything related to submitting the app
3
- class ItunesConnect < FastlaneCore::ItunesConnect
4
- BUTTON_ADD_NEW_BUILD = 'Click + to add a build before you submit your app.'
5
-
6
- # This will put the latest uploaded build as a new beta build
7
- def put_build_into_beta_testing!(app, version_number)
8
- begin
9
- verify_app(app)
10
- open_app_page(app)
11
-
12
- Helper.log.info("Choosing the latest build on iTunesConnect for beta distribution")
13
-
14
- require 'excon'
15
-
16
- # Migrate session
17
- cookie_string = page.driver.cookies.collect { |key, cookie| "#{cookie.name}=#{cookie.value}" }.join(";")
18
-
19
- trains_url = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/#{app.apple_id}/trains/"
20
-
21
- current_build = nil
22
- current_train = nil
23
- started = Time.now
24
-
25
-
26
- loop do
27
- trains = JSON.parse(Excon.get(trains_url, headers: { "Cookie" => cookie_string } ).body)
28
- if trains['data']['processingBuilds'].count == 0
29
- # Make sure the build was successfully processed
30
- latest_build_time = 0
31
-
32
- trains['data']['trains'].each do |train|
33
- train['builds'].each do |build|
34
- if build['uploadDate'] > latest_build_time
35
- current_build = build
36
- current_train = train
37
- latest_build_time = build['uploadDate']
38
- end
39
- end
40
- end
41
-
42
- # We got the most recent build, let's see if it's ready
43
- if current_build['readyToInstall'] == true
44
- Helper.log.info "Build is ready 3.2.1...".green
45
- break # Success!
46
- end
47
- end
48
-
49
- Helper.log.info("Sorry, we have to wait for iTunesConnect, since it's still processing the uploaded ipa file\n" +
50
- "If this takes longer than 45 minutes, you have to re-upload the ipa file again.\n" +
51
- "You can always open the browser page yourself: '#{current_url}/pre/builds'\n" +
52
- "Passed time: ~#{((Time.now - started) / 60.0).to_i} minute(s)")
53
- sleep 60
54
- end
55
-
56
-
57
- if not current_train['testing']['value']
58
- # Beta testing for latest build is not yet enabled
59
- current_train['testing']['value'] = true
60
-
61
- Helper.log.info "Beta Testing is disabled for version #{current_train['versionString']}... enabling it now!".green
62
-
63
- # Update the only train we modify
64
- Excon.post(trains_url, body: {trains: [current_train]}.to_json, headers: { "Cookie" => cookie_string } )
65
- end
66
-
67
- build_url = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/apps/#{app.apple_id}/trains/#{current_build['trainVersion']}/builds/#{current_build['buildVersion']}/testInformation"
68
- build_info = JSON.parse(Excon.get(build_url, headers: { "Cookie" => cookie_string } ).body)['data']
69
-
70
- Helper.log.info "Setting the following information for this build:".yellow
71
- Helper.log.info "DELIVER_WHAT_TO_TEST: '#{ENV['DELIVER_WHAT_TO_TEST']}'"
72
- Helper.log.info "DELIVER_BETA_DESCRIPTION: '#{ENV['DELIVER_BETA_DESCRIPTION']}'"
73
- Helper.log.info "DELIVER_BETA_FEEDBACK_EMAIL: '#{ENV['DELIVER_BETA_FEEDBACK_EMAIL']}'"
74
-
75
- build_info['details'].each_with_index do |hash, index|
76
- build_info['details'][index]['whatsNew']['value'] = ENV["DELIVER_WHAT_TO_TEST"]
77
- build_info['details'][index]['description']['value'] ||= ENV["DELIVER_BETA_DESCRIPTION"]
78
- build_info['details'][index]['feedbackEmail']['value'] ||= ENV["DELIVER_BETA_FEEDBACK_EMAIL"]
79
- end
80
-
81
- h = Excon.post(build_url, body: build_info.to_json, headers: { "Cookie" => cookie_string } )
82
-
83
- if h.status == 200
84
- Helper.log.info "Successfully distributed latest beta build 🚀".green
85
- else
86
- Helper.log.info h.data
87
- Helper.log.info "Some error occured marking the new builds as TestFlight build. Please do it manually on '#{current_url}'.".green
88
- end
89
-
90
- return true
91
- rescue => ex
92
- error_occured(ex)
93
- end
94
- end
95
-
96
- # This will choose the latest uploaded build on iTunesConnect as the production one
97
- # After this method, you still have to call submit_for_review to actually submit the
98
- # whole update
99
- # @param app (Deliver::App) the app you want to choose the build for
100
- # @param version_number (String) the version number as string for
101
- def put_build_into_production!(app, version_number)
102
- begin
103
- verify_app(app)
104
- open_app_page(app)
105
-
106
- Helper.log.info("Choosing the latest build on iTunesConnect for release")
107
-
108
- click_on "Prerelease"
109
-
110
- wait_for_preprocessing
111
-
112
- ################# Apple is finished processing the ipa file #################
113
-
114
- Helper.log.info("Apple finally finished processing the ipa file")
115
- open_app_page(app)
116
-
117
- begin
118
- first('a', :text => BUTTON_ADD_NEW_BUILD).click
119
- wait_for_elements(".buildModalList")
120
- sleep 5
121
- rescue
122
- if page.has_content?"Upload Date"
123
- # That's fine, the ipa was already selected
124
- return true
125
- else
126
- raise "Could not find Build Button. It looks like the ipa file was not properly uploaded."
127
- end
128
- end
129
-
130
- if page.all('td', :text => version_number).count > 1
131
- Helper.log.fatal "There were multiple submitted builds found. Don't know which one to choose. Just choosing the top one for now"
132
- end
133
-
134
- result = page.first('td', :text => version_number).first(:xpath,"./..").first(:css, ".small").click
135
- click_on "Done" # Save the modal dialog
136
- click_on "Save" # on the top right to save everything else
137
-
138
- error = page.has_content?BUTTON_ADD_NEW_BUILD
139
- raise "Could not put build itself onto production. Try opening '#{current_url}'" if error
140
-
141
- return true
142
- rescue => ex
143
- error_occured(ex)
144
- end
145
- end
146
-
147
- # Submits the update itself to Apple, this includes the app metadata and the ipa file
148
- # This can easily cause exceptions, which will be shown on iTC.
149
- # @param app (Deliver::App) the app you want to submit
150
- # @param perms (Hash) information about content rights, ...
151
- def submit_for_review!(app, perms = nil)
152
- begin
153
- verify_app(app)
154
- open_app_page(app)
155
-
156
- Helper.log.info("Submitting app for Review")
157
-
158
- if not page.has_content?BUTTON_STRING_SUBMIT_FOR_REVIEW
159
- if page.has_content?WAITING_FOR_REVIEW
160
- Helper.log.info("App is already Waiting For Review")
161
- return true
162
- else
163
- raise "Couldn't find button with name '#{BUTTON_STRING_SUBMIT_FOR_REVIEW}'!"
164
- end
165
- end
166
-
167
- click_on BUTTON_STRING_SUBMIT_FOR_REVIEW
168
- sleep 4
169
-
170
- errors = (all(".pagemessage.error") || []).count > 0
171
- raise "Some error occured when submitting the app for review: '#{current_url}'" if errors
172
-
173
- wait_for_elements(".savingWrapper.ng-scope.ng-pristine")
174
- wait_for_elements(".radiostyle")
175
- sleep 3
176
-
177
- if (page.has_content?"Content Rights") || (page.has_content?"Export") || (page.has_content?"Advertising Identifier")
178
- # Looks good.. just a few more steps
179
-
180
- perms ||= {
181
- export_compliance: {
182
- encryption_updated: false,
183
- cryptography_enabled: false,
184
- is_exempt: false
185
- },
186
- third_party_content: {
187
- contains_third_party_content: false,
188
- has_rights: false
189
- },
190
- advertising_identifier: {
191
- use_idfa: false,
192
- serve_advertisement: false,
193
- attribute_advertisement: false,
194
- attribute_actions: false,
195
- limit_ad_tracking: false
196
- }
197
- }
198
-
199
- basic = "//*[@itc-radio='submitForReviewAnswers"
200
- checkbox = "//*[@itc-checkbox='submitForReviewAnswers"
201
-
202
- #####################
203
- # Export Compliance #
204
- #####################
205
- if page.has_content?"Export"
206
-
207
- if not perms[:export_compliance][:encryption_updated] and perms[:export_compliance][:cryptography_enabled]
208
- raise "encryption_updated must be enabled if cryptography_enabled is enabled!"
209
- end
210
-
211
- begin
212
- encryption_updated_control = all(:xpath, "#{basic}.exportCompliance.encryptionUpdated.value' and @radio-value='#{perms[:export_compliance][:encryption_updated]}']//input")
213
- encryption_updated_control[0].trigger('click') if encryption_updated_control.count > 0
214
- first(:xpath, "#{basic}.exportCompliance.usesEncryption.value' and @radio-value='#{perms[:export_compliance][:cryptography_enabled]}']//input").trigger('click')
215
- first(:xpath, "#{basic}.exportCompliance.isExempt.value' and @radio-value='#{perms[:export_compliance][:is_exempt]}']//input").trigger('click')
216
- rescue
217
- end
218
- end
219
-
220
- ##################
221
- # Content Rights #
222
- ##################
223
- if page.has_content?"Content Rights"
224
-
225
- if not perms[:third_party_content][:contains_third_party_content] and perms[:third_party_content][:has_rights]
226
- raise "contains_third_party_content must be enabled if has_rights is enabled".red
227
- end
228
-
229
- begin
230
- first(:xpath, "#{basic}.contentRights.containsThirdPartyContent.value' and @radio-value='#{perms[:third_party_content][:contains_third_party_content]}']//input").trigger('click')
231
- first(:xpath, "#{basic}.contentRights.hasRights.value' and @radio-value='#{perms[:third_party_content][:has_rights]}']//input").trigger('click')
232
- rescue
233
- end
234
- end
235
-
236
- ##########################
237
- # Advertising Identifier #
238
- ##########################
239
- if page.has_content?"Advertising Identifier"
240
-
241
- first(:xpath, "#{basic}.adIdInfo.usesIdfa.value' and @radio-value='#{perms[:advertising_identifier][:use_idfa]}']//a").click rescue nil
242
-
243
- if perms[:advertising_identifier][:use_idfa]
244
- if perms[:advertising_identifier][:serve_advertisement]
245
- first(:xpath, "#{checkbox}.adIdInfo.servesAds.value']//a").click
246
- end
247
- if perms[:advertising_identifier][:attribute_advertisement]
248
- first(:xpath, "#{checkbox}.adIdInfo.tracksInstall.value']//a").click
249
- end
250
- if perms[:advertising_identifier][:attribute_actions]
251
- first(:xpath, "#{checkbox}.adIdInfo.tracksAction.value']//a").click
252
- end
253
- if perms[:advertising_identifier][:limit_ad_tracking]
254
- first(:xpath, "#{checkbox}.adIdInfo.limitsTracking.value']//a").click
255
- end
256
- end
257
- end
258
-
259
-
260
- Helper.log.info("Filled out the export compliance and other information on iTC".green)
261
-
262
- click_on "Submit"
263
- sleep 5
264
-
265
- if page.has_content?WAITING_FOR_REVIEW
266
- # Everything worked :)
267
- Helper.log.info("Successfully submitted App for Review".green)
268
- return true
269
- else
270
- raise "So close, it looks like there went something wrong with the actual deployment. Checkout '#{current_url}'".red
271
- end
272
- else
273
- raise "Something is missing here.".red
274
- end
275
- return false
276
- rescue => ex
277
- error_occured(ex)
278
- end
279
- end
280
-
281
- end
282
- end