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,377 @@
|
|
1
|
+
require 'rubygems/requirement'
|
2
|
+
|
3
|
+
module Pantograph
|
4
|
+
class PantFile
|
5
|
+
# Stores all relevant information from the currently running process
|
6
|
+
attr_accessor :runner
|
7
|
+
|
8
|
+
# the platform in which we're currently in when parsing the Pantfile
|
9
|
+
# This is used to identify the platform in which the lane is in
|
10
|
+
attr_accessor :current_platform
|
11
|
+
|
12
|
+
SharedValues = Pantograph::Actions::SharedValues
|
13
|
+
|
14
|
+
# @return The runner which can be executed to trigger the given actions
|
15
|
+
def initialize(path = nil)
|
16
|
+
return unless (path || '').length > 0
|
17
|
+
UI.user_error!("Could not find Pantfile at path '#{path}'") unless File.exist?(path)
|
18
|
+
@path = File.expand_path(path)
|
19
|
+
content = File.read(path, encoding: "utf-8")
|
20
|
+
|
21
|
+
# From https://github.com/orta/danger/blob/master/lib/danger/Dangerfile.rb
|
22
|
+
if content.tr!('“”‘’‛', %(""'''))
|
23
|
+
UI.error("Your #{File.basename(path)} has had smart quotes sanitised. " \
|
24
|
+
'To avoid issues in the future, you should not use ' \
|
25
|
+
'TextEdit for editing it. If you are not using TextEdit, ' \
|
26
|
+
'you should turn off smart quotes in your editor of choice.')
|
27
|
+
end
|
28
|
+
|
29
|
+
content.scan(/^\s*require ["'](.*?)["']/).each do |current|
|
30
|
+
gem_name = current.last
|
31
|
+
next if gem_name.include?(".") # these are local gems
|
32
|
+
|
33
|
+
begin
|
34
|
+
require(gem_name)
|
35
|
+
rescue LoadError
|
36
|
+
UI.important("You have required a gem, if this is a third party gem, please use `pantograph_require '#{gem_name}'` to ensure the gem is installed locally.")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
parse(content, @path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def parsing_binding
|
44
|
+
binding
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse(data, path = nil)
|
48
|
+
@runner ||= Runner.new
|
49
|
+
|
50
|
+
Dir.chdir(PantographCore::PantographFolder.path || Dir.pwd) do # context: pantograph subfolder
|
51
|
+
# create nice path that we want to print in case of some problem
|
52
|
+
relative_path = path.nil? ? '(eval)' : Pathname.new(path).relative_path_from(Pathname.new(Dir.pwd)).to_s
|
53
|
+
|
54
|
+
begin
|
55
|
+
# We have to use #get_binding method, because some test files defines method called `path` (for example SwitcherPantfile)
|
56
|
+
# and local variable has higher priority, so it causes to remove content of original Pantfile for example. With #get_binding
|
57
|
+
# is this always clear and safe to declare any local variables we want, because the eval function uses the instance scope
|
58
|
+
# instead of local.
|
59
|
+
|
60
|
+
# rubocop:disable Security/Eval
|
61
|
+
eval(data, parsing_binding, relative_path) # using eval is ok for this case
|
62
|
+
# rubocop:enable Security/Eval
|
63
|
+
rescue SyntaxError => ex
|
64
|
+
match = ex.to_s.match(/#{Regexp.escape(relative_path)}:(\d+)/)
|
65
|
+
if match
|
66
|
+
line = match[1]
|
67
|
+
UI.content_error(data, line)
|
68
|
+
UI.user_error!("Syntax error in your Pantfile on line #{line}: #{ex}")
|
69
|
+
else
|
70
|
+
UI.user_error!("Syntax error in your Pantfile: #{ex}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
#####################################################
|
79
|
+
# @!group DSL
|
80
|
+
#####################################################
|
81
|
+
|
82
|
+
# User defines a new lane
|
83
|
+
def lane(lane_name, &block)
|
84
|
+
UI.user_error!("You have to pass a block using 'do' for lane '#{lane_name}'. Make sure you read the docs on GitHub.") unless block
|
85
|
+
|
86
|
+
self.runner.add_lane(Lane.new(platform: self.current_platform,
|
87
|
+
block: block,
|
88
|
+
description: desc_collection,
|
89
|
+
name: lane_name,
|
90
|
+
is_private: false))
|
91
|
+
|
92
|
+
@desc_collection = nil # reset the collected description again for the next lane
|
93
|
+
end
|
94
|
+
|
95
|
+
# User defines a new private lane, which can't be called from the CLI
|
96
|
+
def private_lane(lane_name, &block)
|
97
|
+
UI.user_error!("You have to pass a block using 'do' for lane '#{lane_name}'. Make sure you read the docs on GitHub.") unless block
|
98
|
+
|
99
|
+
self.runner.add_lane(Lane.new(platform: self.current_platform,
|
100
|
+
block: block,
|
101
|
+
description: desc_collection,
|
102
|
+
name: lane_name,
|
103
|
+
is_private: true))
|
104
|
+
|
105
|
+
@desc_collection = nil # reset the collected description again for the next lane
|
106
|
+
end
|
107
|
+
|
108
|
+
# User defines a lane that can overwrite existing lanes. Useful when importing a Pantfile
|
109
|
+
def override_lane(lane_name, &block)
|
110
|
+
UI.user_error!("You have to pass a block using 'do' for lane '#{lane_name}'. Make sure you read the docs on GitHub.") unless block
|
111
|
+
|
112
|
+
self.runner.add_lane(Lane.new(platform: self.current_platform,
|
113
|
+
block: block,
|
114
|
+
description: desc_collection,
|
115
|
+
name: lane_name,
|
116
|
+
is_private: false), true)
|
117
|
+
|
118
|
+
@desc_collection = nil # reset the collected description again for the next lane
|
119
|
+
end
|
120
|
+
|
121
|
+
# User defines a platform block
|
122
|
+
def platform(platform_name)
|
123
|
+
SupportedPlatforms.verify!(platform_name)
|
124
|
+
|
125
|
+
self.current_platform = platform_name
|
126
|
+
|
127
|
+
yield
|
128
|
+
|
129
|
+
self.current_platform = nil
|
130
|
+
end
|
131
|
+
|
132
|
+
# Is executed before each test run
|
133
|
+
def before_all(&block)
|
134
|
+
@runner.set_before_all(@current_platform, block)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Is executed before each lane
|
138
|
+
def before_each(&block)
|
139
|
+
@runner.set_before_each(@current_platform, block)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Is executed after each test run
|
143
|
+
def after_all(&block)
|
144
|
+
@runner.set_after_all(@current_platform, block)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Is executed before each lane
|
148
|
+
def after_each(&block)
|
149
|
+
@runner.set_after_each(@current_platform, block)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Is executed if an error occurred during pantograph execution
|
153
|
+
def error(&block)
|
154
|
+
@runner.set_error(@current_platform, block)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Is used to look if the method is implemented as an action
|
158
|
+
def method_missing(method_sym, *arguments, &_block)
|
159
|
+
self.runner.trigger_action_by_name(method_sym, nil, false, *arguments)
|
160
|
+
end
|
161
|
+
|
162
|
+
#####################################################
|
163
|
+
# @!group Other things
|
164
|
+
#####################################################
|
165
|
+
|
166
|
+
# Is the given key a platform block or a lane?
|
167
|
+
def is_platform_block?(key)
|
168
|
+
UI.crash!('No key given') unless key
|
169
|
+
|
170
|
+
return false if self.runner.lanes.fetch(nil, {}).fetch(key.to_sym, nil)
|
171
|
+
return true if self.runner.lanes[key.to_sym].kind_of?(Hash)
|
172
|
+
|
173
|
+
if key.to_sym == :update
|
174
|
+
# The user ran `pantograph update`, instead of `pantograph update_pantograph`
|
175
|
+
# We're gonna be nice and understand what the user is trying to do
|
176
|
+
require 'pantograph/one_off'
|
177
|
+
Pantograph::OneOff.run(action: "update_pantograph", parameters: {})
|
178
|
+
else
|
179
|
+
UI.user_error!("Could not find '#{key}'. Available lanes: #{self.runner.available_lanes.join(', ')}")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def actions_path(path)
|
184
|
+
UI.crash!("Path '#{path}' not found!") unless File.directory?(path)
|
185
|
+
|
186
|
+
Actions.load_external_actions(path)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Execute shell command
|
190
|
+
# Accepts arguments with with and without the command named keyword so that sh
|
191
|
+
# behaves like other actions with named keywords
|
192
|
+
# https://github.com/pantograph/pantograph/issues/14930
|
193
|
+
#
|
194
|
+
# Example:
|
195
|
+
# sh("ls")
|
196
|
+
# sh("ls", log: false)
|
197
|
+
# sh(command: "ls")
|
198
|
+
# sh(command: "ls", log: false)
|
199
|
+
def sh(*args, &b)
|
200
|
+
# First accepts hash (or named keywords) like other actions
|
201
|
+
# Otherwise uses sh method that doesn't have an interface like an action
|
202
|
+
if args.count == 1 && args.first.kind_of?(Hash)
|
203
|
+
hash = args.first
|
204
|
+
command = hash.delete(:command)
|
205
|
+
|
206
|
+
raise ArgumentError, "sh requires :command keyword in argument" if command.nil?
|
207
|
+
|
208
|
+
new_args = [*command, hash]
|
209
|
+
PantFile.sh(*new_args, &b)
|
210
|
+
else
|
211
|
+
PantFile.sh(*args, &b)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.sh(*command, log: true, error_callback: nil, &b)
|
216
|
+
command_header = log ? Actions.shell_command_from_args(*command) : "shell command"
|
217
|
+
Actions.execute_action(command_header) do
|
218
|
+
Actions.sh_no_action(*command, log: log, error_callback: error_callback, &b)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def desc(string)
|
223
|
+
desc_collection << string
|
224
|
+
end
|
225
|
+
|
226
|
+
def desc_collection
|
227
|
+
@desc_collection ||= []
|
228
|
+
end
|
229
|
+
|
230
|
+
def pantograph_require(gem_name)
|
231
|
+
PantographRequire.install_gem_if_needed(gem_name: gem_name, require_gem: true)
|
232
|
+
end
|
233
|
+
|
234
|
+
def generated_pantfile_id(id)
|
235
|
+
UI.important("The `generated_pantfile_id` action was deprecated, you can remove the line from your `Pantfile`")
|
236
|
+
end
|
237
|
+
|
238
|
+
def import(path = nil)
|
239
|
+
UI.user_error!("Please pass a path to the `import` action") unless path
|
240
|
+
|
241
|
+
path = path.dup.gsub("~", Dir.home)
|
242
|
+
unless Pathname.new(path).absolute? # unless an absolute path
|
243
|
+
path = File.join(File.expand_path('..', @path), path)
|
244
|
+
end
|
245
|
+
|
246
|
+
UI.user_error!("Could not find Pantfile at path '#{path}'") unless File.exist?(path)
|
247
|
+
|
248
|
+
# First check if there are local actions to import in the same directory as the Pantfile
|
249
|
+
actions_path = File.join(File.expand_path("..", path), 'actions')
|
250
|
+
Pantograph::Actions.load_external_actions(actions_path) if File.directory?(actions_path)
|
251
|
+
|
252
|
+
action_launched('import')
|
253
|
+
|
254
|
+
return_value = parse(File.read(path), path)
|
255
|
+
|
256
|
+
action_completed('import', status: PantographCore::ActionCompletionStatus::SUCCESS)
|
257
|
+
|
258
|
+
return return_value
|
259
|
+
end
|
260
|
+
|
261
|
+
# @param url [String] The git URL to clone the repository from
|
262
|
+
# @param branch [String] The branch to checkout in the repository
|
263
|
+
# @param path [String] The path to the Pantfile
|
264
|
+
# @param version [String, Array] Version requirement for repo tags
|
265
|
+
def import_from_git(url: nil, branch: 'HEAD', path: 'pantograph/Pantfile', version: nil)
|
266
|
+
UI.user_error!("Please pass a path to the `import_from_git` action") if url.to_s.length == 0
|
267
|
+
|
268
|
+
Actions.execute_action('import_from_git') do
|
269
|
+
require 'tmpdir'
|
270
|
+
|
271
|
+
action_launched('import_from_git')
|
272
|
+
|
273
|
+
# Checkout the repo
|
274
|
+
repo_name = url.split("/").last
|
275
|
+
checkout_param = branch
|
276
|
+
|
277
|
+
Dir.mktmpdir("fl_clone") do |tmp_path|
|
278
|
+
clone_folder = File.join(tmp_path, repo_name)
|
279
|
+
|
280
|
+
branch_option = "--branch #{branch}" if branch != 'HEAD'
|
281
|
+
|
282
|
+
UI.message("Cloning remote git repo...")
|
283
|
+
Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
|
284
|
+
Actions.sh("git clone #{url.shellescape} #{clone_folder.shellescape} --depth 1 -n #{branch_option}")
|
285
|
+
end
|
286
|
+
|
287
|
+
unless version.nil?
|
288
|
+
req = Gem::Requirement.new(version)
|
289
|
+
all_tags = fetch_remote_tags(folder: clone_folder)
|
290
|
+
checkout_param = all_tags.select { |t| req =~ PantographCore::TagVersion.new(t) }.last
|
291
|
+
UI.user_error!("No tag found matching #{version.inspect}") if checkout_param.nil?
|
292
|
+
end
|
293
|
+
|
294
|
+
Actions.sh("cd #{clone_folder.shellescape} && git checkout #{checkout_param.shellescape} #{path.shellescape}")
|
295
|
+
|
296
|
+
# We also want to check out all the local actions of this pantograph setup
|
297
|
+
containing = path.split(File::SEPARATOR)[0..-2]
|
298
|
+
containing = "." if containing.count == 0
|
299
|
+
actions_folder = File.join(containing, "actions")
|
300
|
+
begin
|
301
|
+
Actions.sh("cd #{clone_folder.shellescape} && git checkout #{checkout_param.shellescape} #{actions_folder.shellescape}")
|
302
|
+
rescue
|
303
|
+
# We don't care about a failure here, as local actions are optional
|
304
|
+
end
|
305
|
+
|
306
|
+
return_value = import(File.join(clone_folder, path))
|
307
|
+
|
308
|
+
action_completed('import_from_git', status: PantographCore::ActionCompletionStatus::SUCCESS)
|
309
|
+
|
310
|
+
return return_value
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
#####################################################
|
316
|
+
# @!group Versioning helpers
|
317
|
+
#####################################################
|
318
|
+
|
319
|
+
def fetch_remote_tags(folder: nil)
|
320
|
+
UI.message("Fetching remote git tags...")
|
321
|
+
Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
|
322
|
+
Actions.sh("cd #{folder.shellescape} && git fetch --all --tags -q")
|
323
|
+
end
|
324
|
+
|
325
|
+
# Fetch all possible tags
|
326
|
+
git_tags_string = Actions.sh("cd #{folder.shellescape} && git tag -l")
|
327
|
+
git_tags = git_tags_string.split("\n")
|
328
|
+
|
329
|
+
# Sort tags based on their version number
|
330
|
+
return git_tags
|
331
|
+
.select { |tag| PantographCore::TagVersion.correct?(tag) }
|
332
|
+
.sort_by { |tag| PantographCore::TagVersion.new(tag) }
|
333
|
+
end
|
334
|
+
|
335
|
+
#####################################################
|
336
|
+
# @!group Overwriting Ruby methods
|
337
|
+
#####################################################
|
338
|
+
|
339
|
+
# Speak out loud
|
340
|
+
def say(value)
|
341
|
+
# Overwrite this, since there is already a 'say' method defined in the Ruby standard library
|
342
|
+
value ||= yield
|
343
|
+
|
344
|
+
value = { text: value } if value.kind_of?(String) || value.kind_of?(Array)
|
345
|
+
self.runner.trigger_action_by_name(:say, nil, false, value)
|
346
|
+
end
|
347
|
+
|
348
|
+
def puts(value)
|
349
|
+
# Overwrite this, since there is already a 'puts' method defined in the Ruby standard library
|
350
|
+
value ||= yield if block_given?
|
351
|
+
|
352
|
+
action_launched('puts')
|
353
|
+
return_value = Pantograph::Actions::PutsAction.run([value])
|
354
|
+
action_completed('puts', status: PantographCore::ActionCompletionStatus::SUCCESS)
|
355
|
+
return return_value
|
356
|
+
end
|
357
|
+
|
358
|
+
def test(params = {})
|
359
|
+
# Overwrite this, since there is already a 'test' method defined in the Ruby standard library
|
360
|
+
self.runner.try_switch_to_lane(:test, [params])
|
361
|
+
end
|
362
|
+
|
363
|
+
def action_launched(action_name)
|
364
|
+
action_launch_context = PantographCore::ActionLaunchContext.context_for_action_name(action_name,
|
365
|
+
pantograph_client_language: :ruby,
|
366
|
+
args: ARGV)
|
367
|
+
PantographCore.session.action_launched(launch_context: action_launch_context)
|
368
|
+
end
|
369
|
+
|
370
|
+
def action_completed(action_name, status: nil)
|
371
|
+
completion_context = PantographCore::ActionCompletionContext.context_for_action_name(action_name,
|
372
|
+
args: ARGV,
|
373
|
+
status: status)
|
374
|
+
PantographCore.session.action_completed(completion_context: completion_context)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class PantographRequire
|
3
|
+
class << self
|
4
|
+
def install_gem_if_needed(gem_name: nil, require_gem: true)
|
5
|
+
gem_require_name = format_gem_require_name(gem_name)
|
6
|
+
|
7
|
+
# check if it's installed
|
8
|
+
if gem_installed?(gem_name)
|
9
|
+
UI.success("gem '#{gem_name}' is already installed") if PantographCore::Globals.verbose?
|
10
|
+
require gem_require_name if require_gem
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
|
14
|
+
if Helper.bundler?
|
15
|
+
# User uses bundler, we don't want to install gems on the fly here
|
16
|
+
# Instead tell the user how to add it to their Gemfile
|
17
|
+
UI.important("Missing gem '#{gem_name}', please add the following to your local Gemfile:")
|
18
|
+
UI.important("")
|
19
|
+
UI.command_output("gem \"#{gem_name}\"")
|
20
|
+
UI.important("")
|
21
|
+
UI.user_error!("Add 'gem \"#{gem_name}\"' to your Gemfile and restart pantograph") unless Helper.test?
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems/command_manager"
|
25
|
+
installer = Gem::CommandManager.instance[:install]
|
26
|
+
|
27
|
+
UI.important("Installing Ruby gem '#{gem_name}'...")
|
28
|
+
|
29
|
+
spec_name = self.find_gem_name(gem_name)
|
30
|
+
UI.important("Found gem \"#{spec_name}\" instead of the required name \"#{gem_name}\"") if spec_name != gem_name
|
31
|
+
|
32
|
+
return if Helper.test?
|
33
|
+
|
34
|
+
# We install the gem like this because we also want to gem to be available to be required
|
35
|
+
# at this point. If we were to shell out, this wouldn't be the case
|
36
|
+
installer.install_gem(spec_name, Gem::Requirement.default)
|
37
|
+
UI.success("Successfully installed '#{gem_name}'")
|
38
|
+
require gem_require_name if require_gem
|
39
|
+
end
|
40
|
+
|
41
|
+
def gem_installed?(name, req = Gem::Requirement.default)
|
42
|
+
installed = Gem::Specification.any? { |s| s.name == name and req =~ s.version }
|
43
|
+
return true if installed
|
44
|
+
|
45
|
+
# In special cases a gem is already preinstalled, e.g. YAML.
|
46
|
+
# To find out we try to load a gem with that name in a child process
|
47
|
+
# (so we don't actually load anything we don't want to load)
|
48
|
+
# See https://github.com/pantograph/pantograph/issues/6951
|
49
|
+
require_tester = <<-RB.gsub(/^ */, '')
|
50
|
+
begin
|
51
|
+
require ARGV.first
|
52
|
+
rescue LoadError
|
53
|
+
exit(1)
|
54
|
+
end
|
55
|
+
RB
|
56
|
+
system(RbConfig.ruby, "-e", require_tester.lines.map(&:chomp).join("; "), name)
|
57
|
+
return $?.success?
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_gem_name(user_supplied_name)
|
61
|
+
fetcher = Gem::SpecFetcher.fetcher
|
62
|
+
gems = fetcher.suggest_gems_from_name(user_supplied_name)
|
63
|
+
|
64
|
+
return gems.first
|
65
|
+
end
|
66
|
+
|
67
|
+
def format_gem_require_name(gem_name)
|
68
|
+
# from "pantograph-plugin-xcversion" to "pantograph/plugin/xcversion"
|
69
|
+
gem_name = gem_name.tr("-", "/") if gem_name.start_with?("pantograph-plugin-")
|
70
|
+
|
71
|
+
return gem_name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Pantograph
|
2
|
+
# Use the RubyGems API to get all pantograph plugins
|
3
|
+
class PluginFetcher
|
4
|
+
require 'pantograph_core'
|
5
|
+
require 'pantograph/plugins/plugin_manager'
|
6
|
+
|
7
|
+
# Returns an array of PantographPlugin objects
|
8
|
+
def self.fetch_gems(search_query: nil)
|
9
|
+
require 'json'
|
10
|
+
require 'open-uri'
|
11
|
+
|
12
|
+
page = 1
|
13
|
+
plugins = []
|
14
|
+
loop do
|
15
|
+
url = "https://rubygems.org/api/v1/search.json?query=#{PluginManager.plugin_prefix}&page=#{page}"
|
16
|
+
PantographCore::UI.verbose("RubyGems API Request: #{url}")
|
17
|
+
results = JSON.parse(open(url).read)
|
18
|
+
break if results.count == 0
|
19
|
+
|
20
|
+
plugins += results.collect do |current|
|
21
|
+
PantographPlugin.new(current)
|
22
|
+
end
|
23
|
+
page += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
return plugins if search_query.to_s.length == 0
|
27
|
+
plugins.keep_if do |current|
|
28
|
+
current.full_name.include?(search_query) or current.info.include?(search_query)
|
29
|
+
end
|
30
|
+
|
31
|
+
return plugins
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class PantographPlugin
|
36
|
+
attr_accessor :full_name
|
37
|
+
attr_accessor :name
|
38
|
+
attr_accessor :downloads
|
39
|
+
attr_accessor :info
|
40
|
+
attr_accessor :homepage
|
41
|
+
|
42
|
+
def initialize(hash)
|
43
|
+
self.full_name = hash["name"]
|
44
|
+
self.name = self.full_name.gsub(PluginManager.plugin_prefix, '')
|
45
|
+
self.downloads = hash["downloads"]
|
46
|
+
self.info = hash["info"]
|
47
|
+
self.homepage = hash["homepage_uri"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def linked_title
|
51
|
+
return "`#{name}`" if homepage.to_s.length == 0
|
52
|
+
return "[#{name}](#{homepage})"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Pantograph
|
2
|
+
# Generates a sample plugin by traversing a template directory structure
|
3
|
+
# and reproducing it in a destination location. At the same time, it runs
|
4
|
+
# variable replacements on directory names, file names, and runs ERB
|
5
|
+
# templating on file contents whose names end with '.erb'.
|
6
|
+
#
|
7
|
+
# Directory and file name variable replacements are defined like: %gem_name%
|
8
|
+
# The text between the percent signs will be used to invoke an accessor
|
9
|
+
# method on the PluginInfo object to get the replacement value.
|
10
|
+
class PluginGenerator
|
11
|
+
def initialize(ui: PluginGeneratorUI.new,
|
12
|
+
info_collector: PluginInfoCollector.new(ui),
|
13
|
+
template_root: File.join(File.dirname(__FILE__), 'template'),
|
14
|
+
dest_root: FileUtils.pwd)
|
15
|
+
@ui = ui
|
16
|
+
@info_collector = info_collector
|
17
|
+
@template_root = template_root
|
18
|
+
@dest_root = dest_root
|
19
|
+
end
|
20
|
+
|
21
|
+
# entry point
|
22
|
+
def generate(plugin_name = nil)
|
23
|
+
plugin_info = @info_collector.collect_info(plugin_name)
|
24
|
+
|
25
|
+
# Traverse all the files and directories in the template root,
|
26
|
+
# handling each in turn
|
27
|
+
Find.find(@template_root) do |template_path|
|
28
|
+
handle_template_path(template_path, plugin_info)
|
29
|
+
end
|
30
|
+
|
31
|
+
@ui.success("\nYour plugin was successfully generated at #{plugin_info.gem_name}/ 🚀")
|
32
|
+
@ui.success("\nTo get started with using this plugin, run")
|
33
|
+
@ui.message("\n pantograph add_plugin #{plugin_info.plugin_name}\n")
|
34
|
+
@ui.success("\nfrom a pantograph-enabled app project directory and provide the following as the path:")
|
35
|
+
@ui.message("\n #{File.expand_path(plugin_info.gem_name)}\n\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_template_path(template_path, plugin_info)
|
39
|
+
dest_path = derive_dest_path(template_path, plugin_info)
|
40
|
+
|
41
|
+
if File.directory?(template_path)
|
42
|
+
FileUtils.mkdir_p(dest_path)
|
43
|
+
else
|
44
|
+
copy_file(template_path, dest_path, plugin_info)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def derive_dest_path(template_path, plugin_info)
|
49
|
+
relative_template_path = template_path.gsub(@template_root, '')
|
50
|
+
replaced_path = replace_path_variables(relative_template_path, plugin_info)
|
51
|
+
|
52
|
+
File.join(@dest_root, plugin_info.gem_name, replaced_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def copy_file(template_path, dest_path, plugin_info)
|
56
|
+
contents = File.read(template_path)
|
57
|
+
|
58
|
+
if dest_path.end_with?('.erb')
|
59
|
+
contents = ERB.new(contents).result(plugin_info.get_binding)
|
60
|
+
dest_path = dest_path[0...-4] # Remove the .erb suffix
|
61
|
+
end
|
62
|
+
|
63
|
+
File.write(dest_path, contents)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Path variables can be defined like: %gem_name%
|
67
|
+
#
|
68
|
+
# The text between the percent signs will be used to invoke an accessor
|
69
|
+
# method on the PluginInfo object to be the replacement value.
|
70
|
+
def replace_path_variables(template_path, plugin_info)
|
71
|
+
path = template_path.dup
|
72
|
+
|
73
|
+
loop do
|
74
|
+
replacement_variable_regexp = /%([\w\-]*)%/
|
75
|
+
match = replacement_variable_regexp.match(path)
|
76
|
+
|
77
|
+
break unless match
|
78
|
+
|
79
|
+
replacement_value = plugin_info.send(match[1].to_sym)
|
80
|
+
path.gsub!(replacement_variable_regexp, replacement_value)
|
81
|
+
end
|
82
|
+
|
83
|
+
path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Pantograph
|
2
|
+
class PluginInfo
|
3
|
+
attr_reader :plugin_name
|
4
|
+
attr_reader :author
|
5
|
+
attr_reader :gem_name
|
6
|
+
attr_reader :email
|
7
|
+
attr_reader :summary
|
8
|
+
attr_reader :details
|
9
|
+
|
10
|
+
def initialize(plugin_name, author, email, summary, details)
|
11
|
+
@plugin_name = plugin_name
|
12
|
+
@author = author
|
13
|
+
@email = email
|
14
|
+
@summary = summary
|
15
|
+
@details = details
|
16
|
+
end
|
17
|
+
|
18
|
+
def gem_name
|
19
|
+
"#{Pantograph::PluginManager::PANTOGRAPH_PLUGIN_PREFIX}#{plugin_name}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def require_path
|
23
|
+
gem_name.tr('-', '/')
|
24
|
+
end
|
25
|
+
|
26
|
+
def actions_path
|
27
|
+
File.join(require_path, 'actions')
|
28
|
+
end
|
29
|
+
|
30
|
+
def helper_path
|
31
|
+
File.join(require_path, 'helper')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Used to expose a local binding for use in ERB templating
|
35
|
+
#
|
36
|
+
# rubocop:disable Style/AccessorMethodName
|
37
|
+
def get_binding
|
38
|
+
binding
|
39
|
+
end
|
40
|
+
# rubocop:enable Style/AccessorMethodName
|
41
|
+
|
42
|
+
def ==(other)
|
43
|
+
@plugin_name == other.plugin_name &&
|
44
|
+
@author == other.author &&
|
45
|
+
@email == other.email &&
|
46
|
+
@summary == other.summary
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|