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,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
|