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,232 @@
|
|
1
|
+
require 'pantograph/server/command_executor.rb'
|
2
|
+
require 'pantograph/server/command_parser.rb'
|
3
|
+
require 'pantograph/server/json_return_value_processor.rb'
|
4
|
+
require 'socket'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Pantograph
|
8
|
+
class SocketServer
|
9
|
+
COMMAND_EXECUTION_STATE = {
|
10
|
+
ready: :ready,
|
11
|
+
already_shutdown: :already_shutdown,
|
12
|
+
error: :error
|
13
|
+
}
|
14
|
+
|
15
|
+
attr_accessor :command_executor
|
16
|
+
attr_accessor :return_value_processor
|
17
|
+
|
18
|
+
def initialize(
|
19
|
+
command_executor: nil,
|
20
|
+
return_value_processor: nil,
|
21
|
+
connection_timeout: 5,
|
22
|
+
stay_alive: false,
|
23
|
+
port: 2000
|
24
|
+
)
|
25
|
+
if return_value_processor.nil?
|
26
|
+
return_value_processor = JSONReturnValueProcessor.new
|
27
|
+
end
|
28
|
+
|
29
|
+
@command_executor = command_executor
|
30
|
+
@return_value_processor = return_value_processor
|
31
|
+
@connection_timeout = connection_timeout.to_i
|
32
|
+
@stay_alive = stay_alive
|
33
|
+
@port = port.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
# this is the public API, don't call anything else
|
37
|
+
def start
|
38
|
+
listen
|
39
|
+
|
40
|
+
while @stay_alive
|
41
|
+
UI.important("stay_alive is set to true, restarting server")
|
42
|
+
listen
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def receive_and_process_commands
|
49
|
+
loop do # no idea how many commands are coming, so we loop until an error or the done command is sent
|
50
|
+
execution_state = COMMAND_EXECUTION_STATE[:ready]
|
51
|
+
|
52
|
+
command_string = nil
|
53
|
+
begin
|
54
|
+
command_string = @client.recv(1_048_576) # 1024 * 1024
|
55
|
+
rescue Errno::ECONNRESET => e
|
56
|
+
UI.verbose(e)
|
57
|
+
execution_state = COMMAND_EXECUTION_STATE[:error]
|
58
|
+
end
|
59
|
+
|
60
|
+
if execution_state == COMMAND_EXECUTION_STATE[:ready]
|
61
|
+
# Ok, all is good, let's see what command we have
|
62
|
+
execution_state = parse_and_execute_command(command_string: command_string)
|
63
|
+
end
|
64
|
+
|
65
|
+
case execution_state
|
66
|
+
when COMMAND_EXECUTION_STATE[:ready]
|
67
|
+
# command executed successfully, let's setup for the next command
|
68
|
+
next
|
69
|
+
when COMMAND_EXECUTION_STATE[:already_shutdown]
|
70
|
+
# we shutdown in response to a command, nothing left to do but exit
|
71
|
+
break
|
72
|
+
when COMMAND_EXECUTION_STATE[:error]
|
73
|
+
# we got an error somewhere, let's shutdown and exit
|
74
|
+
handle_disconnect(error: true, exit_reason: :error)
|
75
|
+
break
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_and_execute_command(command_string: nil)
|
81
|
+
command = CommandParser.parse(json: command_string)
|
82
|
+
case command
|
83
|
+
when ControlCommand
|
84
|
+
return handle_control_command(command)
|
85
|
+
when ActionCommand
|
86
|
+
return handle_action_command(command)
|
87
|
+
end
|
88
|
+
|
89
|
+
# catch all
|
90
|
+
raise "Command #{command} not supported"
|
91
|
+
end
|
92
|
+
|
93
|
+
# we got a server control command from the client to do something like shutdown
|
94
|
+
def handle_control_command(command)
|
95
|
+
exit_reason = nil
|
96
|
+
if command.cancel_signal?
|
97
|
+
UI.verbose("received cancel signal shutting down, reason: #{command.reason}")
|
98
|
+
|
99
|
+
# send an ack to the client to let it know we're shutting down
|
100
|
+
cancel_response = '{"payload":{"status":"cancelled"}}'
|
101
|
+
send_response(cancel_response)
|
102
|
+
|
103
|
+
exit_reason = :cancelled
|
104
|
+
elsif command.done_signal?
|
105
|
+
UI.verbose("received done signal shutting down")
|
106
|
+
|
107
|
+
# client is already in the process of shutting down, no need to ack
|
108
|
+
exit_reason = :done
|
109
|
+
end
|
110
|
+
|
111
|
+
# if the command came in with a user-facing message, display it
|
112
|
+
if command.user_message
|
113
|
+
UI.important(command.user_message)
|
114
|
+
end
|
115
|
+
|
116
|
+
# currently all control commands should trigger a disconnect and shutdown
|
117
|
+
handle_disconnect(error: false, exit_reason: exit_reason)
|
118
|
+
return COMMAND_EXECUTION_STATE[:already_shutdown]
|
119
|
+
end
|
120
|
+
|
121
|
+
# execute and send back response to client
|
122
|
+
def handle_action_command(command)
|
123
|
+
response_json = process_action_command(command: command)
|
124
|
+
return send_response(response_json)
|
125
|
+
end
|
126
|
+
|
127
|
+
# send json back to client
|
128
|
+
def send_response(json)
|
129
|
+
UI.verbose("sending #{json}")
|
130
|
+
begin
|
131
|
+
@client.puts(json) # Send some json to the client
|
132
|
+
rescue Errno::EPIPE => e
|
133
|
+
UI.verbose(e)
|
134
|
+
return COMMAND_EXECUTION_STATE[:error]
|
135
|
+
end
|
136
|
+
return COMMAND_EXECUTION_STATE[:ready]
|
137
|
+
end
|
138
|
+
|
139
|
+
def listen
|
140
|
+
@server = TCPServer.open('localhost', @port) # Socket to listen on port 2000
|
141
|
+
UI.verbose("Waiting for #{@connection_timeout} seconds for a connection from PantographRunner")
|
142
|
+
|
143
|
+
# set thread local to ready so we can check it
|
144
|
+
Thread.current[:ready] = true
|
145
|
+
@client = nil
|
146
|
+
begin
|
147
|
+
Timeout.timeout(@connection_timeout) do
|
148
|
+
@client = @server.accept # Wait for a client to connect
|
149
|
+
end
|
150
|
+
rescue Timeout::Error
|
151
|
+
UI.user_error!("pantograph failed to receive a connection from the PantographRunner binary after #{@connection_timeout} seconds, shutting down")
|
152
|
+
rescue StandardError => e
|
153
|
+
UI.user_error!("Something went wrong while waiting for a connection from the PantographRunner binary, shutting down\n#{e}")
|
154
|
+
end
|
155
|
+
UI.verbose("Client connected")
|
156
|
+
|
157
|
+
# this loops forever
|
158
|
+
receive_and_process_commands
|
159
|
+
end
|
160
|
+
|
161
|
+
def handle_disconnect(error: false, exit_reason: :error)
|
162
|
+
Thread.current[:exit_reason] = exit_reason
|
163
|
+
|
164
|
+
UI.important("Client disconnected, a pipe broke, or received malformed data") if exit_reason == :error
|
165
|
+
# clean up
|
166
|
+
@client.close
|
167
|
+
@client = nil
|
168
|
+
|
169
|
+
@server.close
|
170
|
+
@server = nil
|
171
|
+
end
|
172
|
+
|
173
|
+
# record pantograph action command and then execute it
|
174
|
+
def process_action_command(command: nil)
|
175
|
+
UI.verbose("received command:#{command.inspect}")
|
176
|
+
return execute_action_command(command: command)
|
177
|
+
end
|
178
|
+
|
179
|
+
# execute pantograph action command
|
180
|
+
def execute_action_command(command: nil)
|
181
|
+
command_return = @command_executor.execute(command: command, target_object: nil)
|
182
|
+
## probably need to just return Strings, or ready_for_next with object isn't String
|
183
|
+
return_object = command_return.return_value
|
184
|
+
return_value_type = command_return.return_value_type
|
185
|
+
closure_arg = command_return.closure_argument_value
|
186
|
+
|
187
|
+
return_object = return_value_processor.prepare_object(
|
188
|
+
return_value: return_object,
|
189
|
+
return_value_type: return_value_type
|
190
|
+
)
|
191
|
+
|
192
|
+
if closure_arg.nil?
|
193
|
+
closure_arg = closure_arg.to_s
|
194
|
+
else
|
195
|
+
closure_arg = return_value_processor.prepare_object(
|
196
|
+
return_value: closure_arg,
|
197
|
+
return_value_type: :string # always assume string for closure error_callback
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
Thread.current[:exception] = nil
|
202
|
+
|
203
|
+
payload = {
|
204
|
+
payload: {
|
205
|
+
status: "ready_for_next",
|
206
|
+
return_object: return_object,
|
207
|
+
closure_argument_value: closure_arg
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return JSON.generate(payload)
|
211
|
+
rescue StandardError => e
|
212
|
+
Thread.current[:exception] = e
|
213
|
+
|
214
|
+
exception_array = []
|
215
|
+
exception_array << "#{e.class}:"
|
216
|
+
exception_array << e.backtrace
|
217
|
+
|
218
|
+
while e.respond_to?("cause") && (e = e.cause)
|
219
|
+
exception_array << "cause: #{e.class}"
|
220
|
+
exception_array << e.backtrace
|
221
|
+
end
|
222
|
+
|
223
|
+
payload = {
|
224
|
+
payload: {
|
225
|
+
status: "failure",
|
226
|
+
failure_information: exception_array.flatten
|
227
|
+
}
|
228
|
+
}
|
229
|
+
return JSON.generate(payload)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'pantograph/server/action_command_return.rb'
|
2
|
+
require 'pantograph/server/command_parser.rb'
|
3
|
+
require 'pantograph/server/command_executor.rb'
|
4
|
+
|
5
|
+
module Pantograph
|
6
|
+
# Handles receiving commands from the socket server, finding the Action to be invoked,
|
7
|
+
# invoking it, and returning any return values
|
8
|
+
class SocketServerActionCommandExecutor < CommandExecutor
|
9
|
+
attr_accessor :runner
|
10
|
+
attr_accessor :actions_requiring_special_handling
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
Pantograph.load_actions
|
14
|
+
@runner = Runner.new
|
15
|
+
@actions_requiring_special_handling = ["sh"].to_set
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(command: nil, target_object: nil)
|
19
|
+
action_name = command.method_name
|
20
|
+
action_class_ref = class_ref_for_action(named: action_name)
|
21
|
+
parameter_map = {}
|
22
|
+
closure_argument_value = nil
|
23
|
+
|
24
|
+
command.args.each do |arg|
|
25
|
+
arg_value = arg.value
|
26
|
+
if arg.value_type.to_s.to_sym == :string_closure
|
27
|
+
closure = proc { |string_value| closure_argument_value = string_value }
|
28
|
+
arg_value = closure
|
29
|
+
end
|
30
|
+
parameter_map[arg.name.to_sym] = arg_value
|
31
|
+
end
|
32
|
+
|
33
|
+
if @actions_requiring_special_handling.include?(action_name)
|
34
|
+
command_return = run_action_requiring_special_handling(
|
35
|
+
command: command,
|
36
|
+
parameter_map: parameter_map,
|
37
|
+
action_return_type: action_class_ref.return_type
|
38
|
+
)
|
39
|
+
return command_return
|
40
|
+
end
|
41
|
+
|
42
|
+
action_return = run(
|
43
|
+
action_named: action_name,
|
44
|
+
action_class_ref: action_class_ref,
|
45
|
+
parameter_map: parameter_map
|
46
|
+
)
|
47
|
+
|
48
|
+
command_return = ActionCommandReturn.new(
|
49
|
+
return_value: action_return,
|
50
|
+
return_value_type: action_class_ref.return_type,
|
51
|
+
closure_argument_value: closure_argument_value
|
52
|
+
)
|
53
|
+
return command_return
|
54
|
+
end
|
55
|
+
|
56
|
+
def class_ref_for_action(named: nil)
|
57
|
+
class_ref = Actions.action_class_ref(named)
|
58
|
+
unless class_ref
|
59
|
+
if Pantograph::Actions.formerly_bundled_actions.include?(action)
|
60
|
+
# This was a formerly bundled action which is now a plugin.
|
61
|
+
UI.verbose(caller.join("\n"))
|
62
|
+
UI.user_error!("The action '#{action}' is no longer bundled with pantograph. You can install it using `pantograph add_plugin #{action}`")
|
63
|
+
else
|
64
|
+
Pantograph::ActionsList.print_suggestions(action)
|
65
|
+
UI.user_error!("Action '#{action}' not available, run `pantograph actions` to get a full list")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return class_ref
|
70
|
+
end
|
71
|
+
|
72
|
+
def run(action_named: nil, action_class_ref: nil, parameter_map: nil)
|
73
|
+
action_return = runner.execute_action(action_named, action_class_ref, [parameter_map], custom_dir: '.')
|
74
|
+
return action_return
|
75
|
+
end
|
76
|
+
|
77
|
+
# Some actions have special handling in pant_file.rb, that means we can't directly call the action
|
78
|
+
# but we have to use the same logic that is in pant_file.rb instead.
|
79
|
+
# That's where this switch statement comes into play
|
80
|
+
def run_action_requiring_special_handling(command: nil, parameter_map: nil, action_return_type: nil)
|
81
|
+
action_return = nil
|
82
|
+
closure_argument_value = nil # only used if the action uses it
|
83
|
+
|
84
|
+
case command.method_name
|
85
|
+
when "sh"
|
86
|
+
error_callback = proc { |string_value| closure_argument_value = string_value }
|
87
|
+
command_param = parameter_map[:command]
|
88
|
+
log_param = parameter_map[:log]
|
89
|
+
action_return = Pantograph::PantFile.sh(command_param, log: log_param, error_callback: error_callback)
|
90
|
+
end
|
91
|
+
|
92
|
+
command_return = ActionCommandReturn.new(
|
93
|
+
return_value: action_return,
|
94
|
+
return_value_type: action_return_type,
|
95
|
+
closure_argument_value: closure_argument_value
|
96
|
+
)
|
97
|
+
|
98
|
+
return command_return
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,290 @@
|
|
1
|
+
require "tty-spinner"
|
2
|
+
|
3
|
+
module Pantograph
|
4
|
+
class Setup
|
5
|
+
# :ios or :android
|
6
|
+
attr_accessor :platform
|
7
|
+
|
8
|
+
# Path to the xcodeproj or xcworkspace
|
9
|
+
attr_accessor :project_path
|
10
|
+
|
11
|
+
# Used for :manual sometimes
|
12
|
+
attr_accessor :preferred_setup_method
|
13
|
+
|
14
|
+
# remember if there were multiple projects
|
15
|
+
# if so, we set it as part of the Pantfile
|
16
|
+
attr_accessor :had_multiple_projects_to_choose_from
|
17
|
+
|
18
|
+
# The current content of the generated Pantfile
|
19
|
+
attr_accessor :pantfile_content
|
20
|
+
|
21
|
+
# For iOS projects that's the Apple ID email
|
22
|
+
attr_accessor :user
|
23
|
+
|
24
|
+
# This is the lane that we tell the user to run to try the new pantograph setup
|
25
|
+
# This needs to be setup by each setup
|
26
|
+
attr_accessor :lane_to_mention
|
27
|
+
|
28
|
+
# Start the setup process
|
29
|
+
# rubocop:disable Metrics/BlockNesting
|
30
|
+
def self.start(user: nil)
|
31
|
+
if PantographCore::PantographFolder.setup? && !Helper.test?
|
32
|
+
require 'pantograph/lane_list'
|
33
|
+
Pantograph::LaneList.output(PantographCore::PantographFolder.pantfile_path)
|
34
|
+
UI.important("------------------")
|
35
|
+
UI.important("pantograph is already set up at path `#{PantographCore::PantographFolder.path}`, see the available lanes above")
|
36
|
+
UI.message("")
|
37
|
+
|
38
|
+
setup_ios = self.new
|
39
|
+
setup_ios.add_or_update_gemfile(update_gemfile_if_needed: false)
|
40
|
+
setup_ios.suggest_next_steps
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
# this is used by e.g. configuration.rb to not show warnings when running produce
|
45
|
+
ENV["PANTOGRAPH_ONBOARDING_IN_PROCESS"] = 1.to_s
|
46
|
+
|
47
|
+
spinner = TTY::Spinner.new("[:spinner] Looking for iOS and Android projects in current directory...", format: :dots)
|
48
|
+
spinner.auto_spin
|
49
|
+
|
50
|
+
maven_projects = Dir["**/pom.xml"]
|
51
|
+
gradle_projects = Dir["**/*.gradle"] + Dir["**/*.gradle.kts"]
|
52
|
+
|
53
|
+
spinner.success
|
54
|
+
|
55
|
+
PantographCore::PantographFolder.create_folder!
|
56
|
+
|
57
|
+
# Currently we prefer iOS app projects, as the `init` process is
|
58
|
+
# more intelligent and does more things. The user can easily add
|
59
|
+
# the `:android` platform to the resulting Pantfile
|
60
|
+
if maven_projects.count > 0
|
61
|
+
current_directory = maven_projects.find_all do |current_project_path|
|
62
|
+
current_project_path.split(File::Separator).count == 1
|
63
|
+
end
|
64
|
+
chosen_project = nil
|
65
|
+
had_multiple_projects_to_choose_from = false
|
66
|
+
|
67
|
+
if current_directory.count == 1
|
68
|
+
chosen_project = current_directory.first
|
69
|
+
elsif current_directory.count > 1
|
70
|
+
if current_directory.count == 2
|
71
|
+
# This is a common case (e.g. with CocoaPods), where the project has an xcodeproj and an xcworkspace file
|
72
|
+
extensions = [File.extname(current_directory[0]), File.extname(current_directory[1])]
|
73
|
+
if extensions.sort == [".xcodeproj", ".xcworkspace"].sort
|
74
|
+
# Yep, that's this kind of setup
|
75
|
+
chosen_project = current_directory.find { |d| d.end_with?(".xcworkspace") }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
chosen_project ||= UI.select("Multiple iOS projects found in current directory", current_directory)
|
79
|
+
had_multiple_projects_to_choose_from = true
|
80
|
+
else
|
81
|
+
UI.error("It looks like there is no iOS project in the current directory, though we did find one in a sub-directory")
|
82
|
+
UI.error("Please `cd` into the directory of the intended Xcode project you wish to use.")
|
83
|
+
UI.user_error!("Please `cd` into the directory of the intended Xcode project you wish to use and run `pantograph init` again")
|
84
|
+
end
|
85
|
+
|
86
|
+
UI.message("Detected an iOS/macOS project in the current directory: '#{chosen_project}'")
|
87
|
+
|
88
|
+
SetupIos.new(
|
89
|
+
user: user,
|
90
|
+
project_path: chosen_project,
|
91
|
+
had_multiple_projects_to_choose_from: had_multiple_projects_to_choose_from
|
92
|
+
).setup_ios
|
93
|
+
elsif gradle_projects.count > 0
|
94
|
+
UI.message("Detected an Android project in the current directory...")
|
95
|
+
SetupAndroid.new.setup_android
|
96
|
+
else
|
97
|
+
UI.error("No iOS or Android projects were found in directory '#{Dir.pwd}'")
|
98
|
+
UI.error("Make sure to `cd` into the directory containing your iOS or Android app")
|
99
|
+
if UI.confirm("Alternatively, would you like to manually setup a pantograph config in the current directory instead?")
|
100
|
+
SetupIos.new(
|
101
|
+
user: user,
|
102
|
+
project_path: chosen_project,
|
103
|
+
had_multiple_projects_to_choose_from: had_multiple_projects_to_choose_from,
|
104
|
+
preferred_setup_method: :ios_manual
|
105
|
+
).setup_ios
|
106
|
+
else
|
107
|
+
UI.user_error!("Make sure to `cd` into the directory containing your project and then use `pantograph init` again")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
# rubocop:enable Metrics/BlockNesting
|
112
|
+
|
113
|
+
def initialize(user: nil, project_path: nil, had_multiple_projects_to_choose_from: nil, preferred_setup_method: nil)
|
114
|
+
self.user = user
|
115
|
+
self.project_path = project_path
|
116
|
+
self.had_multiple_projects_to_choose_from = had_multiple_projects_to_choose_from
|
117
|
+
self.preferred_setup_method = preferred_setup_method
|
118
|
+
end
|
119
|
+
|
120
|
+
# Helpers
|
121
|
+
def welcome_to_pantograph
|
122
|
+
UI.header("Welcome to pantograph 🚀")
|
123
|
+
UI.message("pantograph can help you with all kinds of automation")
|
124
|
+
UI.message("We recommend automating one task first, and then gradually automating more over time")
|
125
|
+
end
|
126
|
+
|
127
|
+
# Append a lane to the current Pantfile template we're generating
|
128
|
+
def append_lane(lane)
|
129
|
+
lane.compact! # remove nil values
|
130
|
+
|
131
|
+
new_lines = "\n\n"
|
132
|
+
new_lines = "" unless self.pantfile_content.include?("lane :") # the first lane we don't want new lines
|
133
|
+
|
134
|
+
self.pantfile_content.gsub!("[[LANES]]", "#{new_lines} #{lane.join("\n ")}[[LANES]]")
|
135
|
+
end
|
136
|
+
|
137
|
+
def write_pantfile!
|
138
|
+
# Write the Pantfile
|
139
|
+
pantfile_file_name = "Pantfile"
|
140
|
+
|
141
|
+
pantfile_path = File.join(PantographCore::PantographFolder.path, pantfile_file_name)
|
142
|
+
self.pantfile_content.gsub!("[[LANES]]", "") # since we always keep it until writing out
|
143
|
+
File.write(pantfile_path, self.pantfile_content) # remove trailing spaces before platform ends
|
144
|
+
|
145
|
+
add_or_update_gemfile(update_gemfile_if_needed: true)
|
146
|
+
|
147
|
+
UI.header("✅ Successfully generated pantograph configuration")
|
148
|
+
UI.message("Generated Pantfile at path `#{pantfile_path}`")
|
149
|
+
UI.message("Gemfile and Gemfile.lock at path `#{gemfile_path}`")
|
150
|
+
|
151
|
+
UI.message("Please check the newly generated configuration files into git along with your project")
|
152
|
+
UI.message("This way everyone in your team can benefit from your pantograph setup")
|
153
|
+
continue_with_enter
|
154
|
+
end
|
155
|
+
|
156
|
+
def gemfile_path
|
157
|
+
"Gemfile"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Gemfile related code:
|
161
|
+
def gemfile_exists?
|
162
|
+
return File.exist?(gemfile_path)
|
163
|
+
end
|
164
|
+
|
165
|
+
def setup_gemfile!
|
166
|
+
# No Gemfile yet
|
167
|
+
gemfile_content = []
|
168
|
+
gemfile_content << "source \"https://rubygems.org\""
|
169
|
+
gemfile_content << ""
|
170
|
+
gemfile_content << 'gem "pantograph"'
|
171
|
+
gemfile_content << ""
|
172
|
+
File.write(gemfile_path, gemfile_content.join("\n"))
|
173
|
+
|
174
|
+
UI.message("Installing dependencies for you...")
|
175
|
+
PantographCore::CommandExecutor.execute(
|
176
|
+
command: "bundle update",
|
177
|
+
print_all: PantographCore::Globals.verbose?,
|
178
|
+
print_command: true,
|
179
|
+
error: proc do |error_output|
|
180
|
+
UI.error("Something went wrong when running `bundle update` for you")
|
181
|
+
UI.error("Please take a look at your Gemfile at path `#{gemfile_path}`")
|
182
|
+
UI.error("and make sure you can run `bundle update` on your machine.")
|
183
|
+
end
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
def ensure_gemfile_valid!(update_gemfile_if_needed: false)
|
188
|
+
gemfile_content = File.read(gemfile_path)
|
189
|
+
unless gemfile_content.include?("https://rubygems.org")
|
190
|
+
UI.error("You have a local Gemfile, but RubyGems isn't defined as source")
|
191
|
+
UI.error("Please update your Gemfile at path `#{gemfile_path}` to include")
|
192
|
+
UI.important("")
|
193
|
+
UI.important("source \"https://rubygems.org\"")
|
194
|
+
UI.important("")
|
195
|
+
UI.error("Update your Gemfile, and run `bundle update` afterwards")
|
196
|
+
end
|
197
|
+
|
198
|
+
unless gemfile_content.include?("pantograph")
|
199
|
+
if update_gemfile_if_needed
|
200
|
+
gemfile_content << "\n\ngem \"pantograph\""
|
201
|
+
UI.message("Adding `pantograph` to your existing Gemfile at path '#{gemfile_path}'")
|
202
|
+
|
203
|
+
File.write(gemfile_path, gemfile_content)
|
204
|
+
else
|
205
|
+
UI.error("You have a local Gemfile, but it doesn't include \"pantograph\" as a dependency")
|
206
|
+
UI.error("Please add `gem \"pantograph\"` to your Gemfile")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# This method is responsible for ensuring there is a working
|
212
|
+
# Gemfile, and that `pantograph` is defined as a dependency
|
213
|
+
# while also having `rubygems` as a gem source
|
214
|
+
def add_or_update_gemfile(update_gemfile_if_needed: false)
|
215
|
+
if gemfile_exists?
|
216
|
+
ensure_gemfile_valid!(update_gemfile_if_needed: update_gemfile_if_needed)
|
217
|
+
else
|
218
|
+
if update_gemfile_if_needed || UI.confirm("It is recommended to run pantograph with a Gemfile set up, do you want pantograph to create one for you?")
|
219
|
+
setup_gemfile!
|
220
|
+
end
|
221
|
+
end
|
222
|
+
return gemfile_path
|
223
|
+
end
|
224
|
+
|
225
|
+
def finish_up
|
226
|
+
write_pantfile!
|
227
|
+
show_analytics_note
|
228
|
+
explain_concepts
|
229
|
+
suggest_next_steps
|
230
|
+
end
|
231
|
+
|
232
|
+
def pantfile_template_content
|
233
|
+
path = "#{Pantograph::ROOT}/lib/assets/DefaultPantfileTemplate"
|
234
|
+
return File.read(path)
|
235
|
+
end
|
236
|
+
|
237
|
+
def explain_concepts
|
238
|
+
UI.header("pantograph lanes")
|
239
|
+
UI.message("pantograph uses a " + "`Pantfile`".yellow + " to store the automation configuration")
|
240
|
+
UI.message("Within that, you'll see different " + "lanes".yellow + ".")
|
241
|
+
UI.message("Each is there to automate a different task, like testing, building, or pushing new releases")
|
242
|
+
continue_with_enter
|
243
|
+
|
244
|
+
UI.header("How to customize your Pantfile")
|
245
|
+
UI.message("Use a text editor of your choice to open the newly created Pantfile and take a look")
|
246
|
+
UI.message("You can now edit the available lanes and actions to customize the setup to fit your needs")
|
247
|
+
UI.message("To get a list of all the available actions, open " + "https://johnknapprs.github.io/pantograph/".cyan)
|
248
|
+
continue_with_enter
|
249
|
+
end
|
250
|
+
|
251
|
+
def continue_with_enter
|
252
|
+
UI.input("Continue by pressing Enter ⏎")
|
253
|
+
end
|
254
|
+
|
255
|
+
def suggest_next_steps
|
256
|
+
UI.header("Where to go from here?")
|
257
|
+
if self.platform == :android
|
258
|
+
UI.message("📸 Learn more about how to automatically generate localized Google Play screenshots:")
|
259
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/android/screenshots/".cyan)
|
260
|
+
UI.message("👩✈️ Learn more about distribution to beta testing services:")
|
261
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/android/beta-deployment/".cyan)
|
262
|
+
UI.message("🚀 Learn more about how to automate the Google Play release process:")
|
263
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/android/release-deployment/".cyan)
|
264
|
+
else
|
265
|
+
UI.message("📸 Learn more about how to automatically generate localized App Store screenshots:")
|
266
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/ios/screenshots/".cyan)
|
267
|
+
UI.message("👩✈️ Learn more about distribution to beta testing services:")
|
268
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/ios/beta-deployment/".cyan)
|
269
|
+
UI.message("🚀 Learn more about how to automate the App Store release process:")
|
270
|
+
UI.message("\t\thttps://docs.pantograph.tools/getting-started/ios/appstore-deployment/".cyan)
|
271
|
+
UI.message("👩⚕️ Learn more about how to setup code signing with pantograph")
|
272
|
+
UI.message("\t\thttps://docs.pantograph.tools/codesigning/getting-started/".cyan)
|
273
|
+
end
|
274
|
+
|
275
|
+
# we crash here, so that this never happens when a new setup method is added
|
276
|
+
return if self.lane_to_mention.to_s.length == 0
|
277
|
+
UI.message("")
|
278
|
+
UI.message("To try your new pantograph setup, just enter and run")
|
279
|
+
UI.command("pantograph #{self.lane_to_mention}")
|
280
|
+
end
|
281
|
+
|
282
|
+
def show_analytics_note
|
283
|
+
UI.message("pantograph will collect the number of errors for each action to detect integration issues")
|
284
|
+
UI.message("No sensitive/private information will be uploaded, more information: " + "https://docs.pantograph.tools/#metrics".cyan)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
require 'pantograph/setup/setup_ios'
|
290
|
+
require 'pantograph/setup/setup_android'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class SetupAndroid < Setup
|
3
|
+
attr_accessor :json_key_file
|
4
|
+
attr_accessor :package_name
|
5
|
+
|
6
|
+
def setup_android
|
7
|
+
self.platform = :android
|
8
|
+
|
9
|
+
welcome_to_pantograph
|
10
|
+
|
11
|
+
self.pantfile_content = pantfile_template_content
|
12
|
+
|
13
|
+
fetch_information_for_appfile
|
14
|
+
|
15
|
+
PantographCore::PantographFolder.create_folder!
|
16
|
+
|
17
|
+
self.append_lane([
|
18
|
+
"desc \"Runs all the tests\"",
|
19
|
+
"lane :test do",
|
20
|
+
" gradle(task: \"test\")",
|
21
|
+
"end"
|
22
|
+
])
|
23
|
+
|
24
|
+
self.append_lane([
|
25
|
+
"desc \"Submit a new Beta Build to Crashlytics Beta\"",
|
26
|
+
"lane :beta do",
|
27
|
+
" gradle(task: \"clean assembleRelease\")",
|
28
|
+
" crashlytics",
|
29
|
+
"",
|
30
|
+
" # sh \"your_script.sh\"",
|
31
|
+
" # You can also use other beta testing services here",
|
32
|
+
"end"
|
33
|
+
])
|
34
|
+
|
35
|
+
self.append_lane([
|
36
|
+
"desc \"Deploy a new version to the Google Play\"",
|
37
|
+
"lane :deploy do",
|
38
|
+
" gradle(task: \"clean assembleRelease\")",
|
39
|
+
" upload_to_play_store",
|
40
|
+
"end"
|
41
|
+
])
|
42
|
+
|
43
|
+
self.lane_to_mention = "test"
|
44
|
+
|
45
|
+
finish_up
|
46
|
+
end
|
47
|
+
|
48
|
+
def fetch_information_for_appfile
|
49
|
+
UI.message('')
|
50
|
+
UI.message("To avoid re-entering your package name and issuer every time you run pantograph, we'll store those in a so-called Appfile.")
|
51
|
+
|
52
|
+
self.package_name = UI.input("Package Name (com.krausefx.app): ")
|
53
|
+
puts("")
|
54
|
+
puts("To automatically upload builds and metadata to Google Play, pantograph needs a service account json secret file".yellow)
|
55
|
+
puts("Feel free to press Enter at any time in order to skip providing pieces of information when asked")
|
56
|
+
end
|
57
|
+
|
58
|
+
def finish_up
|
59
|
+
self.pantfile_content.gsub!(":ios", ":android")
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|