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.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -0
  3. data/LICENSE +21 -0
  4. data/README.md +197 -0
  5. data/bin/bin-proxy +19 -0
  6. data/bin/pantograph +23 -0
  7. data/pantograph/README.md +11 -0
  8. data/pantograph/lib/assets/ActionDetails.md.erb +106 -0
  9. data/pantograph/lib/assets/Actions.md.erb +43 -0
  10. data/pantograph/lib/assets/DefaultPantfileTemplate +20 -0
  11. data/pantograph/lib/assets/completions/completion.bash +23 -0
  12. data/pantograph/lib/assets/completions/completion.fish +39 -0
  13. data/pantograph/lib/assets/completions/completion.sh +12 -0
  14. data/pantograph/lib/assets/completions/completion.zsh +23 -0
  15. data/pantograph/lib/assets/custom_action_template.rb +80 -0
  16. data/pantograph/lib/assets/report_template.xml.erb +15 -0
  17. data/pantograph/lib/pantograph/action.rb +194 -0
  18. data/pantograph/lib/pantograph/action_collector.rb +35 -0
  19. data/pantograph/lib/pantograph/actions/README.md +3 -0
  20. data/pantograph/lib/pantograph/actions/actions_helper.rb +166 -0
  21. data/pantograph/lib/pantograph/actions/add_extra_platforms.rb +45 -0
  22. data/pantograph/lib/pantograph/actions/artifactory.rb +157 -0
  23. data/pantograph/lib/pantograph/actions/bundle_install.rb +156 -0
  24. data/pantograph/lib/pantograph/actions/changelog_from_git_commits.rb +197 -0
  25. data/pantograph/lib/pantograph/actions/clipboard.rb +52 -0
  26. data/pantograph/lib/pantograph/actions/cloc.rb +89 -0
  27. data/pantograph/lib/pantograph/actions/create_pull_request.rb +190 -0
  28. data/pantograph/lib/pantograph/actions/danger.rb +131 -0
  29. data/pantograph/lib/pantograph/actions/debug.rb +32 -0
  30. data/pantograph/lib/pantograph/actions/default_platform.rb +47 -0
  31. data/pantograph/lib/pantograph/actions/download.rb +76 -0
  32. data/pantograph/lib/pantograph/actions/echo.rb +14 -0
  33. data/pantograph/lib/pantograph/actions/ensure_bundle_exec.rb +59 -0
  34. data/pantograph/lib/pantograph/actions/ensure_env_vars.rb +58 -0
  35. data/pantograph/lib/pantograph/actions/ensure_git_branch.rb +69 -0
  36. data/pantograph/lib/pantograph/actions/ensure_git_status_clean.rb +81 -0
  37. data/pantograph/lib/pantograph/actions/erb.rb +88 -0
  38. data/pantograph/lib/pantograph/actions/get_build_number_repository.rb +120 -0
  39. data/pantograph/lib/pantograph/actions/get_github_release.rb +163 -0
  40. data/pantograph/lib/pantograph/actions/git_add.rb +93 -0
  41. data/pantograph/lib/pantograph/actions/git_branch.rb +58 -0
  42. data/pantograph/lib/pantograph/actions/git_commit.rb +80 -0
  43. data/pantograph/lib/pantograph/actions/git_pull.rb +53 -0
  44. data/pantograph/lib/pantograph/actions/git_submodule_update.rb +52 -0
  45. data/pantograph/lib/pantograph/actions/git_tag_exists.rb +74 -0
  46. data/pantograph/lib/pantograph/actions/github_api.rb +262 -0
  47. data/pantograph/lib/pantograph/actions/gradle.rb +278 -0
  48. data/pantograph/lib/pantograph/actions/import.rb +49 -0
  49. data/pantograph/lib/pantograph/actions/import_from_git.rb +71 -0
  50. data/pantograph/lib/pantograph/actions/is_ci.rb +51 -0
  51. data/pantograph/lib/pantograph/actions/jira.rb +115 -0
  52. data/pantograph/lib/pantograph/actions/lane_context.rb +60 -0
  53. data/pantograph/lib/pantograph/actions/last_git_commit.rb +58 -0
  54. data/pantograph/lib/pantograph/actions/last_git_tag.rb +51 -0
  55. data/pantograph/lib/pantograph/actions/make_changelog_from_jenkins.rb +81 -0
  56. data/pantograph/lib/pantograph/actions/min_pantograph_version.rb +57 -0
  57. data/pantograph/lib/pantograph/actions/nexus_upload.rb +230 -0
  58. data/pantograph/lib/pantograph/actions/notification.rb +75 -0
  59. data/pantograph/lib/pantograph/actions/number_of_commits.rb +75 -0
  60. data/pantograph/lib/pantograph/actions/opt_out_usage.rb +40 -0
  61. data/pantograph/lib/pantograph/actions/pantograph_version.rb +15 -0
  62. data/pantograph/lib/pantograph/actions/println.rb +14 -0
  63. data/pantograph/lib/pantograph/actions/prompt.rb +119 -0
  64. data/pantograph/lib/pantograph/actions/push_git_tags.rb +76 -0
  65. data/pantograph/lib/pantograph/actions/push_to_git_remote.rb +127 -0
  66. data/pantograph/lib/pantograph/actions/puts.rb +68 -0
  67. data/pantograph/lib/pantograph/actions/reset_git_repo.rb +121 -0
  68. data/pantograph/lib/pantograph/actions/rocket.rb +83 -0
  69. data/pantograph/lib/pantograph/actions/rsync.rb +74 -0
  70. data/pantograph/lib/pantograph/actions/ruby_version.rb +56 -0
  71. data/pantograph/lib/pantograph/actions/say.rb +56 -0
  72. data/pantograph/lib/pantograph/actions/scp.rb +114 -0
  73. data/pantograph/lib/pantograph/actions/set_github_release.rb +274 -0
  74. data/pantograph/lib/pantograph/actions/sh.rb +71 -0
  75. data/pantograph/lib/pantograph/actions/skip_docs.rb +52 -0
  76. data/pantograph/lib/pantograph/actions/slack.rb +288 -0
  77. data/pantograph/lib/pantograph/actions/sonar.rb +156 -0
  78. data/pantograph/lib/pantograph/actions/ssh.rb +162 -0
  79. data/pantograph/lib/pantograph/actions/twitter.rb +89 -0
  80. data/pantograph/lib/pantograph/actions/update_pantograph.rb +177 -0
  81. data/pantograph/lib/pantograph/actions/zip.rb +120 -0
  82. data/pantograph/lib/pantograph/auto_complete.rb +82 -0
  83. data/pantograph/lib/pantograph/boolean.rb +5 -0
  84. data/pantograph/lib/pantograph/cli_tools_distributor.rb +183 -0
  85. data/pantograph/lib/pantograph/command_line_handler.rb +43 -0
  86. data/pantograph/lib/pantograph/commands_generator.rb +344 -0
  87. data/pantograph/lib/pantograph/configuration_helper.rb +26 -0
  88. data/pantograph/lib/pantograph/core_ext/bundler_monkey_patch.rb +14 -0
  89. data/pantograph/lib/pantograph/documentation/actions_list.rb +214 -0
  90. data/pantograph/lib/pantograph/documentation/docs_generator.rb +95 -0
  91. data/pantograph/lib/pantograph/documentation/markdown_docs_generator.rb +221 -0
  92. data/pantograph/lib/pantograph/environment_printer.rb +282 -0
  93. data/pantograph/lib/pantograph/erb_template_helper.rb +30 -0
  94. data/pantograph/lib/pantograph/features.rb +4 -0
  95. data/pantograph/lib/pantograph/helper/README.md +29 -0
  96. data/pantograph/lib/pantograph/helper/dotenv_helper.rb +50 -0
  97. data/pantograph/lib/pantograph/helper/gem_helper.rb +26 -0
  98. data/pantograph/lib/pantograph/helper/git_helper.rb +135 -0
  99. data/pantograph/lib/pantograph/helper/gradle_helper.rb +62 -0
  100. data/pantograph/lib/pantograph/helper/sh_helper.rb +134 -0
  101. data/pantograph/lib/pantograph/junit_generator.rb +27 -0
  102. data/pantograph/lib/pantograph/lane.rb +97 -0
  103. data/pantograph/lib/pantograph/lane_list.rb +77 -0
  104. data/pantograph/lib/pantograph/lane_manager.rb +140 -0
  105. data/pantograph/lib/pantograph/lane_manager_base.rb +92 -0
  106. data/pantograph/lib/pantograph/markdown_table_formatter.rb +62 -0
  107. data/pantograph/lib/pantograph/new_action.rb +47 -0
  108. data/pantograph/lib/pantograph/one_off.rb +45 -0
  109. data/pantograph/lib/pantograph/other_action.rb +29 -0
  110. data/pantograph/lib/pantograph/pant_file.rb +377 -0
  111. data/pantograph/lib/pantograph/pantograph_require.rb +75 -0
  112. data/pantograph/lib/pantograph/plugins/plugin_fetcher.rb +55 -0
  113. data/pantograph/lib/pantograph/plugins/plugin_generator.rb +86 -0
  114. data/pantograph/lib/pantograph/plugins/plugin_generator_ui.rb +19 -0
  115. data/pantograph/lib/pantograph/plugins/plugin_info.rb +49 -0
  116. data/pantograph/lib/pantograph/plugins/plugin_info_collector.rb +159 -0
  117. data/pantograph/lib/pantograph/plugins/plugin_manager.rb +387 -0
  118. data/pantograph/lib/pantograph/plugins/plugin_search.rb +46 -0
  119. data/pantograph/lib/pantograph/plugins/plugin_update_manager.rb +70 -0
  120. data/pantograph/lib/pantograph/plugins/plugins.rb +12 -0
  121. data/pantograph/lib/pantograph/plugins/template/%gem_name%.gemspec.erb +35 -0
  122. data/pantograph/lib/pantograph/plugins/template/.circleci/config.yml +43 -0
  123. data/pantograph/lib/pantograph/plugins/template/.gitignore +12 -0
  124. data/pantograph/lib/pantograph/plugins/template/.rspec +5 -0
  125. data/pantograph/lib/pantograph/plugins/template/.rubocop.yml +179 -0
  126. data/pantograph/lib/pantograph/plugins/template/.travis.yml +4 -0
  127. data/pantograph/lib/pantograph/plugins/template/Gemfile +6 -0
  128. data/pantograph/lib/pantograph/plugins/template/LICENSE.erb +21 -0
  129. data/pantograph/lib/pantograph/plugins/template/README.md.erb +52 -0
  130. data/pantograph/lib/pantograph/plugins/template/Rakefile +9 -0
  131. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/actions/%plugin_name%_action.rb.erb +47 -0
  132. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +16 -0
  133. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%/version.rb.erb +5 -0
  134. data/pantograph/lib/pantograph/plugins/template/lib/pantograph/plugin/%plugin_name%.rb.erb +16 -0
  135. data/pantograph/lib/pantograph/plugins/template/pantograph/Pantfile.erb +3 -0
  136. data/pantograph/lib/pantograph/plugins/template/pantograph/Pluginfile.erb +1 -0
  137. data/pantograph/lib/pantograph/plugins/template/spec/%plugin_name%_action_spec.rb.erb +9 -0
  138. data/pantograph/lib/pantograph/plugins/template/spec/spec_helper.rb.erb +15 -0
  139. data/pantograph/lib/pantograph/runner.rb +371 -0
  140. data/pantograph/lib/pantograph/server/action_command.rb +61 -0
  141. data/pantograph/lib/pantograph/server/action_command_return.rb +14 -0
  142. data/pantograph/lib/pantograph/server/command_executor.rb +7 -0
  143. data/pantograph/lib/pantograph/server/command_parser.rb +36 -0
  144. data/pantograph/lib/pantograph/server/control_command.rb +23 -0
  145. data/pantograph/lib/pantograph/server/json_return_value_processor.rb +72 -0
  146. data/pantograph/lib/pantograph/server/socket_server.rb +232 -0
  147. data/pantograph/lib/pantograph/server/socket_server_action_command_executor.rb +101 -0
  148. data/pantograph/lib/pantograph/setup/setup.rb +290 -0
  149. data/pantograph/lib/pantograph/setup/setup_android.rb +64 -0
  150. data/pantograph/lib/pantograph/setup/setup_ios.rb +412 -0
  151. data/pantograph/lib/pantograph/shells.rb +6 -0
  152. data/pantograph/lib/pantograph/supported_platforms.rb +28 -0
  153. data/pantograph/lib/pantograph/tools.rb +10 -0
  154. data/pantograph/lib/pantograph/version.rb +5 -0
  155. data/pantograph/lib/pantograph.rb +51 -0
  156. data/pantograph_core/README.md +79 -0
  157. data/pantograph_core/lib/assets/XMLTemplate.xml.erb +12 -0
  158. data/pantograph_core/lib/pantograph_core/analytics/action_completion_context.rb +34 -0
  159. data/pantograph_core/lib/pantograph_core/analytics/action_launch_context.rb +38 -0
  160. data/pantograph_core/lib/pantograph_core/analytics/analytics_event_builder.rb +23 -0
  161. data/pantograph_core/lib/pantograph_core/analytics/analytics_ingester_client.rb +54 -0
  162. data/pantograph_core/lib/pantograph_core/analytics/analytics_session.rb +71 -0
  163. data/pantograph_core/lib/pantograph_core/cert_checker.rb +116 -0
  164. data/pantograph_core/lib/pantograph_core/command_executor.rb +99 -0
  165. data/pantograph_core/lib/pantograph_core/configuration/commander_generator.rb +103 -0
  166. data/pantograph_core/lib/pantograph_core/configuration/config_item.rb +314 -0
  167. data/pantograph_core/lib/pantograph_core/configuration/configuration.rb +332 -0
  168. data/pantograph_core/lib/pantograph_core/configuration/configuration_file.rb +182 -0
  169. data/pantograph_core/lib/pantograph_core/core_ext/shellwords.rb +63 -0
  170. data/pantograph_core/lib/pantograph_core/core_ext/string.rb +17 -0
  171. data/pantograph_core/lib/pantograph_core/env.rb +9 -0
  172. data/pantograph_core/lib/pantograph_core/feature/feature.rb +51 -0
  173. data/pantograph_core/lib/pantograph_core/features.rb +4 -0
  174. data/pantograph_core/lib/pantograph_core/globals.rb +27 -0
  175. data/pantograph_core/lib/pantograph_core/helper.rb +409 -0
  176. data/pantograph_core/lib/pantograph_core/keychain_importer.rb +74 -0
  177. data/pantograph_core/lib/pantograph_core/languages.rb +14 -0
  178. data/pantograph_core/lib/pantograph_core/module.rb +29 -0
  179. data/pantograph_core/lib/pantograph_core/pantograph_folder.rb +39 -0
  180. data/pantograph_core/lib/pantograph_core/pantograph_pty.rb +57 -0
  181. data/pantograph_core/lib/pantograph_core/pkg_file_analyser.rb +44 -0
  182. data/pantograph_core/lib/pantograph_core/print_table.rb +131 -0
  183. data/pantograph_core/lib/pantograph_core/string_filters.rb +51 -0
  184. data/pantograph_core/lib/pantograph_core/swag.rb +85 -0
  185. data/pantograph_core/lib/pantograph_core/tag_version.rb +31 -0
  186. data/pantograph_core/lib/pantograph_core/test_parser.rb +107 -0
  187. data/pantograph_core/lib/pantograph_core/ui/disable_colors.rb +17 -0
  188. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_common_error.rb +19 -0
  189. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_crash.rb +11 -0
  190. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_error.rb +25 -0
  191. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_exception.rb +19 -0
  192. data/pantograph_core/lib/pantograph_core/ui/errors/pantograph_shell_error.rb +11 -0
  193. data/pantograph_core/lib/pantograph_core/ui/errors.rb +1 -0
  194. data/pantograph_core/lib/pantograph_core/ui/github_issue_inspector_reporter.rb +62 -0
  195. data/pantograph_core/lib/pantograph_core/ui/implementations/shell.rb +159 -0
  196. data/pantograph_core/lib/pantograph_core/ui/interface.rb +205 -0
  197. data/pantograph_core/lib/pantograph_core/ui/pantograph_runner.rb +276 -0
  198. data/pantograph_core/lib/pantograph_core/ui/ui.rb +26 -0
  199. data/pantograph_core/lib/pantograph_core/update_checker/changelog.rb +37 -0
  200. data/pantograph_core/lib/pantograph_core/update_checker/update_checker.rb +107 -0
  201. data/pantograph_core/lib/pantograph_core.rb +45 -0
  202. metadata +987 -0
@@ -0,0 +1,50 @@
1
+ module Pantograph
2
+ module Helper
3
+ class DotenvHelper
4
+ # @param env_cl_param [String] an optional list of dotenv environment names separated by commas, without space
5
+ def self.load_dot_env(env_cl_param)
6
+ base_path = find_dotenv_directory
7
+
8
+ return unless base_path
9
+
10
+ load_dot_envs_from(env_cl_param, base_path)
11
+ end
12
+
13
+ # finds the first directory of [pantograph, its parent] containing dotenv files
14
+ def self.find_dotenv_directory
15
+ path = PantographCore::PantographFolder.path
16
+ search_paths = [path]
17
+ search_paths << path + "/.." unless path.nil?
18
+ search_paths.compact!
19
+ search_paths.find do |dir|
20
+ Dir.glob(File.join(dir, '*.env*'), File::FNM_DOTMATCH).count > 0
21
+ end
22
+ end
23
+
24
+ # loads the dotenvs. First the .env and .env.default and
25
+ # then override with all speficied extra environments
26
+ def self.load_dot_envs_from(env_cl_param, base_path)
27
+ require 'dotenv'
28
+
29
+ # Making sure the default '.env' and '.env.default' get loaded
30
+ env_file = File.join(base_path, '.env')
31
+ env_default_file = File.join(base_path, '.env.default')
32
+ Dotenv.load(env_file, env_default_file)
33
+
34
+ return unless env_cl_param
35
+
36
+ Pantograph::Actions.lane_context[Pantograph::Actions::SharedValues::ENVIRONMENT] = env_cl_param
37
+
38
+ # multiple envs?
39
+ envs = env_cl_param.split(",")
40
+
41
+ # Loads .env file for the environment(s) passed in through options
42
+ envs.each do |env|
43
+ env_file = File.join(base_path, ".env.#{env}")
44
+ UI.success("Loading from '#{env_file}'")
45
+ Dotenv.overload(env_file)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ module Pantograph
2
+ module Actions
3
+ # will make sure a gem is installed. If it's not an appropriate error message is shown
4
+ # this will *not* 'require' the gem
5
+ def self.verify_gem!(gem_name)
6
+ begin
7
+ PantographRequire.install_gem_if_needed(gem_name: gem_name, require_gem: false)
8
+ # We don't import this by default, as it's not always the same
9
+ # also e.g. cocoapods is just required and not imported
10
+ rescue Gem::LoadError
11
+ UI.error("Could not find gem '#{gem_name}'")
12
+ UI.error("")
13
+ UI.error("If you installed pantograph using `gem install pantograph` run")
14
+ UI.command("gem install #{gem_name}")
15
+ UI.error("to install the missing gem")
16
+ UI.error("")
17
+ UI.error("If you use a Gemfile add this to your Gemfile:")
18
+ UI.important(" gem '#{gem_name}'")
19
+ UI.error("and run `bundle install`")
20
+
21
+ UI.user_error!("You have to install the `#{gem_name}` gem on this machine") unless Helper.test?
22
+ end
23
+ true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,135 @@
1
+ module Pantograph
2
+ module Actions
3
+ GIT_MERGE_COMMIT_FILTERING_OPTIONS = [:include_merges, :exclude_merges, :only_include_merges].freeze
4
+
5
+ def self.git_log_between(pretty_format, from, to, merge_commit_filtering, date_format = nil, ancestry_path)
6
+ command = %w(git log)
7
+ command << "--pretty=#{pretty_format}"
8
+ command << "--date=#{date_format}" if date_format
9
+ command << '--ancestry-path' if ancestry_path
10
+ command << "#{from}...#{to}"
11
+ command << git_log_merge_commit_filtering_option(merge_commit_filtering)
12
+ # "*command" syntax expands "command" array into variable arguments, which
13
+ # will then be individually shell-escaped by Actions.sh.
14
+ Actions.sh(*command.compact, log: false).chomp
15
+ rescue
16
+ nil
17
+ end
18
+
19
+ def self.git_log_last_commits(pretty_format, commit_count, merge_commit_filtering, date_format = nil, ancestry_path)
20
+ command = %w(git log)
21
+ command << "--pretty=#{pretty_format}"
22
+ command << "--date=#{date_format}" if date_format
23
+ command << '--ancestry-path' if ancestry_path
24
+ command << '-n' << commit_count.to_s
25
+ command << git_log_merge_commit_filtering_option(merge_commit_filtering)
26
+ Actions.sh(*command.compact, log: false).chomp
27
+ rescue
28
+ nil
29
+ end
30
+
31
+ def self.last_git_tag_hash(tag_match_pattern = nil)
32
+ tag_pattern_param = tag_match_pattern ? "=#{tag_match_pattern}" : ''
33
+ Actions.sh('git', 'rev-list', "--tags#{tag_pattern_param}", '--max-count=1').chomp
34
+ rescue
35
+ nil
36
+ end
37
+
38
+ def self.last_git_tag_name(match_lightweight = true, tag_match_pattern = nil)
39
+ hash = last_git_tag_hash(tag_match_pattern)
40
+ # If hash is nil (command fails), "git describe" command below will still
41
+ # run and provide some output, although it's definitely not going to be
42
+ # anything reasonably expected. Bail out early.
43
+ return unless hash
44
+
45
+ command = %w(git describe)
46
+ command << '--tags' if match_lightweight
47
+ command << hash
48
+ Actions.sh(*command.compact, log: false).chomp
49
+ rescue
50
+ nil
51
+ end
52
+
53
+ def self.last_git_commit_dict
54
+ return nil if last_git_commit_formatted_with('%an').nil?
55
+
56
+ {
57
+ author: last_git_commit_formatted_with('%an'),
58
+ author_email: last_git_commit_formatted_with('%ae'),
59
+ message: last_git_commit_formatted_with('%B'),
60
+ commit_hash: last_git_commit_formatted_with('%H'),
61
+ abbreviated_commit_hash: last_git_commit_formatted_with('%h')
62
+ }
63
+ end
64
+
65
+ # Gets the last git commit information formatted into a String by the provided
66
+ # pretty format String. See the git-log documentation for valid format placeholders
67
+ def self.last_git_commit_formatted_with(pretty_format, date_format = nil)
68
+ command = %w(git log -1)
69
+ command << "--pretty=#{pretty_format}"
70
+ command << "--date=#{date_format}" if date_format
71
+ Actions.sh(*command.compact, log: false).chomp
72
+ rescue
73
+ nil
74
+ end
75
+
76
+ # @deprecated Use <tt>git_author_email</tt> instead
77
+ # Get the author email of the last git commit
78
+ # <b>DEPRECATED:</b> Use <tt>git_author_email</tt> instead.
79
+ def self.git_author
80
+ UI.deprecated('`git_author` is deprecated. Please use `git_author_email` instead.')
81
+ git_author_email
82
+ end
83
+
84
+ # Get the author email of the last git commit
85
+ def self.git_author_email
86
+ s = last_git_commit_formatted_with('%ae')
87
+ return s if s.to_s.length > 0
88
+ return nil
89
+ end
90
+
91
+ # Returns the unwrapped subject and body of the last commit
92
+ # <b>DEPRECATED:</b> Use <tt>last_git_commit_message</tt> instead.
93
+ def self.last_git_commit
94
+ UI.important('`last_git_commit` is deprecated. Please use `last_git_commit_message` instead.')
95
+ last_git_commit_message
96
+ end
97
+
98
+ # Returns the unwrapped subject and body of the last commit
99
+ def self.last_git_commit_message
100
+ s = (last_git_commit_formatted_with('%B') || "").strip
101
+ return s if s.to_s.length > 0
102
+ nil
103
+ end
104
+
105
+ # Get the hash of the last commit
106
+ def self.last_git_commit_hash(short)
107
+ format_specifier = short ? '%h' : '%H'
108
+ string = last_git_commit_formatted_with(format_specifier).to_s
109
+ return string unless string.empty?
110
+ return nil
111
+ end
112
+
113
+ # Returns the current git branch - can be replaced using the environment variable `GIT_BRANCH`
114
+ def self.git_branch
115
+ return ENV['GIT_BRANCH'] if ENV['GIT_BRANCH'].to_s.length > 0 # set by Jenkins
116
+ s = Actions.sh("git rev-parse --abbrev-ref HEAD", log: false).chomp
117
+ return s.to_s.strip if s.to_s.length > 0
118
+ nil
119
+ rescue
120
+ nil
121
+ end
122
+
123
+ private_class_method
124
+ def self.git_log_merge_commit_filtering_option(merge_commit_filtering)
125
+ case merge_commit_filtering
126
+ when :exclude_merges
127
+ "--no-merges"
128
+ when :only_include_merges
129
+ "--merges"
130
+ when :include_merges
131
+ nil
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,62 @@
1
+ module Pantograph
2
+ module Helper
3
+ class GradleTask
4
+ attr_accessor :title
5
+
6
+ attr_accessor :description
7
+
8
+ def initialize(title: nil, description: nil)
9
+ self.title = title
10
+ self.description = description
11
+ end
12
+ end
13
+
14
+ class GradleHelper
15
+ # Path to the gradle script
16
+ attr_accessor :gradle_path
17
+
18
+ # Read-only path to the shell-escaped gradle script, suitable for use in shell commands
19
+ attr_reader :escaped_gradle_path
20
+
21
+ # All the available tasks
22
+ attr_accessor :tasks
23
+
24
+ def initialize(gradle_path: nil)
25
+ self.gradle_path = gradle_path
26
+ end
27
+
28
+ # Run a certain action
29
+ def trigger(task: nil, flags: nil, serial: nil, print_command: true, print_command_output: true)
30
+ android_serial = (serial != "") ? "ANDROID_SERIAL=#{serial}" : nil
31
+ command = [android_serial, escaped_gradle_path, task, flags].compact.join(" ")
32
+ Action.sh(command, print_command: print_command, print_command_output: print_command_output)
33
+ end
34
+
35
+ def task_available?(task)
36
+ load_all_tasks
37
+ return tasks.collect(&:title).include?(task)
38
+ end
39
+
40
+ def gradle_path=(gradle_path)
41
+ @gradle_path = gradle_path
42
+ @escaped_gradle_path = gradle_path.shellescape
43
+ end
44
+
45
+ private
46
+
47
+ def load_all_tasks
48
+ self.tasks = []
49
+
50
+ command = [escaped_gradle_path, "tasks", "--console=plain"].join(" ")
51
+ output = Action.sh(command, print_command: false, print_command_output: false)
52
+ output.split("\n").each do |line|
53
+ if (result = line.match(/(\w+)\s\-\s([\w\s]+)/))
54
+ self.tasks << GradleTask.new(title: result[1], description: result[2])
55
+ end
56
+ end
57
+
58
+ self.tasks
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,134 @@
1
+ require "open3"
2
+
3
+ module Pantograph
4
+ module Actions
5
+ # Execute a shell command
6
+ # This method will output the string and execute it
7
+ # Just an alias for sh_no_action
8
+ # When running this in tests, it will return the actual command instead of executing it
9
+ # @param log [Boolean] should pantograph print out the executed command
10
+ # @param error_callback [Block] a callback invoked with the command output if there is a non-zero exit status
11
+ def self.sh(*command, log: true, error_callback: nil, &b)
12
+ sh_control_output(*command, print_command: log, print_command_output: log, error_callback: error_callback, &b)
13
+ end
14
+
15
+ def self.sh_no_action(*command, log: true, error_callback: nil, &b)
16
+ sh_control_output(*command, print_command: log, print_command_output: log, error_callback: error_callback, &b)
17
+ end
18
+
19
+ # @param command The command to be executed (variadic)
20
+ # @param print_command [Boolean] Should we print the command that's being executed
21
+ # @param print_command_output [Boolean] Should we print the command output during execution
22
+ # @param error_callback [Block] A block that's called if the command exits with a non-zero status
23
+ # @yield [status, result, cmd] The return status of the command, all output from the command and an equivalent shell command
24
+ # @yieldparam [Process::Status] status A Process::Status indicating the status of the completed command
25
+ # @yieldparam [String] result The complete output to stdout and stderr of the completed command
26
+ # @yieldparam [String] cmd A shell command equivalent to the arguments passed
27
+ # rubocop: disable Metrics/PerceivedComplexity
28
+ def self.sh_control_output(*command, print_command: true, print_command_output: true, error_callback: nil)
29
+ print_command = print_command_output = true if $troubleshoot
30
+ # Set the encoding first, the user might have set it wrong
31
+ previous_encoding = [Encoding.default_external, Encoding.default_internal]
32
+ Encoding.default_external = Encoding::UTF_8
33
+ Encoding.default_internal = Encoding::UTF_8
34
+
35
+ # Workaround to support previous Pantograph syntax.
36
+ # This has some limitations. For example, it requires the caller to shell escape
37
+ # everything because of usages like ["ls -la", "/tmp"] instead of ["ls", "-la", "/tmp"].
38
+ command = [command.first.join(" ")] if command.length == 1 && command.first.kind_of?(Array)
39
+
40
+ shell_command = shell_command_from_args(*command)
41
+ UI.command(shell_command) if print_command
42
+
43
+ result = ''
44
+ exit_status = nil
45
+ if Helper.sh_enabled?
46
+ # The argument list is passed directly to Open3.popen2e, which
47
+ # handles the variadic argument list in the same way as Kernel#spawn.
48
+ # (http://ruby-doc.org/core-2.4.2/Kernel.html#method-i-spawn) or
49
+ # Process.spawn (http://ruby-doc.org/core-2.4.2/Process.html#method-c-spawn).
50
+ #
51
+ # sh "ls -la /Applications/Xcode\ 7.3.1.app"
52
+ # sh "ls", "-la", "/Applications/Xcode 7.3.1.app"
53
+ # sh({ "FOO" => "Hello" }, "echo $FOO")
54
+ Open3.popen2e(*command) do |stdin, io, thread|
55
+ io.sync = true
56
+ io.each do |line|
57
+ UI.command_output(line.strip) if print_command_output
58
+ result << line
59
+ end
60
+ exit_status = thread.value
61
+ end
62
+
63
+ # Checking Process::Status#exitstatus instead of #success? makes for more
64
+ # testable code. (Tests mock exitstatus only.) This is also consistent
65
+ # with previous implementations of sh and... probably portable to all
66
+ # relevant platforms.
67
+ if exit_status.exitstatus != 0
68
+ message = if print_command
69
+ "Exit status of command '#{shell_command}' was #{exit_status.exitstatus} instead of 0."
70
+ else
71
+ "Shell command exited with exit status #{exit_status.exitstatus} instead of 0."
72
+ end
73
+ message += "\n#{result}" if print_command_output
74
+
75
+ if error_callback || block_given?
76
+ UI.error(message)
77
+ # block notified below, on success or failure
78
+ error_callback && error_callback.call(result)
79
+ else
80
+ UI.shell_error!(message)
81
+ end
82
+ end
83
+ else
84
+ result << shell_command # only for the tests
85
+ end
86
+
87
+ if block_given?
88
+ # Avoid yielding nil in tests. $? will be meaningless, but calls to
89
+ # it will not crash. There is no Process::Status.new. The alternative
90
+ # is to move this inside the sh_enabled? check and not yield in tests.
91
+ return yield(exit_status || $?, result, shell_command)
92
+ end
93
+ result
94
+ rescue => ex
95
+ raise ex
96
+ ensure
97
+ Encoding.default_external = previous_encoding.first
98
+ Encoding.default_internal = previous_encoding.last
99
+ end
100
+ # rubocop: enable Metrics/PerceivedComplexity
101
+
102
+ # Used to produce a shell command string from a list of arguments that may
103
+ # be passed to methods such as Kernel#system, Kernel#spawn and Open3.popen2e
104
+ # in order to print the command to the terminal. The same *args are passed
105
+ # directly to a system call (Open3.popen2e). This interpretation is not
106
+ # used when executing a command.
107
+ #
108
+ # @param args Any number of arguments used to construct a command
109
+ # @raise [ArgumentError] If no arguments passed
110
+ # @return [String] A shell command representing the arguments passed in
111
+ def self.shell_command_from_args(*args)
112
+ raise ArgumentError, "sh requires at least one argument" unless args.count > 0
113
+
114
+ command = ""
115
+
116
+ # Optional initial environment Hash
117
+ if args.first.kind_of?(Hash)
118
+ command = args.shift.map { |k, v| "#{k}=#{v.shellescape}" }.join(" ") + " "
119
+ end
120
+
121
+ # Support [ "/usr/local/bin/foo", "foo" ], "-x", ...
122
+ if args.first.kind_of?(Array)
123
+ command += args.shift.first.shellescape + " " + args.shelljoin
124
+ command.chomp!(" ")
125
+ elsif args.count == 1 && args.first.kind_of?(String)
126
+ command += args.first
127
+ else
128
+ command += args.shelljoin
129
+ end
130
+
131
+ command
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,27 @@
1
+ module Pantograph
2
+ class JUnitGenerator
3
+ def self.generate(results)
4
+ # JUnit file documentation: http://llg.cubic.org/docs/junit/
5
+ # And http://nelsonwells.net/2012/09/how-jenkins-ci-parses-and-displays-junit-output/
6
+ # And http://windyroad.com.au/dl/Open%20Source/JUnit.xsd
7
+
8
+ containing_folder = ENV['FL_REPORT_PATH'] || PantographCore::PantographFolder.path || Dir.pwd
9
+ path = File.join(containing_folder, 'report.xml')
10
+
11
+ @steps = results
12
+ xml_path = File.join(Pantograph::ROOT, "lib/assets/report_template.xml.erb")
13
+ xml = ERB.new(File.read(xml_path)).result(binding) # https://web.archive.org/web/20160430190141/www.rrn.dk/rubys-erb-templating-system
14
+
15
+ xml = xml.gsub('system_', 'system-').delete("\e") # Jenkins can not parse 'ESC' symbol
16
+
17
+ begin
18
+ File.write(path, xml)
19
+ rescue => ex
20
+ UI.error(ex)
21
+ UI.error("Couldn't save report.xml at path '#{File.expand_path(path)}', make sure you have write access to the containing directory.")
22
+ end
23
+
24
+ return path
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,97 @@
1
+ module Pantograph
2
+ # Represents a lane
3
+ class Lane
4
+ attr_accessor :platform
5
+
6
+ attr_accessor :name
7
+
8
+ # @return [Array] An array containing the description of this lane
9
+ # Each item of the array is one line
10
+ attr_accessor :description
11
+
12
+ attr_accessor :block
13
+
14
+ # @return [Boolean] Is that a private lane that can't be called from the CLI?
15
+ attr_accessor :is_private
16
+
17
+ def initialize(platform: nil, name: nil, description: nil, block: nil, is_private: false)
18
+ UI.user_error!("description must be an array") unless description.kind_of?(Array)
19
+ UI.user_error!("lane name must not contain any spaces") if name.to_s.include?(" ")
20
+ UI.user_error!("lane name must start with :") unless name.kind_of?(Symbol)
21
+
22
+ self.class.verify_lane_name(name)
23
+
24
+ self.platform = platform
25
+ self.name = name
26
+ self.description = description
27
+ self.block = block
28
+ self.is_private = is_private
29
+ end
30
+
31
+ # Execute this lane
32
+ def call(parameters)
33
+ block.call(parameters || {})
34
+ end
35
+
36
+ # @return [String] The lane + name of the lane. If there is no platform, it will only be the lane name
37
+ def pretty_name
38
+ [platform, name].reject(&:nil?).join(' ')
39
+ end
40
+
41
+ class << self
42
+ # Makes sure the lane name is valid
43
+ def verify_lane_name(name)
44
+ if self.black_list.include?(name.to_s)
45
+ UI.error("Lane name '#{name}' is invalid! Invalid names are #{self.black_list.join(', ')}.")
46
+ UI.user_error!("Lane name '#{name}' is invalid")
47
+ end
48
+
49
+ if self.gray_list.include?(name.to_sym)
50
+ UI.error("------------------------------------------------")
51
+ UI.error("Lane name '#{name}' should not be used because it is the name of a pantograph tool")
52
+ UI.error("It is recommended to not use '#{name}' as the name of your lane")
53
+ UI.error("------------------------------------------------")
54
+ # We still allow it, because we're nice
55
+ # Otherwise we might break existing setups
56
+ return
57
+ end
58
+
59
+ self.ensure_name_not_conflicts(name.to_s)
60
+ end
61
+
62
+ def black_list
63
+ %w(
64
+ run
65
+ init
66
+ new_action
67
+ lanes
68
+ list
69
+ docs
70
+ action
71
+ actions
72
+ enable_auto_complete
73
+ new_plugin
74
+ add_plugin
75
+ install_plugins
76
+ update_plugins
77
+ search_plugins
78
+ help
79
+ env
80
+ update_pantograph
81
+ )
82
+ end
83
+
84
+ def gray_list
85
+ Pantograph::TOOLS
86
+ end
87
+
88
+ def ensure_name_not_conflicts(name)
89
+ # First, check if there is a predefined method in the actions folder
90
+ return unless Actions.action_class_ref(name)
91
+ UI.error("------------------------------------------------")
92
+ UI.error("Name of the lane '#{name}' is already taken by the action named '#{name}'")
93
+ UI.error("------------------------------------------------")
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,77 @@
1
+ module Pantograph
2
+ class LaneList
3
+ # Print out the result of `generate`
4
+
5
+ def self.output(path)
6
+ puts(generate(path))
7
+
8
+ puts("Execute using `pantograph [lane_name]`".yellow)
9
+ end
10
+
11
+ def self.generate(path)
12
+ ff = Pantograph::PantFile.new(path)
13
+ lanes = ff.runner.lanes
14
+
15
+ output = ""
16
+
17
+ all_keys = lanes.keys.reject(&:nil?)
18
+ all_keys.unshift(nil) # because we want root elements on top. always! They have key nil
19
+
20
+ all_keys.each do |platform|
21
+ next if (lanes[platform] || []).count == 0
22
+
23
+ plat_text = platform
24
+ plat_text = "general" if platform.to_s.empty?
25
+ output += "\n--------- #{plat_text}---------\n".yellow
26
+
27
+ value = lanes[platform]
28
+ next unless value
29
+
30
+ value.each do |lane_name, lane|
31
+ next if lane.is_private
32
+
33
+ output += "----- pantograph #{lane.pretty_name}".green
34
+ if lane.description.count > 0
35
+ output += "\n" + lane.description.join("\n") + "\n\n"
36
+ else
37
+ output += "\n\n"
38
+ end
39
+ end
40
+ end
41
+
42
+ output
43
+ end
44
+
45
+ def self.output_json(path)
46
+ puts(JSON.pretty_generate(self.generate_json(path)))
47
+ end
48
+
49
+ # Returns a hash
50
+ def self.generate_json(path)
51
+ output = {}
52
+ return output if path.nil?
53
+ ff = Pantograph::PantFile.new(path)
54
+
55
+ all_keys = ff.runner.lanes.keys
56
+
57
+ all_keys.each do |platform|
58
+ next if (ff.runner.lanes[platform] || []).count == 0
59
+
60
+ output[platform] ||= {}
61
+
62
+ value = ff.runner.lanes[platform]
63
+ next unless value
64
+
65
+ value.each do |lane_name, lane|
66
+ next if lane.is_private
67
+
68
+ output[platform][lane_name] = {
69
+ description: lane.description.join("\n")
70
+ }
71
+ end
72
+ end
73
+
74
+ return output
75
+ end
76
+ end
77
+ end