pantograph 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -127
  3. data/pantograph/README.md +2 -2
  4. data/pantograph/lib/assets/ActionDetails.md.erb +1 -1
  5. data/pantograph/lib/assets/DefaultPantfileTemplate +18 -5
  6. data/pantograph/lib/pantograph/action_collector.rb +1 -1
  7. data/pantograph/lib/pantograph/actions/actions_helper.rb +2 -2
  8. data/pantograph/lib/pantograph/actions/clipboard.rb +1 -1
  9. data/pantograph/lib/pantograph/actions/lane_context.rb +1 -1
  10. data/pantograph/lib/pantograph/actions/opt_out_usage.rb +1 -1
  11. data/pantograph/lib/pantograph/actions/sh.rb +1 -1
  12. data/pantograph/lib/pantograph/actions/sonar.rb +1 -1
  13. data/pantograph/lib/pantograph/actions/update_pantograph.rb +1 -1
  14. data/pantograph/lib/pantograph/cli_tools_distributor.rb +2 -2
  15. data/pantograph/lib/pantograph/documentation/actions_list.rb +1 -1
  16. data/pantograph/lib/pantograph/documentation/docs_generator.rb +7 -2
  17. data/pantograph/lib/pantograph/pant_file.rb +4 -4
  18. data/pantograph/lib/pantograph/plugins/plugin_manager.rb +1 -1
  19. data/pantograph/lib/pantograph/plugins/template/README.md.erb +2 -2
  20. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +1 -1
  21. data/pantograph/lib/pantograph/runner.rb +1 -1
  22. data/pantograph/lib/pantograph/setup/setup.rb +28 -64
  23. data/pantograph/lib/pantograph/setup/setup_angular.rb +58 -0
  24. data/pantograph/lib/pantograph/setup/setup_generic.rb +58 -0
  25. data/pantograph/lib/pantograph/setup/setup_gradle.rb +11 -12
  26. data/pantograph/lib/pantograph/setup/setup_maven.rb +58 -0
  27. data/pantograph/lib/pantograph/version.rb +1 -1
  28. data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +1 -1
  29. data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +1 -1
  30. data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +1 -1
  31. data/pantograph_core/lib/pantograph_core/helper.rb +1 -1
  32. data/pantograph_core/lib/pantograph_core/keychain_importer.rb +2 -2
  33. data/pantograph_core/lib/pantograph_core/module.rb +1 -1
  34. data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +2 -2
  35. metadata +6 -4
  36. data/pantograph/lib/pantograph/setup/setup_ios.rb +0 -412
@@ -1,412 +0,0 @@
1
- module Pantograph
2
- class SetupIos < Setup
3
- # Reference to the iOS project `project.rb`
4
- attr_accessor :project
5
-
6
- # App Identifier of the current app
7
- attr_accessor :app_identifier
8
-
9
- # Scheme of the Xcode project
10
- attr_accessor :scheme
11
-
12
- # If the current setup requires a login, this is where we'll store the team ID
13
- attr_accessor :itc_team_id
14
- attr_accessor :adp_team_id
15
-
16
- attr_accessor :app_exists_on_itc
17
-
18
- attr_accessor :automatic_versioning_enabled
19
-
20
- def setup_ios
21
- require 'spaceship'
22
-
23
- self.platform = :ios
24
-
25
- welcome_to_pantograph
26
-
27
- self.pantfile_content = pantfile_template_content
28
-
29
- if preferred_setup_method
30
- self.send(preferred_setup_method)
31
-
32
- return
33
- end
34
-
35
- options = {
36
- "📸 Automate screenshots" => :ios_screenshots,
37
- "👩‍✈️ Automate beta distribution to TestFlight" => :ios_testflight,
38
- "🚀 Automate App Store distribution" => :ios_app_store,
39
- "🛠 Manual setup - manually setup your project to automate your tasks" => :ios_manual
40
- }
41
-
42
- selected = UI.select("What would you like to use pantograph for?", options.keys)
43
- @method_to_use = options[selected]
44
-
45
- begin
46
- self.send(@method_to_use)
47
- rescue => ex
48
- # If it's already manual, and it has failed
49
- # we need to re-raise the exception, as something definitely is wrong
50
- raise ex if @method_to_use == :ios_manual
51
-
52
- # If we're here, that means something else failed. We now show the
53
- # error message and fallback to `:ios_manual`
54
- UI.error("--------------------")
55
- UI.error("pantograph init failed")
56
- UI.error("--------------------")
57
-
58
- UI.verbose(ex.backtrace.join("\n"))
59
- if ex.kind_of?(Spaceship::Client::BasicPreferredInfoError) || ex.kind_of?(Spaceship::Client::UnexpectedResponse)
60
- UI.error(ex.preferred_error_info)
61
- else
62
- UI.error(ex.to_s)
63
- end
64
-
65
- UI.important("Something failed while running `pantograph init`")
66
- UI.important("Tried using Apple ID with email '#{self.user}'")
67
- UI.important("You can either retry, or fallback to manual setup which will create a basic Pantfile")
68
- if UI.confirm("Would you like to fallback to a manual Pantfile?")
69
- self.ios_manual
70
- else
71
- self.send(@method_to_use)
72
- end
73
- # the second time, we're just failing, and don't use a `begin` `rescue` block any more
74
- end
75
- end
76
-
77
- # Different iOS flows
78
- def ios_testflight
79
- UI.header("Setting up pantograph for iOS TestFlight distribution")
80
- find_and_setup_xcode_project
81
- apple_xcode_project_versioning_enabled
82
- ask_for_credentials(adp: true, itc: true)
83
- verify_app_exists_adp!
84
- verify_app_exists_itc!
85
-
86
- lane = ["desc \"Push a new beta build to TestFlight\"",
87
- "lane :beta do",
88
- increment_build_number_if_applicable,
89
- " build_app(#{project_prefix}scheme: \"#{self.scheme}\")",
90
- " upload_to_testflight",
91
- "end"]
92
-
93
- self.append_lane(lane)
94
-
95
- self.lane_to_mention = "beta"
96
- finish_up
97
- end
98
-
99
- def ios_app_store
100
- UI.header("Setting up pantograph for iOS App Store distribution")
101
- find_and_setup_xcode_project
102
- apple_xcode_project_versioning_enabled
103
- ask_for_credentials(adp: true, itc: true)
104
- verify_app_exists_adp!
105
- verify_app_exists_itc!
106
-
107
- if self.app_exists_on_itc
108
- UI.header("Manage app metadata?")
109
- UI.message("Would you like to have pantograph manage your app's metadata?")
110
- UI.message("If you enable this feature, pantograph will download your existing metadata and screenshots.")
111
- UI.message("This way, you'll be able to edit your app's metadata in local `.txt` files.")
112
- UI.message("After editing the local `.txt` files, just run pantograph and all changes will be pushed up.")
113
- UI.message("If you don't want to use this feature, you can still use pantograph to upload and distribute new builds to the App Store")
114
- end
115
-
116
- lane = ["desc \"Push a new release build to the App Store\"",
117
- "lane :release do",
118
- increment_build_number_if_applicable,
119
- " build_app(#{project_prefix}scheme: \"#{self.scheme}\")"]
120
- if include_metadata
121
- lane << " upload_to_app_store"
122
- else
123
- lane << " upload_to_app_store(skip_metadata: true, skip_screenshots: true)"
124
- end
125
- lane << "end"
126
-
127
- append_lane(lane)
128
- self.lane_to_mention = "release"
129
- finish_up
130
- end
131
-
132
- def ios_screenshots
133
- UI.header("Setting up pantograph to automate iOS screenshots")
134
-
135
- UI.message("pantograph uses UI Tests to automate generating localized screenshots of your iOS app")
136
- UI.message("pantograph will now create 2 helper files that are needed to get the setup running")
137
- UI.message("For more information on how this works and best practices, check out")
138
- UI.message("\thttps://docs.pantograph.tools/getting-started/ios/screenshots/".cyan)
139
- continue_with_enter
140
-
141
- begin
142
- find_and_setup_xcode_project(ask_for_scheme: false) # to get the bundle identifier
143
- rescue => ex
144
- # If this fails, it's no big deal, since we really just want the bundle identifier
145
- # so instead, we'll just ask the user
146
- UI.verbose(ex.to_s)
147
- end
148
-
149
- continue_with_enter
150
-
151
- available_schemes = self.project.schemes
152
- ui_testing_scheme = UI.select("Which is your UI Testing scheme? If you can't find it in this list, make sure it's marked as `Shared` in the Xcode scheme list", available_schemes)
153
-
154
- UI.header("Automatically upload to iTC?")
155
- UI.message("Would you like pantograph to automatically upload all generated screenshots to App Store Connect")
156
- UI.message("after generating them?")
157
- UI.message("If you enable this feature you'll need to provide your App Store Connect credentials so pantograph can upload the screenshots to App Store Connect")
158
- automatic_upload = UI.confirm("Enable automatic upload of localized screenshots to App Store Connect?")
159
- if automatic_upload
160
- ask_for_credentials(adp: true, itc: true)
161
- verify_app_exists_itc!
162
- end
163
-
164
- lane = ["desc \"Generate new localized screenshots\"",
165
- "lane :screenshots do",
166
- " capture_screenshots(#{project_prefix}scheme: \"#{ui_testing_scheme}\")"]
167
-
168
- if automatic_upload
169
- lane << " upload_to_app_store(skip_binary_upload: true, skip_metadata: true)"
170
- end
171
- lane << "end"
172
-
173
- append_lane(lane)
174
-
175
- self.lane_to_mention = "screenshots"
176
- finish_up
177
- end
178
-
179
- def ios_manual
180
- UI.header("Setting up pantograph so you can manually configure it")
181
-
182
- append_lane(["desc \"Description of what the lane does\"",
183
- "lane :custom_lane do",
184
- " # add actions here: https://docs.pantograph.tools/actions",
185
- "end"])
186
- self.lane_to_mention = "custom_lane"
187
-
188
- finish_up
189
- end
190
-
191
- # Helpers
192
-
193
- # Every installation setup that needs an Xcode project should
194
- # call this method
195
- def find_and_setup_xcode_project(ask_for_scheme: true)
196
- UI.message("Parsing your local Xcode project to find the available schemes and the app identifier")
197
- config = {} # this is needed as the first method call will store information in there
198
- if self.project_path.end_with?("xcworkspace")
199
- config[:workspace] = self.project_path
200
- else
201
- config[:project] = self.project_path
202
- end
203
-
204
- PantographCore::Project.detect_projects(config)
205
- self.project = PantographCore::Project.new(config)
206
-
207
- if ask_for_scheme
208
- self.scheme = self.project.select_scheme(preferred_to_include: self.project.project_name)
209
- end
210
-
211
- self.app_identifier = self.project.default_app_identifier # These two vars need to be accessed in order to be set
212
- if self.app_identifier.to_s.length == 0
213
- ask_for_bundle_identifier
214
- end
215
- end
216
-
217
- def ask_for_bundle_identifier
218
- loop do
219
- return if self.app_identifier.to_s.length > 0
220
- self.app_identifier = UI.input("Bundle identifier of your app: ")
221
- end
222
- end
223
-
224
- def ask_for_credentials(itc: true, adp: false)
225
- UI.header("Login with your Apple ID")
226
- UI.message("To use App Store Connect and Apple Developer Portal features as part of pantograph,")
227
- UI.message("we will ask you for your Apple ID username and password")
228
- UI.message("This is necessary for certain pantograph features, for example:")
229
- UI.message("")
230
- UI.message("- Create and manage your provisioning profiles on the Developer Portal")
231
- UI.message("- Upload and manage TestFlight and App Store builds on App Store Connect")
232
- UI.message("- Manage your App Store Connect app metadata and screenshots")
233
- UI.message("")
234
- UI.message("Your Apple ID credentials will only be stored in your Keychain, on your local machine")
235
- UI.message("For more information, check out")
236
- UI.message("\thttps://github.com/pantograph/pantograph/tree/master/credentials_manager".cyan)
237
- UI.message("")
238
-
239
- if self.user.to_s.length == 0
240
- UI.important("Please enter your Apple ID developer credentials")
241
- self.user = UI.input("Apple ID Username:")
242
- end
243
- UI.message("Logging in...")
244
-
245
- # Disable the warning texts and information that's not relevant during onboarding
246
- ENV["PANTOGRAPH_HIDE_LOGIN_INFORMATION"] = 1.to_s
247
- ENV["PANTOGRAPH_HIDE_TEAM_INFORMATION"] = 1.to_s
248
-
249
- if itc
250
- Spaceship::Tunes.login(self.user)
251
- Spaceship::Tunes.select_team
252
- self.itc_team_id = Spaceship::Tunes.client.team_id
253
-
254
- end
255
-
256
- if adp
257
- Spaceship::Portal.login(self.user)
258
- Spaceship::Portal.select_team
259
- self.adp_team_id = Spaceship::Portal.client.team_id
260
-
261
- end
262
-
263
- UI.success("✅ Logging in with your Apple ID was successful")
264
- end
265
-
266
- def apple_xcode_project_versioning_enabled
267
- self.automatic_versioning_enabled = false
268
-
269
- paths = self.project.project_paths
270
- return false if paths.count == 0
271
-
272
- result = Pantograph::Actions::GetBuildNumberAction.run({
273
- project: paths.first, # most of the times, there will only be one project in there
274
- hide_error_when_versioning_disabled: true
275
- })
276
-
277
- if result.kind_of?(String) && result.to_f > 0
278
- self.automatic_versioning_enabled = true
279
- end
280
- return self.automatic_versioning_enabled
281
- end
282
-
283
- def show_information_about_version_bumps
284
- UI.important("It looks like your project isn't set up to do automatic version incrementing")
285
- UI.important("To enable pantograph to handle automatic version incrementing for you, please follow this guide:")
286
- UI.message("\thttps://developer.apple.com/library/content/qa/qa1827/_index.html".cyan)
287
- UI.important("Afterwards check out the pantograph docs on how to set up automatic build increments")
288
- UI.message("\thttps://docs.pantograph.tools/getting-started/ios/beta-deployment/#best-practices".cyan)
289
- end
290
-
291
- def verify_app_exists_adp!
292
- UI.user_error!("No app identifier provided") if self.app_identifier.to_s.length == 0
293
- UI.message("Checking if the app '#{self.app_identifier}' exists in your Apple Developer Portal...")
294
- app = Spaceship::Portal::App.find(self.app_identifier)
295
- if app.nil?
296
- UI.error("It looks like the app '#{self.app_identifier}' isn't available on the #{'Apple Developer Portal'.bold.underline}")
297
- UI.error("for the team ID '#{self.adp_team_id}' on Apple ID '#{self.user}'")
298
-
299
- if UI.confirm("Do you want pantograph to create the App ID for you on the Apple Developer Portal?")
300
- create_app_online!(mode: :adp)
301
- else
302
- UI.important("Alright, we won't create the app for you. Be aware, the build is probably going to fail when you try it")
303
- end
304
- else
305
- UI.success("✅ Your app '#{self.app_identifier}' is available in your Apple Developer Portal")
306
- end
307
- end
308
-
309
- def verify_app_exists_itc!
310
- UI.user_error!("No app identifier provided") if self.app_identifier.to_s.length == 0
311
- UI.message("Checking if the app '#{self.app_identifier}' exists on App Store Connect...")
312
- app = Spaceship::Tunes::Application.find(self.app_identifier)
313
- if app.nil?
314
- UI.error("Looks like the app '#{self.app_identifier}' isn't available on #{'App Store Connect'.bold.underline}")
315
- UI.error("for the team ID '#{self.itc_team_id}' on Apple ID '#{self.user}'")
316
- if UI.confirm("Would you like pantograph to create the App on App Store Connect for you?")
317
- create_app_online!(mode: :itc)
318
- self.app_exists_on_itc = true
319
- else
320
- UI.important("Alright, we won't create the app for you. Be aware, the build is probably going to fail when you try it")
321
- end
322
- else
323
- UI.success("✅ Your app '#{self.app_identifier}' is available on App Store Connect")
324
- self.app_exists_on_itc = true
325
- end
326
- end
327
-
328
- def finish_up
329
- # iOS specific things first
330
- if !self.automatic_versioning_enabled && @method_to_use != :ios_manual
331
- self.show_information_about_version_bumps
332
- end
333
-
334
- super
335
- end
336
-
337
- # Returns the `workspace` or `project` key/value pair for
338
- # gym, but only if necessary
339
- # (when there are multiple projects in the current directory)
340
- # it's a prefix, and not a suffix, as Swift cares about the order of parameters
341
- def project_prefix
342
- return "" unless self.had_multiple_projects_to_choose_from
343
-
344
- if self.project_path.end_with?(".xcworkspace")
345
- return "workspace: \"#{self.project_path}\", "
346
- else
347
- return "project: \"#{self.project_path}\", "
348
- end
349
- end
350
-
351
- def increment_build_number_if_applicable
352
- return nil unless self.automatic_versioning_enabled
353
- return nil if self.project.project_paths.first.to_s.length == 0
354
-
355
- project_path = self.project.project_paths.first
356
- # Convert the absolute path to a relative path
357
- project_path_name = Pathname.new(project_path)
358
- current_path_name = Pathname.new(File.expand_path("."))
359
-
360
- relative_project_path = project_path_name.relative_path_from(current_path_name)
361
-
362
- return " increment_build_number(xcodeproj: \"#{relative_project_path}\")"
363
- end
364
-
365
- def create_app_online!(mode: nil)
366
- # mode is either :adp or :itc
367
- require 'produce'
368
- produce_options = {
369
- username: self.user,
370
- team_id: self.adp_team_id,
371
- itc_team_id: self.itc_team_id,
372
- platform: "ios",
373
- app_identifier: self.app_identifier
374
- }
375
- if mode == :adp
376
- produce_options[:skip_itc] = true
377
- else
378
- produce_options[:skip_devcenter] = true
379
- end
380
-
381
- # The retrying system allows people to correct invalid inputs
382
- # e.g. the app's name is already taken
383
- loop do
384
- # Creating config in the loop so user will be reprompted
385
- # for app name if app name is taken or too long
386
- Produce.config = PantographCore::Configuration.create(
387
- Produce::Options.available_options,
388
- produce_options
389
- )
390
-
391
- begin
392
- Produce::Manager.start_producing
393
- UI.success("✅ Successfully created app")
394
- return # success
395
- rescue => ex
396
- # show the user facing error, and inform them of what went wrong
397
- if ex.kind_of?(Spaceship::Client::BasicPreferredInfoError) || ex.kind_of?(Spaceship::Client::UnexpectedResponse)
398
- UI.error(ex.preferred_error_info)
399
- else
400
- UI.error(ex.to_s)
401
- end
402
- UI.error(ex.backtrace.join("\n")) if PantographCore::Globals.verbose?
403
- UI.important("It looks like something went wrong when we tried to create your app on the Apple Developer Portal")
404
- unless UI.confirm("Would you like to try again (y)? If you enter (n), pantograph will fall back to the manual setup")
405
- raise ex
406
- end
407
- end
408
- end
409
- end
410
- end
411
- # rubocop:enable Metrics/ClassLength
412
- end