pantograph 0.1.4 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -127
- data/pantograph/README.md +2 -2
- data/pantograph/lib/assets/ActionDetails.md.erb +1 -1
- data/pantograph/lib/assets/DefaultPantfileTemplate +18 -5
- data/pantograph/lib/pantograph/action_collector.rb +1 -1
- data/pantograph/lib/pantograph/actions/actions_helper.rb +2 -2
- data/pantograph/lib/pantograph/actions/clipboard.rb +1 -1
- data/pantograph/lib/pantograph/actions/lane_context.rb +1 -1
- data/pantograph/lib/pantograph/actions/opt_out_usage.rb +1 -1
- data/pantograph/lib/pantograph/actions/sh.rb +1 -1
- data/pantograph/lib/pantograph/actions/sonar.rb +1 -1
- data/pantograph/lib/pantograph/actions/update_pantograph.rb +1 -1
- data/pantograph/lib/pantograph/cli_tools_distributor.rb +2 -2
- data/pantograph/lib/pantograph/documentation/actions_list.rb +1 -1
- data/pantograph/lib/pantograph/documentation/docs_generator.rb +7 -2
- data/pantograph/lib/pantograph/pant_file.rb +4 -4
- data/pantograph/lib/pantograph/plugins/plugin_manager.rb +1 -1
- data/pantograph/lib/pantograph/plugins/template/README.md.erb +2 -2
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +1 -1
- data/pantograph/lib/pantograph/runner.rb +1 -1
- data/pantograph/lib/pantograph/setup/setup.rb +28 -64
- data/pantograph/lib/pantograph/setup/setup_angular.rb +58 -0
- data/pantograph/lib/pantograph/setup/setup_generic.rb +58 -0
- data/pantograph/lib/pantograph/setup/setup_gradle.rb +11 -12
- data/pantograph/lib/pantograph/setup/setup_maven.rb +58 -0
- data/pantograph/lib/pantograph/version.rb +1 -1
- data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +1 -1
- data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +1 -1
- data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +1 -1
- data/pantograph_core/lib/pantograph_core/helper.rb +1 -1
- data/pantograph_core/lib/pantograph_core/keychain_importer.rb +2 -2
- data/pantograph_core/lib/pantograph_core/module.rb +1 -1
- data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +2 -2
- metadata +6 -4
- 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
|