tddium 1.25.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/tddium +29 -0
- data/lib/tddium.rb +19 -0
- data/lib/tddium/agent.rb +3 -0
- data/lib/tddium/agent/tddium.rb +122 -0
- data/lib/tddium/cli.rb +26 -0
- data/lib/tddium/cli/api.rb +319 -0
- data/lib/tddium/cli/commands/account.rb +49 -0
- data/lib/tddium/cli/commands/activate.rb +14 -0
- data/lib/tddium/cli/commands/config.rb +55 -0
- data/lib/tddium/cli/commands/describe.rb +96 -0
- data/lib/tddium/cli/commands/find_failing.rb +62 -0
- data/lib/tddium/cli/commands/github.rb +53 -0
- data/lib/tddium/cli/commands/heroku.rb +15 -0
- data/lib/tddium/cli/commands/hg.rb +48 -0
- data/lib/tddium/cli/commands/keys.rb +83 -0
- data/lib/tddium/cli/commands/login.rb +37 -0
- data/lib/tddium/cli/commands/logout.rb +14 -0
- data/lib/tddium/cli/commands/password.rb +26 -0
- data/lib/tddium/cli/commands/rerun.rb +50 -0
- data/lib/tddium/cli/commands/server.rb +22 -0
- data/lib/tddium/cli/commands/spec.rb +306 -0
- data/lib/tddium/cli/commands/status.rb +107 -0
- data/lib/tddium/cli/commands/stop.rb +19 -0
- data/lib/tddium/cli/commands/suite.rb +110 -0
- data/lib/tddium/cli/commands/web.rb +22 -0
- data/lib/tddium/cli/config.rb +245 -0
- data/lib/tddium/cli/params_helper.rb +36 -0
- data/lib/tddium/cli/prompt.rb +128 -0
- data/lib/tddium/cli/show.rb +122 -0
- data/lib/tddium/cli/suite.rb +179 -0
- data/lib/tddium/cli/tddium.rb +153 -0
- data/lib/tddium/cli/text_helper.rb +16 -0
- data/lib/tddium/cli/timeformat.rb +21 -0
- data/lib/tddium/cli/util.rb +132 -0
- data/lib/tddium/constant.rb +509 -0
- data/lib/tddium/scm.rb +8 -0
- data/lib/tddium/scm/git.rb +188 -0
- data/lib/tddium/scm/git_log_parser.rb +67 -0
- data/lib/tddium/scm/hg.rb +160 -0
- data/lib/tddium/scm/hg_log_parser.rb +66 -0
- data/lib/tddium/scm/scm.rb +20 -0
- data/lib/tddium/script.rb +12 -0
- data/lib/tddium/script/git-remote-hg +1258 -0
- data/lib/tddium/ssh.rb +66 -0
- data/lib/tddium/util.rb +35 -0
- data/lib/tddium/version.rb +5 -0
- metadata +394 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "account", "View account information"
|
6
|
+
def account
|
7
|
+
user_details = tddium_setup({:scm => false})
|
8
|
+
|
9
|
+
if user_details then
|
10
|
+
# User is already logged in, so just display the info
|
11
|
+
show_user_details(user_details)
|
12
|
+
else
|
13
|
+
exit_failure Text::Error::USE_ACTIVATE
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "account:add [ROLE] [EMAIL]", "Authorize and invite a user to use your organization"
|
18
|
+
define_method "account:add" do |role, email|
|
19
|
+
tddium_setup({:scm => false})
|
20
|
+
|
21
|
+
r = Regexp.new(/\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/)
|
22
|
+
if r !~ email then
|
23
|
+
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, "Not a valid e-mail address: must be of the form user@host.domain"]
|
24
|
+
end
|
25
|
+
|
26
|
+
params = {:role=>role, :email=>email}
|
27
|
+
begin
|
28
|
+
say Text::Process::ADDING_MEMBER % [params[:email], params[:role]]
|
29
|
+
result = @tddium_api.set_memberships(params)
|
30
|
+
say Text::Process::ADDED_MEMBER % email
|
31
|
+
rescue TddiumClient::Error::API => e
|
32
|
+
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, e.message]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "account:remove [EMAIL]", "Remove a user from an organization"
|
37
|
+
define_method "account:remove" do |email|
|
38
|
+
tddium_setup({:scm => false})
|
39
|
+
|
40
|
+
begin
|
41
|
+
say Text::Process::REMOVING_MEMBER % email
|
42
|
+
result = @tddium_api.delete_memberships(email)
|
43
|
+
say Text::Process::REMOVED_MEMBER % email
|
44
|
+
rescue TddiumClient::Error::API => e
|
45
|
+
exit_failure Text::Error::REMOVE_MEMBER_ERROR % [email, e.message]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "activate", "Activate an account (deprecated)"
|
6
|
+
method_option :email, :type => :string, :default => nil
|
7
|
+
method_option :password, :type => :string, :default => nil
|
8
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
9
|
+
def activate
|
10
|
+
say "To activate your account, please visit"
|
11
|
+
say "https://ci.solanolabs.com/"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "config [suite | repo | org[:ACCOUNT]]", "Display config variables.
|
6
|
+
The scope argument can be 'suite', 'repo', 'org' (if you are a member of
|
7
|
+
one organization), or 'org:an_organization_name' (if you are a member of
|
8
|
+
multiple organizations). The default is 'suite'."
|
9
|
+
def config(scope="suite")
|
10
|
+
tddium_setup({:repo => true, :suite => true})
|
11
|
+
|
12
|
+
begin
|
13
|
+
config_details = @tddium_api.get_config_key(scope)
|
14
|
+
show_config_details(scope, config_details['env'])
|
15
|
+
rescue TddiumClient::Error::API => e
|
16
|
+
exit_failure Text::Error::LIST_CONFIG_ERROR
|
17
|
+
rescue Exception => e
|
18
|
+
exit_failure e.message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "config:add [SCOPE] [KEY] [VALUE]", "Set KEY=VALUE at SCOPE.
|
23
|
+
The scope argument can be 'suite', 'repo', 'org' (if you are a member of
|
24
|
+
one organization), or 'org:an_organization_name' (if you are a member of
|
25
|
+
multiple organizations)."
|
26
|
+
define_method "config:add" do |scope, key, value|
|
27
|
+
tddium_setup({:repo => true, :suite => true})
|
28
|
+
|
29
|
+
begin
|
30
|
+
say Text::Process::ADD_CONFIG % [key, value, scope]
|
31
|
+
result = @tddium_api.set_config_key(scope, key, value)
|
32
|
+
say Text::Process::ADD_CONFIG_DONE % [key, value, scope]
|
33
|
+
rescue TddiumClient::Error::API => e
|
34
|
+
exit_failure Text::Error::ADD_CONFIG_ERROR
|
35
|
+
rescue Exception => e
|
36
|
+
exit_failure e.message
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "config:remove [SCOPE] [KEY]", "Remove config variable NAME from SCOPE."
|
41
|
+
define_method "config:remove" do |scope, key|
|
42
|
+
tddium_setup({:repo => true, :suite => true})
|
43
|
+
|
44
|
+
begin
|
45
|
+
say Text::Process::REMOVE_CONFIG % [key, scope]
|
46
|
+
result = @tddium_api.delete_config_key(scope, key)
|
47
|
+
say Text::Process::REMOVE_CONFIG_DONE % [key, scope]
|
48
|
+
rescue TddiumClient::Error::API => e
|
49
|
+
exit_failure Text::Error::REMOVE_CONFIG_ERROR
|
50
|
+
rescue Exception => e
|
51
|
+
exit_failure e.message
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
map "show" => :describe
|
6
|
+
desc "describe [SESSION]", "Describe the state of a session, if it
|
7
|
+
is provided; otherwise, the latest session on current branch."
|
8
|
+
method_option :account, :type => :string, :default => nil,
|
9
|
+
:aliases => %w(--org --organization)
|
10
|
+
method_option :all, :type=>:boolean, :default=>false
|
11
|
+
method_option :type, :type=>:string, :default=>nil
|
12
|
+
method_option :json, :type=>:boolean, :default=>false
|
13
|
+
method_option :names, :type=>:boolean, :default=>false
|
14
|
+
def describe(session_id=nil)
|
15
|
+
tddium_setup({:repo => false})
|
16
|
+
|
17
|
+
status_message = ''
|
18
|
+
if !session_id then
|
19
|
+
# params to get the most recent session id on current branch
|
20
|
+
suite_params = {
|
21
|
+
:suite_id => @tddium_api.current_suite_id,
|
22
|
+
:active => false,
|
23
|
+
:limit => 1
|
24
|
+
} if suite_for_current_branch?
|
25
|
+
|
26
|
+
sessions = suite_params ? @tddium_api.get_sessions(suite_params) : []
|
27
|
+
if sessions.empty? then
|
28
|
+
exit_failure Text::Status::NO_INACTIVE_SESSION
|
29
|
+
end
|
30
|
+
|
31
|
+
session_id = sessions[0]['id']
|
32
|
+
|
33
|
+
session_status = sessions[0]['status'].upcase
|
34
|
+
session_commit = sessions[0]['commit']
|
35
|
+
current_commit = @scm.current_commit
|
36
|
+
if session_commit == current_commit
|
37
|
+
commit_message = "equal to your current commit"
|
38
|
+
else
|
39
|
+
cnt_ahead = @scm.number_of_commits(session_commit, current_commit)
|
40
|
+
if cnt_ahead == 0
|
41
|
+
cnt_behind = @scm.number_of_commits(current_commit, session_commit)
|
42
|
+
commit_message = "your workspace is behind by #{cnt_behind} commits"
|
43
|
+
else
|
44
|
+
commit_message = "your workspace is ahead by #{cnt_ahead} commits"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
duration = sessions[0]['duration']
|
49
|
+
start_timeago = "%s ago" % Tddium::TimeFormat.seconds_to_human_time(Time.now - Time.parse(sessions[0]["start_time"]))
|
50
|
+
if duration.nil?
|
51
|
+
finish_timeago = "no info about duration found, started #{start_timeago}"
|
52
|
+
elsif session_status == 'RUNNING'
|
53
|
+
finish_timeago = "in process, started #{start_timeago}"
|
54
|
+
else
|
55
|
+
finish_time = Time.parse(sessions[0]["start_time"]) + duration
|
56
|
+
finish_timeago = "%s ago" % Tddium::TimeFormat.seconds_to_human_time(Time.now - finish_time)
|
57
|
+
end
|
58
|
+
|
59
|
+
status_message = Text::Status::SESSION_STATUS % [session_commit, commit_message, session_status, finish_timeago]
|
60
|
+
end
|
61
|
+
|
62
|
+
result = @tddium_api.query_session(session_id)
|
63
|
+
|
64
|
+
filtered = result['session']['tests']
|
65
|
+
if !options[:all]
|
66
|
+
filtered = filtered.select{|x| x['status'] == 'failed'}
|
67
|
+
end
|
68
|
+
|
69
|
+
if options[:type]
|
70
|
+
filtered = filtered.select{|x| x['test_type'].downcase == options[:type].downcase}
|
71
|
+
end
|
72
|
+
|
73
|
+
if options[:json]
|
74
|
+
puts JSON.pretty_generate(result['session'])
|
75
|
+
elsif options[:names]
|
76
|
+
say filtered.map{|x| x['test_name']}.join(" ")
|
77
|
+
else
|
78
|
+
filtered.sort!{|a,b| [a['test_type'], a['test_name']] <=> [b['test_type'], b['test_name']]}
|
79
|
+
|
80
|
+
say Text::Process::DESCRIBE_SESSION % [session_id, status_message, options[:all] ? 'all' : 'failed']
|
81
|
+
|
82
|
+
table =
|
83
|
+
[["Test", "Status", "Duration"],
|
84
|
+
["----", "------", "--------"]] +
|
85
|
+
filtered.map do |x|
|
86
|
+
[
|
87
|
+
x['test_name'],
|
88
|
+
x['status'],
|
89
|
+
x['elapsed_time'] ? "#{x['elapsed_time']}s" : "-"
|
90
|
+
]
|
91
|
+
end
|
92
|
+
print_table table
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "find_failing FILES", "Find failing ordering by binary searching a failing test run"
|
6
|
+
desc "find_failing files+ failing_file", "Find out which file causes pollution / makes the failing file fail"
|
7
|
+
def find_failing(*files)
|
8
|
+
failing = files.pop
|
9
|
+
if !files.include?(failing)
|
10
|
+
exit_failure "Files have to include the failing file, use the copy helper"
|
11
|
+
elsif files.size < 2
|
12
|
+
exit_failure "Files have to be more than 2, use the copy helper"
|
13
|
+
elsif !success?([failing])
|
14
|
+
exit_failure "#{failing} fails when run on it's own"
|
15
|
+
elsif success?(files)
|
16
|
+
exit_failure "tests pass locally"
|
17
|
+
else
|
18
|
+
loop do
|
19
|
+
a = remove_from(files, files.size / 2, :not => failing)
|
20
|
+
b = files - (a - [failing])
|
21
|
+
status, files = find_failing_set([a, b], failing)
|
22
|
+
if status == :finished
|
23
|
+
say "Fails when #{files.join(", ")} are run together"
|
24
|
+
break
|
25
|
+
elsif status == :continue
|
26
|
+
next
|
27
|
+
else
|
28
|
+
exit_failure "unable to isolate failure to 2 files"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def find_failing_set(sets, failing)
|
37
|
+
sets.each do |set|
|
38
|
+
next if set == [failing]
|
39
|
+
if !success?(set)
|
40
|
+
if set.size == 2
|
41
|
+
return [:finished, set]
|
42
|
+
else
|
43
|
+
return [:continue, set]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return [:failure, []]
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_from(set, x, options)
|
51
|
+
set.dup.delete_if { |f| f != options[:not] && (x -= 1) >= 0 }
|
52
|
+
end
|
53
|
+
|
54
|
+
def success?(files)
|
55
|
+
command = "bundle exec ruby #{files.map { |f| "-r./#{f.sub(/\.rb$/, "")}" }.join(" ")} -e ''"
|
56
|
+
say "Running: #{command}"
|
57
|
+
status = system(command)
|
58
|
+
say "Status: #{status ? "Success" : "Failure"}"
|
59
|
+
status
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "github:migrate_hooks", "Authorize and switch the repo to use the tddium webhook with the proper token"
|
6
|
+
define_method "github:migrate_hooks" do
|
7
|
+
suites = @tddium_api.get_suites
|
8
|
+
if suites.any?
|
9
|
+
say 'Please enter your github credentials; we do not store them anywhere'
|
10
|
+
username = HighLine.ask("username: ")
|
11
|
+
password = HighLine.ask("password: "){ |q| q.echo = "*" }
|
12
|
+
@github = Github.new(login: username, password: password)
|
13
|
+
|
14
|
+
suites.each do |suite|
|
15
|
+
login = suite['org_name'] || username
|
16
|
+
unless has_hook_token?(suite, login)
|
17
|
+
if confirm_for_repo?(suite['repo_name'])
|
18
|
+
set_hook_token(suite, login)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
else
|
23
|
+
say 'You do not have any suites configured with tddium'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def has_hook_token?(suite, login)
|
30
|
+
@github.repos.hooks.list(login, suite['repo_name']).any? do |hook|
|
31
|
+
hook["config"].try(:[], "token") == suite['repo_ci_hook_key'] && hook["active"]
|
32
|
+
end
|
33
|
+
rescue => e
|
34
|
+
say e.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def confirm_for_repo?(name)
|
38
|
+
msg = "Do you want to switch the repo '#{name}' to use the tddium webhook with the proper token? (Yes/No/All)"
|
39
|
+
(@prev && @prev == 'All') ||
|
40
|
+
((@prev = HighLine.ask(msg){ |q| q.validate = /Yes|No|All/ }) && ['Yes','All'].include?(@prev))
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_hook_token(suite, login)
|
44
|
+
@github.repos.hooks.create(login, suite['repo_name'], {
|
45
|
+
active: true,
|
46
|
+
name: :tddium,
|
47
|
+
config: {
|
48
|
+
token: suite['repo_ci_hook_key']
|
49
|
+
}
|
50
|
+
})
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "heroku", "Connect Heroku account with Solano CI (deprecated)"
|
6
|
+
method_option :email, :type => :string, :default => nil
|
7
|
+
method_option :password, :type => :string, :default => nil
|
8
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
9
|
+
method_option :app, :type => :string, :default => nil
|
10
|
+
def heroku
|
11
|
+
say "To activate your heroku account, please visit"
|
12
|
+
say "https://ci.solanolabs.com/"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (c) 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Tddium
|
6
|
+
class TddiumCli < Thor
|
7
|
+
desc "hg:mirror", "Construct local hg -> git mirror"
|
8
|
+
method_option :noop, :type => :boolean, :default => false
|
9
|
+
method_option :force, :type => :boolean, :default => false
|
10
|
+
define_method "hg:mirror" do |*args|
|
11
|
+
tddium_setup({:repo => true})
|
12
|
+
|
13
|
+
if @scm.scm_name != 'hg' then
|
14
|
+
exit_failure("Current repository does not appear to be using Mercurial")
|
15
|
+
end
|
16
|
+
|
17
|
+
if @scm.origin_url.nil? then
|
18
|
+
exit_failure("Missing default path; please set default path in hgrc")
|
19
|
+
end
|
20
|
+
|
21
|
+
if File.exists?(@scm.mirror_path) then
|
22
|
+
if !options[:force] then
|
23
|
+
exit_failure("Mirror already exists; use --force to recreate")
|
24
|
+
end
|
25
|
+
if options[:noop] then
|
26
|
+
exit_failure("Running in no-op mode; not removing existing mirror")
|
27
|
+
end
|
28
|
+
FileUtils.rm_rf(@scm.mirror_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
FileUtils.mkdir_p(@scm.mirror_path)
|
32
|
+
|
33
|
+
Tddium::Scripts.prepend_script_path
|
34
|
+
|
35
|
+
clone_command = "git clone hg::#{@scm.root} #{@scm.mirror_path}"
|
36
|
+
# origin_command = "cd #{@scm.mirror_path} && git remote set-url origin #{@scm.origin_url}"
|
37
|
+
|
38
|
+
if options[:noop] then
|
39
|
+
puts "export PATH=#{ENV['PATH']}"
|
40
|
+
puts clone_command
|
41
|
+
# puts origin_command
|
42
|
+
else
|
43
|
+
Kernel.system(clone_command)
|
44
|
+
# Kernel.system(origin_command)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Tddium
|
4
|
+
class TddiumCli < Thor
|
5
|
+
desc "keys", "List SSH keys authorized for Solano CI"
|
6
|
+
def keys
|
7
|
+
user_details = tddium_setup({:scm => false})
|
8
|
+
|
9
|
+
begin
|
10
|
+
if user_details then
|
11
|
+
show_third_party_keys_details(user_details)
|
12
|
+
end
|
13
|
+
|
14
|
+
keys_details = @tddium_api.get_keys
|
15
|
+
show_keys_details(keys_details)
|
16
|
+
rescue TddiumClient::Error::API => e
|
17
|
+
exit_failure Text::Error::LIST_KEYS_ERROR
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "keys:add [NAME] [PATH]", "Authorize an existing keypair for Solano CI"
|
22
|
+
method_option :dir, :type=>:string, :default=>nil
|
23
|
+
define_method "keys:add" do |name, path|
|
24
|
+
tddium_setup({:scm => false})
|
25
|
+
|
26
|
+
path = File.expand_path(path)
|
27
|
+
|
28
|
+
output_dir = options[:dir] || ENV['TDDIUM_GEM_KEY_DIR']
|
29
|
+
output_dir ||= Default::SSH_OUTPUT_DIR
|
30
|
+
|
31
|
+
begin
|
32
|
+
keydata = Tddium::Ssh.validate_keys name, path, @tddium_api
|
33
|
+
say Text::Process::ADD_KEYS_ADD % name
|
34
|
+
result = @tddium_api.set_keys({:keys => [keydata]})
|
35
|
+
|
36
|
+
priv_path = path.sub(/[.]pub$/, '')
|
37
|
+
say Text::Process::ADD_KEYS_ADD_DONE % [name, priv_path, result["git_server"] || Default::GIT_SERVER, priv_path]
|
38
|
+
|
39
|
+
rescue TddiumClient::Error::API => e
|
40
|
+
exit_failure Text::Error::ADD_KEYS_ERROR % name
|
41
|
+
rescue TddiumError => e
|
42
|
+
exit_failure e.message
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
map "generate" => :gen
|
47
|
+
desc "keys:gen [NAME]", "Generate and authorize a keypair for Solano CI"
|
48
|
+
method_option :dir, :type=>:string, :default=>nil
|
49
|
+
define_method "keys:gen" do |name|
|
50
|
+
tddium_setup({:scm => false})
|
51
|
+
|
52
|
+
output_dir = options[:dir] || ENV['TDDIUM_GEM_KEY_DIR']
|
53
|
+
output_dir ||= Default::SSH_OUTPUT_DIR
|
54
|
+
|
55
|
+
begin
|
56
|
+
keydata = Tddium::Ssh.validate_keys name, output_dir, @tddium_api, true
|
57
|
+
say Text::Process::ADD_KEYS_GENERATE % name
|
58
|
+
|
59
|
+
result = @tddium_api.set_keys({:keys => [keydata]})
|
60
|
+
outfile = File.expand_path(File.join(output_dir, "identity.tddium.#{name}"))
|
61
|
+
say Text::Process::ADD_KEYS_GENERATE_DONE % [name, result["git_server"] || Default::GIT_SERVER, outfile]
|
62
|
+
|
63
|
+
rescue TddiumClient::Error::API => e
|
64
|
+
exit_failure Text::Error::ADD_KEYS_ERROR % name
|
65
|
+
rescue TddiumError => e
|
66
|
+
exit_failure e.message
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "keys:remove [NAME]", "Remove a key that was authorized for Solano CI"
|
71
|
+
define_method "keys:remove" do |name|
|
72
|
+
tddium_setup({:scm => false})
|
73
|
+
|
74
|
+
begin
|
75
|
+
say Text::Process::REMOVE_KEYS % name
|
76
|
+
result = @tddium_api.delete_keys(name)
|
77
|
+
say Text::Process::REMOVE_KEYS_DONE % name
|
78
|
+
rescue TddiumClient::Error::API => e
|
79
|
+
exit_failure Text::Error::REMOVE_KEYS_ERROR % name
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|