pantograph 0.1.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 +7 -0
- data/.yardopts +1 -0
- data/LICENSE +21 -0
- data/README.md +197 -0
- data/bin/bin-proxy +19 -0
- data/bin/pantograph +23 -0
- data/pantograph/README.md +11 -0
- data/pantograph/lib/assets/ActionDetails.md.erb +106 -0
- data/pantograph/lib/assets/Actions.md.erb +43 -0
- data/pantograph/lib/assets/DefaultPantfileTemplate +20 -0
- data/pantograph/lib/assets/completions/completion.bash +23 -0
- data/pantograph/lib/assets/completions/completion.fish +39 -0
- data/pantograph/lib/assets/completions/completion.sh +12 -0
- data/pantograph/lib/assets/completions/completion.zsh +23 -0
- data/pantograph/lib/assets/custom_action_template.rb +80 -0
- data/pantograph/lib/assets/report_template.xml.erb +15 -0
- data/pantograph/lib/pantograph/action.rb +194 -0
- data/pantograph/lib/pantograph/action_collector.rb +35 -0
- data/pantograph/lib/pantograph/actions/README.md +3 -0
- data/pantograph/lib/pantograph/actions/actions_helper.rb +166 -0
- data/pantograph/lib/pantograph/actions/add_extra_platforms.rb +45 -0
- data/pantograph/lib/pantograph/actions/artifactory.rb +157 -0
- data/pantograph/lib/pantograph/actions/bundle_install.rb +156 -0
- data/pantograph/lib/pantograph/actions/changelog_from_git_commits.rb +197 -0
- data/pantograph/lib/pantograph/actions/clipboard.rb +52 -0
- data/pantograph/lib/pantograph/actions/cloc.rb +89 -0
- data/pantograph/lib/pantograph/actions/create_pull_request.rb +190 -0
- data/pantograph/lib/pantograph/actions/danger.rb +131 -0
- data/pantograph/lib/pantograph/actions/debug.rb +32 -0
- data/pantograph/lib/pantograph/actions/default_platform.rb +47 -0
- data/pantograph/lib/pantograph/actions/download.rb +76 -0
- data/pantograph/lib/pantograph/actions/echo.rb +14 -0
- data/pantograph/lib/pantograph/actions/ensure_bundle_exec.rb +59 -0
- data/pantograph/lib/pantograph/actions/ensure_env_vars.rb +58 -0
- data/pantograph/lib/pantograph/actions/ensure_git_branch.rb +69 -0
- data/pantograph/lib/pantograph/actions/ensure_git_status_clean.rb +81 -0
- data/pantograph/lib/pantograph/actions/erb.rb +88 -0
- data/pantograph/lib/pantograph/actions/get_build_number_repository.rb +120 -0
- data/pantograph/lib/pantograph/actions/get_github_release.rb +163 -0
- data/pantograph/lib/pantograph/actions/git_add.rb +93 -0
- data/pantograph/lib/pantograph/actions/git_branch.rb +58 -0
- data/pantograph/lib/pantograph/actions/git_commit.rb +80 -0
- data/pantograph/lib/pantograph/actions/git_pull.rb +53 -0
- data/pantograph/lib/pantograph/actions/git_submodule_update.rb +52 -0
- data/pantograph/lib/pantograph/actions/git_tag_exists.rb +74 -0
- data/pantograph/lib/pantograph/actions/github_api.rb +262 -0
- data/pantograph/lib/pantograph/actions/gradle.rb +278 -0
- data/pantograph/lib/pantograph/actions/import.rb +49 -0
- data/pantograph/lib/pantograph/actions/import_from_git.rb +71 -0
- data/pantograph/lib/pantograph/actions/is_ci.rb +51 -0
- data/pantograph/lib/pantograph/actions/jira.rb +115 -0
- data/pantograph/lib/pantograph/actions/lane_context.rb +60 -0
- data/pantograph/lib/pantograph/actions/last_git_commit.rb +58 -0
- data/pantograph/lib/pantograph/actions/last_git_tag.rb +51 -0
- data/pantograph/lib/pantograph/actions/make_changelog_from_jenkins.rb +81 -0
- data/pantograph/lib/pantograph/actions/min_pantograph_version.rb +57 -0
- data/pantograph/lib/pantograph/actions/nexus_upload.rb +230 -0
- data/pantograph/lib/pantograph/actions/notification.rb +75 -0
- data/pantograph/lib/pantograph/actions/number_of_commits.rb +75 -0
- data/pantograph/lib/pantograph/actions/opt_out_usage.rb +40 -0
- data/pantograph/lib/pantograph/actions/pantograph_version.rb +15 -0
- data/pantograph/lib/pantograph/actions/println.rb +14 -0
- data/pantograph/lib/pantograph/actions/prompt.rb +119 -0
- data/pantograph/lib/pantograph/actions/push_git_tags.rb +76 -0
- data/pantograph/lib/pantograph/actions/push_to_git_remote.rb +127 -0
- data/pantograph/lib/pantograph/actions/puts.rb +68 -0
- data/pantograph/lib/pantograph/actions/reset_git_repo.rb +121 -0
- data/pantograph/lib/pantograph/actions/rocket.rb +83 -0
- data/pantograph/lib/pantograph/actions/rsync.rb +74 -0
- data/pantograph/lib/pantograph/actions/ruby_version.rb +56 -0
- data/pantograph/lib/pantograph/actions/say.rb +56 -0
- data/pantograph/lib/pantograph/actions/scp.rb +114 -0
- data/pantograph/lib/pantograph/actions/set_github_release.rb +274 -0
- data/pantograph/lib/pantograph/actions/sh.rb +71 -0
- data/pantograph/lib/pantograph/actions/skip_docs.rb +52 -0
- data/pantograph/lib/pantograph/actions/slack.rb +288 -0
- data/pantograph/lib/pantograph/actions/sonar.rb +156 -0
- data/pantograph/lib/pantograph/actions/ssh.rb +162 -0
- data/pantograph/lib/pantograph/actions/twitter.rb +89 -0
- data/pantograph/lib/pantograph/actions/update_pantograph.rb +177 -0
- data/pantograph/lib/pantograph/actions/zip.rb +120 -0
- data/pantograph/lib/pantograph/auto_complete.rb +82 -0
- data/pantograph/lib/pantograph/boolean.rb +5 -0
- data/pantograph/lib/pantograph/cli_tools_distributor.rb +183 -0
- data/pantograph/lib/pantograph/command_line_handler.rb +43 -0
- data/pantograph/lib/pantograph/commands_generator.rb +344 -0
- data/pantograph/lib/pantograph/configuration_helper.rb +26 -0
- data/pantograph/lib/pantograph/core_ext/bundler_monkey_patch.rb +14 -0
- data/pantograph/lib/pantograph/documentation/actions_list.rb +214 -0
- data/pantograph/lib/pantograph/documentation/docs_generator.rb +95 -0
- data/pantograph/lib/pantograph/documentation/markdown_docs_generator.rb +221 -0
- data/pantograph/lib/pantograph/environment_printer.rb +282 -0
- data/pantograph/lib/pantograph/erb_template_helper.rb +30 -0
- data/pantograph/lib/pantograph/features.rb +4 -0
- data/pantograph/lib/pantograph/helper/README.md +29 -0
- data/pantograph/lib/pantograph/helper/dotenv_helper.rb +50 -0
- data/pantograph/lib/pantograph/helper/gem_helper.rb +26 -0
- data/pantograph/lib/pantograph/helper/git_helper.rb +135 -0
- data/pantograph/lib/pantograph/helper/gradle_helper.rb +62 -0
- data/pantograph/lib/pantograph/helper/sh_helper.rb +134 -0
- data/pantograph/lib/pantograph/junit_generator.rb +27 -0
- data/pantograph/lib/pantograph/lane.rb +97 -0
- data/pantograph/lib/pantograph/lane_list.rb +77 -0
- data/pantograph/lib/pantograph/lane_manager.rb +140 -0
- data/pantograph/lib/pantograph/lane_manager_base.rb +92 -0
- data/pantograph/lib/pantograph/markdown_table_formatter.rb +62 -0
- data/pantograph/lib/pantograph/new_action.rb +47 -0
- data/pantograph/lib/pantograph/one_off.rb +45 -0
- data/pantograph/lib/pantograph/other_action.rb +29 -0
- data/pantograph/lib/pantograph/pant_file.rb +377 -0
- data/pantograph/lib/pantograph/pantograph_require.rb +75 -0
- data/pantograph/lib/pantograph/plugins/plugin_fetcher.rb +55 -0
- data/pantograph/lib/pantograph/plugins/plugin_generator.rb +86 -0
- data/pantograph/lib/pantograph/plugins/plugin_generator_ui.rb +19 -0
- data/pantograph/lib/pantograph/plugins/plugin_info.rb +49 -0
- data/pantograph/lib/pantograph/plugins/plugin_info_collector.rb +159 -0
- data/pantograph/lib/pantograph/plugins/plugin_manager.rb +387 -0
- data/pantograph/lib/pantograph/plugins/plugin_search.rb +46 -0
- data/pantograph/lib/pantograph/plugins/plugin_update_manager.rb +70 -0
- data/pantograph/lib/pantograph/plugins/plugins.rb +12 -0
- data/pantograph/lib/pantograph/plugins/template/%gem_name%.gemspec.erb +35 -0
- data/pantograph/lib/pantograph/plugins/template/.circleci/config.yml +43 -0
- data/pantograph/lib/pantograph/plugins/template/.gitignore +12 -0
- data/pantograph/lib/pantograph/plugins/template/.rspec +5 -0
- data/pantograph/lib/pantograph/plugins/template/.rubocop.yml +179 -0
- data/pantograph/lib/pantograph/plugins/template/.travis.yml +4 -0
- data/pantograph/lib/pantograph/plugins/template/Gemfile +6 -0
- data/pantograph/lib/pantograph/plugins/template/LICENSE.erb +21 -0
- data/pantograph/lib/pantograph/plugins/template/README.md.erb +52 -0
- data/pantograph/lib/pantograph/plugins/template/Rakefile +9 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +47 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +16 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/version.rb.erb +5 -0
- data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%.rb.erb +16 -0
- data/pantograph/lib/pantograph/plugins/template/pantograph/Pantfile.erb +3 -0
- data/pantograph/lib/pantograph/plugins/template/pantograph/Pluginfile.erb +1 -0
- data/pantograph/lib/pantograph/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
- data/pantograph/lib/pantograph/plugins/template/spec/spec_helper.rb.erb +15 -0
- data/pantograph/lib/pantograph/runner.rb +371 -0
- data/pantograph/lib/pantograph/server/action_command.rb +61 -0
- data/pantograph/lib/pantograph/server/action_command_return.rb +14 -0
- data/pantograph/lib/pantograph/server/command_executor.rb +7 -0
- data/pantograph/lib/pantograph/server/command_parser.rb +36 -0
- data/pantograph/lib/pantograph/server/control_command.rb +23 -0
- data/pantograph/lib/pantograph/server/json_return_value_processor.rb +72 -0
- data/pantograph/lib/pantograph/server/socket_server.rb +232 -0
- data/pantograph/lib/pantograph/server/socket_server_action_command_executor.rb +101 -0
- data/pantograph/lib/pantograph/setup/setup.rb +290 -0
- data/pantograph/lib/pantograph/setup/setup_android.rb +64 -0
- data/pantograph/lib/pantograph/setup/setup_ios.rb +412 -0
- data/pantograph/lib/pantograph/shells.rb +6 -0
- data/pantograph/lib/pantograph/supported_platforms.rb +28 -0
- data/pantograph/lib/pantograph/tools.rb +10 -0
- data/pantograph/lib/pantograph/version.rb +5 -0
- data/pantograph/lib/pantograph.rb +51 -0
- data/pantograph_core/README.md +79 -0
- data/pantograph_core/lib/assets/XMLTemplate.xml.erb +12 -0
- data/pantograph_core/lib/pantograph_core/analytics/action_completion_context.rb +34 -0
- data/pantograph_core/lib/pantograph_core/analytics/action_launch_context.rb +38 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_event_builder.rb +23 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +54 -0
- data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +71 -0
- data/pantograph_core/lib/pantograph_core/cert_checker.rb +116 -0
- data/pantograph_core/lib/pantograph_core/command_executor.rb +99 -0
- data/pantograph_core/lib/pantograph_core/configuration/commander_generator.rb +103 -0
- data/pantograph_core/lib/pantograph_core/configuration/config_item.rb +314 -0
- data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +332 -0
- data/pantograph_core/lib/pantograph_core/configuration/configuration_file.rb +182 -0
- data/pantograph_core/lib/pantograph_core/core_ext/shellwords.rb +63 -0
- data/pantograph_core/lib/pantograph_core/core_ext/string.rb +17 -0
- data/pantograph_core/lib/pantograph_core/env.rb +9 -0
- data/pantograph_core/lib/pantograph_core/feature/feature.rb +51 -0
- data/pantograph_core/lib/pantograph_core/features.rb +4 -0
- data/pantograph_core/lib/pantograph_core/globals.rb +27 -0
- data/pantograph_core/lib/pantograph_core/helper.rb +409 -0
- data/pantograph_core/lib/pantograph_core/keychain_importer.rb +74 -0
- data/pantograph_core/lib/pantograph_core/languages.rb +14 -0
- data/pantograph_core/lib/pantograph_core/module.rb +29 -0
- data/pantograph_core/lib/pantograph_core/pantograph_folder.rb +39 -0
- data/pantograph_core/lib/pantograph_core/pantograph_pty.rb +57 -0
- data/pantograph_core/lib/pantograph_core/pkg_file_analyser.rb +44 -0
- data/pantograph_core/lib/pantograph_core/print_table.rb +131 -0
- data/pantograph_core/lib/pantograph_core/string_filters.rb +51 -0
- data/pantograph_core/lib/pantograph_core/swag.rb +85 -0
- data/pantograph_core/lib/pantograph_core/tag_version.rb +31 -0
- data/pantograph_core/lib/pantograph_core/test_parser.rb +107 -0
- data/pantograph_core/lib/pantograph_core/ui/disable_colors.rb +17 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_common_error.rb +19 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_crash.rb +11 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_error.rb +25 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_exception.rb +19 -0
- data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_shell_error.rb +11 -0
- data/pantograph_core/lib/pantograph_core/ui/errors.rb +1 -0
- data/pantograph_core/lib/pantograph_core/ui/github_issue_inspector_reporter.rb +62 -0
- data/pantograph_core/lib/pantograph_core/ui/implementations/shell.rb +159 -0
- data/pantograph_core/lib/pantograph_core/ui/interface.rb +205 -0
- data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +276 -0
- data/pantograph_core/lib/pantograph_core/ui/ui.rb +26 -0
- data/pantograph_core/lib/pantograph_core/update_checker/changelog.rb +37 -0
- data/pantograph_core/lib/pantograph_core/update_checker/update_checker.rb +107 -0
- data/pantograph_core/lib/pantograph_core.rb +45 -0
- metadata +987 -0
@@ -0,0 +1,412 @@
|
|
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
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class SupportedPlatforms
|
3
|
+
class << self
|
4
|
+
attr_accessor :extra
|
5
|
+
attr_reader :default
|
6
|
+
|
7
|
+
def extra=(value)
|
8
|
+
value ||= []
|
9
|
+
UI.important("Setting '#{value}' as extra SupportedPlatforms")
|
10
|
+
@extra = value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
@default = [:ios, :mac, :android]
|
15
|
+
@extra = []
|
16
|
+
|
17
|
+
def self.all
|
18
|
+
(@default + @extra).flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
# this will log a warning if the passed platform is not supported
|
22
|
+
def self.verify!(platform)
|
23
|
+
unless all.include?(platform.to_s.to_sym)
|
24
|
+
UI.important("Platform '#{platform}' is not officially supported. Currently supported platforms are #{self.all}.")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pantograph_core'
|
2
|
+
|
3
|
+
require 'pantograph/version'
|
4
|
+
require 'pantograph/features'
|
5
|
+
require 'pantograph/shells'
|
6
|
+
require 'pantograph/tools'
|
7
|
+
require 'pantograph/documentation/actions_list'
|
8
|
+
require 'pantograph/actions/actions_helper' # has to be before pant_file
|
9
|
+
require 'pantograph/pant_file'
|
10
|
+
require 'pantograph/runner'
|
11
|
+
require 'pantograph/setup/setup'
|
12
|
+
require 'pantograph/lane'
|
13
|
+
require 'pantograph/junit_generator'
|
14
|
+
require 'pantograph/lane_manager'
|
15
|
+
require 'pantograph/lane_manager_base'
|
16
|
+
require 'pantograph/action'
|
17
|
+
require 'pantograph/action_collector'
|
18
|
+
require 'pantograph/supported_platforms'
|
19
|
+
require 'pantograph/configuration_helper'
|
20
|
+
require 'pantograph/one_off'
|
21
|
+
require 'pantograph/server/socket_server_action_command_executor'
|
22
|
+
require 'pantograph/server/socket_server'
|
23
|
+
require 'pantograph/command_line_handler'
|
24
|
+
require 'pantograph/documentation/docs_generator'
|
25
|
+
require 'pantograph/other_action'
|
26
|
+
require 'pantograph/plugins/plugins'
|
27
|
+
require 'pantograph/pantograph_require'
|
28
|
+
|
29
|
+
module Pantograph
|
30
|
+
Helper = PantographCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in PantographCore
|
31
|
+
UI = PantographCore::UI
|
32
|
+
ROOT = Pathname.new(File.expand_path('../..', __FILE__))
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def load_actions
|
36
|
+
Pantograph::Actions.load_default_actions
|
37
|
+
Pantograph::Actions.load_helpers
|
38
|
+
|
39
|
+
if PantographCore::PantographFolder.path
|
40
|
+
actions_path = File.join(PantographCore::PantographFolder.path, 'actions')
|
41
|
+
@external_actions = Pantograph::Actions.load_external_actions(actions_path) if File.directory?(actions_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :external_actions
|
46
|
+
|
47
|
+
def plugin_manager
|
48
|
+
@plugin_manager ||= Pantograph::PluginManager.new
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
PantographCore
|
2
|
+
============
|
3
|
+
|
4
|
+
[](https://twitter.com/PantographTools)
|
5
|
+
[](https://github.com/pantograph/pantograph/blob/master/LICENSE)
|
6
|
+
|
7
|
+
All shared code of the pantograph tools is stored in this repository.
|
8
|
+
|
9
|
+
Get in contact with the developer on Twitter: [@PantographTools](https://twitter.com/PantographTools)
|
10
|
+
|
11
|
+
# Features
|
12
|
+
|
13
|
+
This gem contains all shared classes and code:
|
14
|
+
|
15
|
+
- Checking for updates for a specific gem and showing an update message
|
16
|
+
- All output of all tools with different logging levels
|
17
|
+
- Finding of the current Xcode and iTunes Transporter path
|
18
|
+
- More helper methods and classes
|
19
|
+
|
20
|
+
You can hide the inline changelog by setting the `PANTOGRAPH_HIDE_CHANGELOG` environment variable
|
21
|
+
|
22
|
+
## Output environment variables
|
23
|
+
|
24
|
+
- To hide timestamps in each row, set the `PANTOGRAPH_HIDE_TIMESTAMP` environment variable to true.
|
25
|
+
- To disable output formatting, set the `PANTOGRAPH_DISABLE_OUTPUT_FORMAT` environment variable to true.
|
26
|
+
|
27
|
+
## Interacting with the user
|
28
|
+
|
29
|
+
Instead of using `puts`, `raise` and `gets`, please use the helper class `UI` across all pantograph tools:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
UI.message("Neutral message (usually white)")
|
33
|
+
UI.success("Successfully finished processing (usually green)")
|
34
|
+
UI.error("Wahaha, what's going on here! (usually red)")
|
35
|
+
UI.important("Make sure to use Windows (usually yellow)")
|
36
|
+
|
37
|
+
UI.header("Inputs") # a big box
|
38
|
+
|
39
|
+
name = UI.input("What's your name? ")
|
40
|
+
if UI.confirm("Are you '#{name}'?")
|
41
|
+
UI.success("Oh yeah")
|
42
|
+
else
|
43
|
+
UI.error("Wups, invalid")
|
44
|
+
end
|
45
|
+
|
46
|
+
UI.password("Your password please: ") # password inputs are hidden
|
47
|
+
|
48
|
+
###### A "Dropdown" for the user
|
49
|
+
project = UI.select("Select your project: ", ["Test Project", "Test Workspace"])
|
50
|
+
|
51
|
+
UI.success("Okay #{name}, you selected '#{project}'")
|
52
|
+
|
53
|
+
###### To run a command use
|
54
|
+
PantographCore::CommandExecutor.execute(command: "ls",
|
55
|
+
print_all: true,
|
56
|
+
error: proc do |error_output|
|
57
|
+
# handle error here
|
58
|
+
end)
|
59
|
+
|
60
|
+
###### or if you just want to receive a simple value use this only if the command doesn't take long
|
61
|
+
diff = Helper.backticks("git diff")
|
62
|
+
|
63
|
+
###### pantograph "crash" because of a user error everything that is caused by the user and is not unexpected
|
64
|
+
UI.user_error!("You don't have a project in the current directory")
|
65
|
+
|
66
|
+
###### an actual crash when something unexpected happened
|
67
|
+
UI.crash!("Network timeout")
|
68
|
+
|
69
|
+
###### a deprecation message
|
70
|
+
UI.deprecated("The '--key' parameter is deprecated")
|
71
|
+
```
|
72
|
+
|
73
|
+
# Code of Conduct
|
74
|
+
Help us keep _pantograph_ open and inclusive. Please read and follow our [Code of Conduct](https://github.com/pantograph/pantograph/blob/master/CODE_OF_CONDUCT.md).
|
75
|
+
|
76
|
+
# License
|
77
|
+
This project is licensed under the terms of the MIT license. See the LICENSE file.
|
78
|
+
|
79
|
+
> This project and all pantograph tools are in no way affiliated with Apple Inc. This project is open source under the MIT license, which means you have full access to the source code and can modify it to fit your own needs. All pantograph tools run on your own computer or server, so your credentials or other sensitive information will never leave your own computer. You are responsible for how you use pantograph tools.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<package xmlns="http://apple.com/itunes/importer" version="software5.4">
|
3
|
+
<software_assets apple_id="<%= @data[:apple_id] %>" app_platform="<%= @data[:platform] %>">
|
4
|
+
<asset type="<%= @data[:archive_type] %>">
|
5
|
+
<data_file>
|
6
|
+
<size><%= @data[:file_size] %></size>
|
7
|
+
<file_name><%= @data[:ipa_path] %></file_name>
|
8
|
+
<checksum type="md5"><%= @data[:md5] %></checksum>
|
9
|
+
</data_file>
|
10
|
+
</asset>
|
11
|
+
</software_assets>
|
12
|
+
</package>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# require_relative 'app_identifier_guesser'
|
2
|
+
|
3
|
+
module PantographCore
|
4
|
+
class ActionCompletionStatus
|
5
|
+
SUCCESS = 'success'
|
6
|
+
FAILED = 'failed' # pantograph crashes unrelated to user_error!
|
7
|
+
USER_ERROR = 'user_error' # Anytime a user_error! is triggered
|
8
|
+
INTERRUPTED = 'interrupted'
|
9
|
+
end
|
10
|
+
|
11
|
+
class ActionCompletionContext
|
12
|
+
attr_accessor :p_hash
|
13
|
+
attr_accessor :action_name
|
14
|
+
attr_accessor :status
|
15
|
+
attr_accessor :pantograph_client_language
|
16
|
+
|
17
|
+
def initialize(p_hash: nil, action_name: nil, status: nil, pantograph_client_language: nil)
|
18
|
+
@p_hash = p_hash
|
19
|
+
@action_name = action_name
|
20
|
+
@status = status
|
21
|
+
@pantograph_client_language = pantograph_client_language
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.context_for_action_name(action_name, pantograph_client_language: :ruby, args: nil, status: nil)
|
25
|
+
# app_id_guesser = PantographCore::AppIdentifierGuesser.new(args: args)
|
26
|
+
return self.new(
|
27
|
+
action_name: action_name,
|
28
|
+
p_hash: 'unknown',
|
29
|
+
status: status,
|
30
|
+
pantograph_client_language: pantograph_client_language
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
# require_relative 'app_identifier_guesser'
|
3
|
+
|
4
|
+
module PantographCore
|
5
|
+
class ActionLaunchContext
|
6
|
+
UNKNOWN_P_HASH = 'unknown'
|
7
|
+
|
8
|
+
attr_accessor :action_name
|
9
|
+
attr_accessor :p_hash
|
10
|
+
attr_accessor :platform
|
11
|
+
attr_accessor :pantograph_client_language # example: ruby pantfile
|
12
|
+
|
13
|
+
def initialize(action_name: nil, p_hash: UNKNOWN_P_HASH, platform: nil, pantograph_client_language: nil)
|
14
|
+
@action_name = action_name
|
15
|
+
@p_hash = p_hash
|
16
|
+
@platform = platform
|
17
|
+
@pantograph_client_language = pantograph_client_language
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.context_for_action_name(action_name, pantograph_client_language: :ruby, args: nil)
|
21
|
+
# app_id_guesser = PantographCore::AppIdentifierGuesser.new(args: args)
|
22
|
+
return self.new(
|
23
|
+
action_name: action_name,
|
24
|
+
p_hash: UNKNOWN_P_HASH,
|
25
|
+
# platform: nil,
|
26
|
+
pantograph_client_language: pantograph_client_language
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_tool_version
|
31
|
+
if platform == :android
|
32
|
+
return 'android'
|
33
|
+
else
|
34
|
+
return "Xcode #{Helper.xcode_version}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|