pantograph 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,23 @@
|
|
1
|
+
module PantographCore
|
2
|
+
class AnalyticsEventBuilder
|
3
|
+
attr_accessor :action_name
|
4
|
+
|
5
|
+
# pantograph_client_language valid options are :ruby
|
6
|
+
def initialize(p_hash: nil, session_id: nil, action_name: nil, pantograph_client_language: :ruby)
|
7
|
+
@p_hash = p_hash
|
8
|
+
@session_id = session_id
|
9
|
+
@action_name = action_name
|
10
|
+
@pantograph_client_language = pantograph_client_language
|
11
|
+
end
|
12
|
+
|
13
|
+
def new_event(action_stage)
|
14
|
+
{
|
15
|
+
client_id: @p_hash,
|
16
|
+
category: "pantograph Client Language - #{@pantograph_client_language}",
|
17
|
+
action: action_stage,
|
18
|
+
label: action_name,
|
19
|
+
value: nil
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'openssl'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative '../helper'
|
6
|
+
|
7
|
+
module PantographCore
|
8
|
+
class AnalyticsIngesterClient
|
9
|
+
GA_URL = "https://www.google-analytics.com"
|
10
|
+
|
11
|
+
private_constant :GA_URL
|
12
|
+
|
13
|
+
def initialize(ga_tracking)
|
14
|
+
@ga_tracking = ga_tracking
|
15
|
+
end
|
16
|
+
|
17
|
+
def post_event(event)
|
18
|
+
# If our users want to opt out of usage metrics, don't post the events.
|
19
|
+
# Learn more at https://docs.pantograph.tools/#metrics
|
20
|
+
if Helper.test? || PantographCore::Env.truthy?("PANTOGRAPH_OPT_OUT_USAGE")
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
return Thread.new do
|
24
|
+
send_request(event)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def send_request(event, retries: 2)
|
29
|
+
post_request(event)
|
30
|
+
rescue
|
31
|
+
retries -= 1
|
32
|
+
retry if retries >= 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def post_request(event)
|
36
|
+
connection = Faraday.new(GA_URL) do |conn|
|
37
|
+
conn.request(:url_encoded)
|
38
|
+
conn.adapter(Faraday.default_adapter)
|
39
|
+
end
|
40
|
+
connection.headers[:user_agent] = 'pantograph/' + Pantograph::VERSION
|
41
|
+
connection.post("/collect", {
|
42
|
+
v: "1", # API Version
|
43
|
+
tid: @ga_tracking, # Tracking ID / Property ID
|
44
|
+
cid: event[:client_id], # Client ID
|
45
|
+
t: "event", # Event hit type
|
46
|
+
ec: event[:category], # Event category
|
47
|
+
ea: event[:action], # Event action
|
48
|
+
el: event[:label] || "na", # Event label
|
49
|
+
ev: event[:value] || "0", # Event value
|
50
|
+
aip: "1" # IP anonymization
|
51
|
+
})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative 'analytics_ingester_client'
|
2
|
+
require_relative 'action_launch_context'
|
3
|
+
require_relative 'analytics_event_builder'
|
4
|
+
|
5
|
+
module PantographCore
|
6
|
+
class AnalyticsSession
|
7
|
+
GA_TRACKING = "UA-121171860-1"
|
8
|
+
|
9
|
+
private_constant :GA_TRACKING
|
10
|
+
attr_accessor :session_id
|
11
|
+
attr_accessor :client
|
12
|
+
|
13
|
+
def initialize(analytics_ingester_client: AnalyticsIngesterClient.new(GA_TRACKING))
|
14
|
+
require 'securerandom'
|
15
|
+
@session_id = SecureRandom.uuid
|
16
|
+
@client = analytics_ingester_client
|
17
|
+
@threads = []
|
18
|
+
@launch_event_sent = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def action_launched(launch_context: nil)
|
22
|
+
unless did_show_message?
|
23
|
+
show_message
|
24
|
+
end
|
25
|
+
|
26
|
+
if @launch_event_sent || launch_context.p_hash.nil?
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
@launch_event_sent = true
|
31
|
+
builder = AnalyticsEventBuilder.new(
|
32
|
+
p_hash: launch_context.p_hash,
|
33
|
+
session_id: session_id,
|
34
|
+
action_name: nil,
|
35
|
+
pantograph_client_language: launch_context.pantograph_client_language
|
36
|
+
)
|
37
|
+
|
38
|
+
launch_event = builder.new_event(:launch)
|
39
|
+
post_thread = client.post_event(launch_event)
|
40
|
+
unless post_thread.nil?
|
41
|
+
@threads << post_thread
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def action_completed(completion_context: nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
def show_message
|
49
|
+
UI.message("Sending anonymous analytics information")
|
50
|
+
UI.message("Learn more at https://docs.pantograph.tools/#metrics")
|
51
|
+
UI.message("No personal or sensitive data is sent.")
|
52
|
+
UI.message("You can disable this by adding `opt_out_usage` at the top of your Pantfile")
|
53
|
+
end
|
54
|
+
|
55
|
+
def did_show_message?
|
56
|
+
file_name = ".did_show_opt_info"
|
57
|
+
|
58
|
+
new_path = File.join(PantographCore.pantograph_user_dir, file_name)
|
59
|
+
did_show = File.exist?(new_path)
|
60
|
+
|
61
|
+
return did_show if did_show
|
62
|
+
|
63
|
+
File.write(new_path, '1')
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def finalize_session
|
68
|
+
@threads.map(&:join)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
module PantographCore
|
7
|
+
# This class checks if a specific certificate is installed on the current mac
|
8
|
+
class CertChecker
|
9
|
+
def self.installed?(path, in_keychain: nil)
|
10
|
+
UI.user_error!("Could not find file '#{path}'") unless File.exist?(path)
|
11
|
+
|
12
|
+
ids = installed_identies(in_keychain: in_keychain)
|
13
|
+
finger_print = sha1_fingerprint(path)
|
14
|
+
|
15
|
+
return ids.include?(finger_print)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Legacy Method, use `installed?` instead
|
19
|
+
def self.is_installed?(path)
|
20
|
+
installed?(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.installed_identies(in_keychain: nil)
|
24
|
+
install_wwdr_certificate unless wwdr_certificate_installed?
|
25
|
+
|
26
|
+
available = list_available_identities(in_keychain: in_keychain)
|
27
|
+
# Match for this text against word boundaries to avoid edge cases around multiples of 10 identities!
|
28
|
+
if /\b0 valid identities found\b/ =~ available
|
29
|
+
UI.error([
|
30
|
+
"There are no local code signing identities found.",
|
31
|
+
"You can run" << " `security find-identity -v -p codesigning #{in_keychain}".rstrip << "` to get this output.",
|
32
|
+
"This Stack Overflow thread has more information: https://stackoverflow.com/q/35390072/774.",
|
33
|
+
"(Check in Keychain Access for an expired WWDR certificate: https://stackoverflow.com/a/35409835/774 has more info.)"
|
34
|
+
].join("\n"))
|
35
|
+
end
|
36
|
+
|
37
|
+
ids = []
|
38
|
+
available.split("\n").each do |current|
|
39
|
+
next if current.include?("REVOKED")
|
40
|
+
begin
|
41
|
+
(ids << current.match(/.*\) ([[:xdigit:]]*) \".*/)[1])
|
42
|
+
rescue
|
43
|
+
# the last line does not match
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
return ids
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.list_available_identities(in_keychain: nil)
|
51
|
+
commands = ['security find-identity -v -p codesigning']
|
52
|
+
commands << in_keychain if in_keychain
|
53
|
+
`#{commands.join(' ')}`
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.wwdr_certificate_installed?
|
57
|
+
certificate_name = "Apple Worldwide Developer Relations Certification Authority"
|
58
|
+
keychain = wwdr_keychain
|
59
|
+
response = Helper.backticks("security find-certificate -c '#{certificate_name}' #{keychain.shellescape}", print: PantographCore::Globals.verbose?)
|
60
|
+
return response.include?("attributes:")
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.install_wwdr_certificate
|
64
|
+
url = 'https://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
|
65
|
+
file = Tempfile.new('AppleWWDRCA')
|
66
|
+
filename = file.path
|
67
|
+
keychain = wwdr_keychain
|
68
|
+
keychain = "-k #{keychain.shellescape}" unless keychain.empty?
|
69
|
+
|
70
|
+
require 'open3'
|
71
|
+
|
72
|
+
import_command = "curl -f -o #{filename} #{url} && security import #{filename} #{keychain}"
|
73
|
+
UI.verbose("Installing WWDR Cert: #{import_command}")
|
74
|
+
|
75
|
+
stdout, stderr, _status = Open3.capture3(import_command)
|
76
|
+
if PantographCore::Globals.verbose?
|
77
|
+
UI.command_output(stdout)
|
78
|
+
UI.command_output(stderr)
|
79
|
+
end
|
80
|
+
|
81
|
+
unless $?.success?
|
82
|
+
UI.verbose("Failed to install WWDR Certificate, checking output to see why")
|
83
|
+
# Check the command output, WWDR might already exist
|
84
|
+
unless /The specified item already exists in the keychain./ =~ stderr
|
85
|
+
UI.user_error!("Could not install WWDR certificate")
|
86
|
+
end
|
87
|
+
UI.verbose("WWDR Certificate was already installed")
|
88
|
+
end
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.wwdr_keychain
|
93
|
+
priority = [
|
94
|
+
"security list-keychains -d user",
|
95
|
+
"security default-keychain -d user"
|
96
|
+
]
|
97
|
+
priority.each do |command|
|
98
|
+
keychains = Helper.backticks(command, print: PantographCore::Globals.verbose?).split("\n")
|
99
|
+
unless keychains.empty?
|
100
|
+
# Select first keychain name from returned keychains list
|
101
|
+
return keychains[0].strip.tr('"', '')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
return ""
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.sha1_fingerprint(path)
|
108
|
+
file_data = File.read(path.to_s)
|
109
|
+
cert = OpenSSL::X509::Certificate.new(file_data)
|
110
|
+
return OpenSSL::Digest::SHA1.new(cert.to_der).to_s.upcase
|
111
|
+
rescue => error
|
112
|
+
UI.error(error)
|
113
|
+
UI.user_error!("Error parsing certificate '#{path}'")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative 'ui/ui'
|
2
|
+
require_relative 'globals'
|
3
|
+
require_relative 'pantograph_pty'
|
4
|
+
|
5
|
+
module PantographCore
|
6
|
+
# Executes commands and takes care of error handling and more
|
7
|
+
class CommandExecutor
|
8
|
+
class << self
|
9
|
+
# Cross-platform way of finding an executable in the $PATH. Respects the $PATHEXT, which lists
|
10
|
+
# valid file extensions for executables on Windows.
|
11
|
+
#
|
12
|
+
# which('ruby') #=> /usr/bin/ruby
|
13
|
+
#
|
14
|
+
# Derived from https://stackoverflow.com/a/5471032/3005
|
15
|
+
def which(cmd)
|
16
|
+
# PATHEXT contains the list of file extensions that Windows considers executable, semicolon separated.
|
17
|
+
# e.g. ".COM;.EXE;.BAT;.CMD"
|
18
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : []
|
19
|
+
exts << '' # Always have an empty string (= no file extension)
|
20
|
+
|
21
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
22
|
+
exts.each do |ext|
|
23
|
+
cmd_path = File.join(path, "#{cmd}#{ext}")
|
24
|
+
return cmd_path if Helper.executable?(cmd_path)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param command [String] The command to be executed
|
32
|
+
# @param print_all [Boolean] Do we want to print out the command output while running?
|
33
|
+
# @param print_command [Boolean] Should we print the command that's being executed
|
34
|
+
# @param error [Block] A block that's called if an error occurs
|
35
|
+
# @param prefix [Array] An array containing a prefix + block which might get applied to the output
|
36
|
+
# @param loading [String] A loading string that is shown before the first output
|
37
|
+
# @param suppress_output [Boolean] Should we print the command's output?
|
38
|
+
# @return [String] All the output as string
|
39
|
+
def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, loading: nil, suppress_output: false)
|
40
|
+
print_all = true if PantographCore::Globals.verbose?
|
41
|
+
prefix ||= {}
|
42
|
+
|
43
|
+
output = []
|
44
|
+
command = command.join(" ") if command.kind_of?(Array)
|
45
|
+
UI.command(command) if print_command
|
46
|
+
|
47
|
+
if print_all && loading # this is only used to show the "Loading text"...
|
48
|
+
UI.command_output(loading)
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
status = PantographCore::PantographPty.spawn(command) do |command_stdout, command_stdin, pid|
|
53
|
+
command_stdout.each do |l|
|
54
|
+
line = l.chomp
|
55
|
+
output << line
|
56
|
+
|
57
|
+
next unless print_all
|
58
|
+
|
59
|
+
# Prefix the current line with a string
|
60
|
+
prefix.each do |element|
|
61
|
+
line = element[:prefix] + line if element[:block] && element[:block].call(line)
|
62
|
+
end
|
63
|
+
|
64
|
+
UI.command_output(line) unless suppress_output
|
65
|
+
end
|
66
|
+
end
|
67
|
+
rescue => ex
|
68
|
+
# PantographPty adds exit_status on to StandardError so every error will have a status code
|
69
|
+
status = ex.exit_status
|
70
|
+
|
71
|
+
# This could happen when the environment is wrong:
|
72
|
+
# > invalid byte sequence in US-ASCII (ArgumentError)
|
73
|
+
output << ex.to_s
|
74
|
+
o = output.join("\n")
|
75
|
+
puts(o)
|
76
|
+
if error
|
77
|
+
error.call(o, nil)
|
78
|
+
else
|
79
|
+
raise ex
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Exit status for build command, should be 0 if build succeeded
|
84
|
+
if status != 0
|
85
|
+
o = output.join("\n")
|
86
|
+
puts(o) unless suppress_output # the user has the right to see the raw output
|
87
|
+
UI.error("Exit status: #{status}")
|
88
|
+
if error
|
89
|
+
error.call(o, status)
|
90
|
+
else
|
91
|
+
UI.user_error!("Exit status: #{status}")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
return output.join("\n")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'commander'
|
2
|
+
|
3
|
+
require_relative '../module'
|
4
|
+
require_relative '../ui/ui'
|
5
|
+
|
6
|
+
module PantographCore
|
7
|
+
class CommanderGenerator
|
8
|
+
include Commander::Methods
|
9
|
+
|
10
|
+
# Calls the appropriate methods for commander to show the available parameters
|
11
|
+
def generate(options, command: nil)
|
12
|
+
# First, enable `always_trace`, to show the stack trace
|
13
|
+
always_trace!
|
14
|
+
|
15
|
+
used_switches = []
|
16
|
+
options.each do |option|
|
17
|
+
next if option.description.to_s.empty? # "private" options
|
18
|
+
next unless option.display_in_shell
|
19
|
+
|
20
|
+
short_switch = option.short_option
|
21
|
+
key = option.key
|
22
|
+
validate_short_switch(used_switches, short_switch, key)
|
23
|
+
|
24
|
+
type = option.data_type
|
25
|
+
|
26
|
+
# We added type: Hash to code generation, but Ruby's OptionParser doesn't like that
|
27
|
+
# so we need to switch that to something that is supported, luckily, we have an `is_string`
|
28
|
+
# property and if that is false, we'll default to nil
|
29
|
+
if type == Hash
|
30
|
+
type = option.is_string ? String : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Boolean is a pantograph thing, it's either TrueClass, or FalseClass, but we won't know
|
34
|
+
# that until runtime, so nil is the best we get
|
35
|
+
if type == Pantograph::Boolean
|
36
|
+
type = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is an important bit of trickery to solve the boolean option situation.
|
40
|
+
#
|
41
|
+
# Typically, boolean command line flags do not accept trailing values. If the flag
|
42
|
+
# is present, the value is true, if it is missing, the value is false. pantograph
|
43
|
+
# supports this style of flag. For example, you can specify a flag like `--clean`,
|
44
|
+
# and the :clean option will be true.
|
45
|
+
#
|
46
|
+
# However, pantograph also supports another boolean flag style that accepts trailing
|
47
|
+
# values much like options for Strings and other value types. That looks like
|
48
|
+
# `--include_bitcode false` The problem is that this does not work out of the box
|
49
|
+
# for Commander and OptionsParser. So, we need to get tricky.
|
50
|
+
#
|
51
|
+
# The value_appendix below acts as a placeholder in the switch definition that
|
52
|
+
# states that we expect to have a trailing value for our options. When an option
|
53
|
+
# declares a data type, we use the name of that data type in all caps like:
|
54
|
+
# "--devices ARRAY". When the data type is nil, this implies that we're going
|
55
|
+
# to be doing some special handling on that value. One special thing we do
|
56
|
+
# automatically in Configuration is to coerce special Strings into boolean values.
|
57
|
+
#
|
58
|
+
# If the data type is nil, the trick we do is to specify a value placeholder, but
|
59
|
+
# we wrap it in [] brackets to mark it as optional. That means that the trailing
|
60
|
+
# value may or may not be present for this flag. If the flag is present, but the
|
61
|
+
# value is not, we get a value of `true`. Perfect for the boolean flag base-case!
|
62
|
+
# If the value is there, we'll actually get it back as a String, which we can
|
63
|
+
# later coerce into a boolean.
|
64
|
+
#
|
65
|
+
# In this way we support handling boolean flags with or without trailing values.
|
66
|
+
value_appendix = (type || '[VALUE]').to_s.upcase
|
67
|
+
long_switch = "--#{option.key} #{value_appendix}"
|
68
|
+
|
69
|
+
description = option.description
|
70
|
+
description += " (#{option.env_name})" unless option.env_name.to_s.empty?
|
71
|
+
|
72
|
+
# We compact this array here to remove the short_switch variable if it is nil.
|
73
|
+
# Passing a nil value to global_option has been shown to create problems with
|
74
|
+
# option parsing!
|
75
|
+
#
|
76
|
+
# See: https://github.com/pantograph/pantograph_core/pull/89
|
77
|
+
#
|
78
|
+
# If we don't have a data type for this option, we tell it to act like a String.
|
79
|
+
# This allows us to get a reasonable value for boolean options that can be
|
80
|
+
# automatically coerced or otherwise handled by the ConfigItem for others.
|
81
|
+
args = [short_switch, long_switch, (type || String), description].compact
|
82
|
+
|
83
|
+
if command
|
84
|
+
command.option(*args)
|
85
|
+
else
|
86
|
+
# This is the call to Commander to set up the option we've been building.
|
87
|
+
global_option(*args)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_short_switch(used_switches, short_switch, key)
|
93
|
+
return if short_switch.nil?
|
94
|
+
|
95
|
+
UI.user_error!("Short option #{short_switch} already taken for key #{key}") if used_switches.include?(short_switch)
|
96
|
+
UI.user_error!("-v is already used for the version (key #{key})") if short_switch == "-v"
|
97
|
+
UI.user_error!("-h is already used for the help screen (key #{key})") if short_switch == "-h"
|
98
|
+
UI.user_error!("-t is already used for the trace screen (key #{key})") if short_switch == "-t"
|
99
|
+
|
100
|
+
used_switches << short_switch
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|