solano 1.31.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 (54) hide show
  1. checksums.yaml +15 -0
  2. data/bin/solano +29 -0
  3. data/bin/tddium +29 -0
  4. data/lib/solano.rb +19 -0
  5. data/lib/solano/agent.rb +3 -0
  6. data/lib/solano/agent/solano.rb +128 -0
  7. data/lib/solano/cli.rb +25 -0
  8. data/lib/solano/cli/api.rb +368 -0
  9. data/lib/solano/cli/commands/account.rb +50 -0
  10. data/lib/solano/cli/commands/activate.rb +16 -0
  11. data/lib/solano/cli/commands/api.rb +15 -0
  12. data/lib/solano/cli/commands/config.rb +78 -0
  13. data/lib/solano/cli/commands/console.rb +85 -0
  14. data/lib/solano/cli/commands/describe.rb +104 -0
  15. data/lib/solano/cli/commands/find_failing.rb +64 -0
  16. data/lib/solano/cli/commands/heroku.rb +17 -0
  17. data/lib/solano/cli/commands/hg.rb +48 -0
  18. data/lib/solano/cli/commands/keys.rb +81 -0
  19. data/lib/solano/cli/commands/login.rb +37 -0
  20. data/lib/solano/cli/commands/logout.rb +14 -0
  21. data/lib/solano/cli/commands/password.rb +26 -0
  22. data/lib/solano/cli/commands/rerun.rb +59 -0
  23. data/lib/solano/cli/commands/server.rb +21 -0
  24. data/lib/solano/cli/commands/spec.rb +401 -0
  25. data/lib/solano/cli/commands/status.rb +117 -0
  26. data/lib/solano/cli/commands/stop.rb +19 -0
  27. data/lib/solano/cli/commands/suite.rb +110 -0
  28. data/lib/solano/cli/commands/support.rb +24 -0
  29. data/lib/solano/cli/commands/web.rb +29 -0
  30. data/lib/solano/cli/config.rb +246 -0
  31. data/lib/solano/cli/params_helper.rb +66 -0
  32. data/lib/solano/cli/prompt.rb +128 -0
  33. data/lib/solano/cli/show.rb +136 -0
  34. data/lib/solano/cli/solano.rb +208 -0
  35. data/lib/solano/cli/suite.rb +104 -0
  36. data/lib/solano/cli/text_helper.rb +16 -0
  37. data/lib/solano/cli/timeformat.rb +21 -0
  38. data/lib/solano/cli/util.rb +132 -0
  39. data/lib/solano/constant.rb +581 -0
  40. data/lib/solano/scm.rb +18 -0
  41. data/lib/solano/scm/configure.rb +37 -0
  42. data/lib/solano/scm/git.rb +349 -0
  43. data/lib/solano/scm/git_log_parser.rb +67 -0
  44. data/lib/solano/scm/hg.rb +263 -0
  45. data/lib/solano/scm/hg_log_parser.rb +66 -0
  46. data/lib/solano/scm/scm.rb +119 -0
  47. data/lib/solano/scm/scm_stub.rb +9 -0
  48. data/lib/solano/scm/url.rb +75 -0
  49. data/lib/solano/script.rb +12 -0
  50. data/lib/solano/script/git-remote-hg +1258 -0
  51. data/lib/solano/ssh.rb +66 -0
  52. data/lib/solano/util.rb +63 -0
  53. data/lib/solano/version.rb +5 -0
  54. metadata +413 -0
@@ -0,0 +1,263 @@
1
+ # Copyright (c) 2011-2015 Solano Labs All Rights Reserved
2
+
3
+ require 'uri'
4
+ require 'shellwords'
5
+
6
+ module Solano
7
+ class Hg < SCM
8
+ include SolanoConstant
9
+
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ def scm_name
15
+ return 'hg'
16
+ end
17
+
18
+ def repo?
19
+ if File.directory?('.hg') then
20
+ return true
21
+ end
22
+ ignore = `hg status 2>&1`
23
+ ok = $?.success?
24
+ return ok
25
+ end
26
+
27
+ def root
28
+ root = `hg root`
29
+ if $?.exitstatus == 0 then
30
+ root.chomp! if root
31
+ return root
32
+ end
33
+ return Dir.pwd
34
+ end
35
+
36
+ def repo_name
37
+ return File.basename(self.root)
38
+ end
39
+
40
+ def origin_url
41
+ return @default_origin_url if @default_origin_url
42
+
43
+ result = `hg paths default`
44
+ return nil unless $?.success?
45
+ return nil if result.empty?
46
+ result.strip!
47
+ u = URI.parse(result) rescue nil
48
+ if u && u.host.nil? then
49
+ warn(Text::Warning::HG_PATHS_DEFAULT_NOT_URI)
50
+ return nil
51
+ end
52
+ return result
53
+ end
54
+
55
+ def ignore_path
56
+ path = File.join(self.root, Config::HG_IGNORE)
57
+ return path
58
+ end
59
+
60
+ def current_branch
61
+ branch = `hg branch`
62
+ branch.chomp!
63
+ return branch
64
+ end
65
+
66
+ def default_branch
67
+ # NOTE: not necessarily quite right in HG 2.1+ with a default bookmark
68
+ return "default"
69
+ end
70
+
71
+ def changes?(options={})
72
+ return Solano::Hg.hg_changes?(:exclude=>".hgignore")
73
+ end
74
+
75
+ def hg_push(uri)
76
+ cmd = "hg push -f -b #{self.current_branch} "
77
+ cmd += " #{uri}"
78
+
79
+ # git outputs something to stderr when it runs git push.
80
+ # hg doesn't always ... so show the command that's being run and its
81
+ # output to indicate progress.
82
+ puts cmd
83
+ puts `#{cmd}`
84
+ return [0,1].include?( $?.exitstatus )
85
+ end
86
+
87
+ def push_latest(session_data, suite_details, options={})
88
+ uri = if options[:use_private_uri] then
89
+ suite_details["git_repo_private_uri"] || suite_details["git_repo_uri"]
90
+ else
91
+ suite_details["git_repo_uri"]
92
+ end
93
+ self.hg_push(uri)
94
+ end
95
+
96
+ def current_commit
97
+ commit = `hg id -i`
98
+ commit.chomp!
99
+ return commit
100
+ end
101
+
102
+ def commits
103
+ commits = HgCommitLogParser.new(self.latest_commit).commits
104
+ return commits
105
+ end
106
+
107
+ def number_of_commits(id_from, id_to)
108
+ result = `hg log --template='{node}\\n' #{id_from}..#{id_to}`
109
+ result.split("\n").length
110
+ end
111
+
112
+ def create_snapshot(session_id, options={})
113
+ api = options[:api]
114
+ res = api.request_snapshot_url({:session_id => session_id})
115
+ auth_url = res['auth_url']
116
+
117
+ say Text::Process::SNAPSHOT_URL % auth_url
118
+
119
+ unique = SecureRandom.hex(10)
120
+ snaphot_path = File.join(Dir.tmpdir,".solano-#{unique}-snapshot")
121
+ file = File.join(Dir.tmpdir, "solano-#{unique}-snapshot.tar")
122
+
123
+ # #git default branch
124
+ # branch = options[:default_branch]
125
+ # branch ||= /\-\>.*\/(.*)$/.match( (`git branch -r | grep origin/HEAD`).strip)[1]
126
+
127
+ # if branch.nil? then
128
+ # raise Text::Error::DEFAULT_BRANCH
129
+ # end
130
+
131
+ out = `hg clone #{root} #{snaphot_path}`
132
+ out = `tar -C #{snaphot_path} -czpf #{file} .`
133
+ upload_file(auth_url, file)
134
+ Dir.chdir(snaphot_path){
135
+ @snap_id = (`hg --debug id -i`).strip
136
+ }
137
+
138
+ desc = {"url" => auth_url.gsub(/\?.*/,''),
139
+ "size" => File.stat(file).size,
140
+ "sha1"=> Digest::SHA1.file(file).hexdigest.upcase,
141
+ "commit_id"=> @snap_id,
142
+ "session_id" => session_id,
143
+ }
144
+ api.update_snapshot({:repo_snapshot => desc})
145
+ ensure
146
+ FileUtils.rm_rf(snaphot_path) if snaphot_path && File.exists?(snaphot_path)
147
+ FileUtils.rm_f(file) if file && File.exists?(file)
148
+ end
149
+
150
+ def create_patch(session_id, options={})
151
+ api = options[:api]
152
+ snapshot_commit = options[:commit]
153
+ if "#{snapshot_commit}" == `hg --debug id -i`.to_s.strip then
154
+ say Text::Warning::SAME_SNAPSHOT_COMMIT
155
+ return
156
+ end
157
+ #check if commit is known locally
158
+ if (`hg log --rev "ancestors(.) and #{snapshot_commit}" 2>&1 >/dev/null | grep -o 'error:' | wc -l`).to_i > 0 then
159
+ raise Text::Error::PATCH_CREATION_ERROR % snapshot_commit
160
+ end
161
+
162
+ file_name = "solano-#{SecureRandom.hex(10)}.patch"
163
+ tmp_dir = Dir.mktmpdir("patches")
164
+ file_path = File.join(tmp_dir, file_name)
165
+ Dir
166
+ out = `hg export -o #{tmp_dir}/patch-%n -r #{snapshot_commit}:tip`
167
+ say out
168
+ build_patch(tmp_dir, file_path)
169
+
170
+ file_size = File.size(file_path)
171
+ file_sha1 = Digest::SHA1.file(file_path).hexdigest.upcase
172
+
173
+ #upload patch
174
+ say Text::Process::REQUST_PATCH_URL
175
+ res = api.request_patch_url({:session_id => session_id})
176
+ if (auth_url = res['auth_url']) then
177
+ say Text::Process::UPLOAD_PATCH % auth_url
178
+ upload_file(auth_url, file_path)
179
+ else
180
+ raise Text::Error::NO_PATCH_URL
181
+ end
182
+
183
+ args = { :session_id => session_id,
184
+ :sha1 => file_sha1,
185
+ :size => file_size,}
186
+ api.upload_session_patch(args)
187
+
188
+ ensure
189
+ FileUtils.rm_rf(file_path) if file_path && File.exists?(file_path)
190
+ FileUtils.rm_rf(tmp_dir) if tmp_dir && File.exists?(tmp_dir)
191
+ end
192
+
193
+ protected
194
+
195
+ def build_patch(tmp_dir, file_path)
196
+ #patch currently includes one two many commits
197
+ files = Dir.glob(File.join(tmp_dir,"patch-*"))
198
+ files.sort!
199
+ files.shift
200
+
201
+ File.open( file_path, "w" ){|f_out|
202
+ files.each {|f_name|
203
+ File.open(f_name){|f_in|
204
+ f_in.each {|f_str| f_out.puts(f_str) }
205
+ }
206
+ }
207
+ }
208
+ end
209
+
210
+ def latest_commit
211
+ `hg log -f -l 1 --template='{node}\\n{desc|firstline}\\n{author|user}\\n{author|email}\\n{date}\\n{author|user}\\n{author|email}\\n{date}\\n\\n'`
212
+ end
213
+
214
+ class << self
215
+ include SolanoConstant
216
+
217
+ def hg_changes?(options={})
218
+ options[:exclude] ||= []
219
+ options[:exclude] = [options[:exclude]] unless options[:exclude].is_a?(Array)
220
+ cmd = "hg status -mardu"
221
+ p = IO.popen(cmd)
222
+ changes = false
223
+ while line = p.gets do
224
+ line = line.strip
225
+ status, name = line.split(/\s+/)
226
+ next if options[:exclude].include?(name)
227
+ if status !~ /^\?/ then
228
+ changes = true
229
+ break
230
+ end
231
+ end
232
+ unless $?.success? then
233
+ warn(Text::Warning::SCM_UNABLE_TO_DETECT)
234
+ return false
235
+ end
236
+ return changes
237
+ end
238
+
239
+ def hg_push(this_branch, additional_refs=[])
240
+ raise "not implemented"
241
+ end
242
+
243
+ def version_ok
244
+ version = nil
245
+ begin
246
+ version_string = `hg -q --version`
247
+ m = version_string.match(Dependency::VERSION_REGEXP)
248
+ version = m[0] unless m.nil?
249
+ rescue Errno
250
+ rescue Exception
251
+ end
252
+ if version.nil? || version.empty? then
253
+ return false
254
+ end
255
+ version_parts = version.split(".")
256
+ if version_parts[0].to_i < 2 then
257
+ warn(Text::Warning::HG_VERSION % version)
258
+ end
259
+ true
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ # this is not namespaced under Solano because we want to eventually move this out into another gem
4
+ class HgCommitLogParser
5
+ attr_accessor :commit_log
6
+
7
+ # example commit_log generated by
8
+ # `hg log -f -l 1 --template='{node}\n{desc|firstline}\n{author|user}\n{author|email}\n{date}\n{author|user}\n{author|email}\n{date}\n'`
9
+
10
+ # beb3d918995bbe6370bb21fd76b4f433bfd64dc4
11
+ # commit summary
12
+ # user
13
+ # user@host.domain
14
+ # 1399437808.00
15
+ # user
16
+ # user@host.domain
17
+ # 1399437808.00
18
+
19
+ def initialize(commit_log)
20
+ @commit_log = commit_log
21
+ end
22
+
23
+ # Returns a list of commits in the following format
24
+ # [{
25
+ # "id" => "15e8cbd88d68d210953d51c28e26c6b9944a313b",
26
+ # "author" => {"name"=>"Bob Smith", "email"=>"bob@example.com"},
27
+ # "committer" => {"name"=>"Fred Smith", "email"=>"fred@example.com"},
28
+ # "summary" => "ignore .ruby-version for rvm",
29
+ # "date" => 1380603292
30
+ # }]
31
+
32
+ def commits
33
+ record = []
34
+ commits = []
35
+ commit_log.lines.each do |line|
36
+ line.strip!
37
+ line.sanitize!
38
+ if line.empty?
39
+ c = parse_commit(record)
40
+ commits.push(c)
41
+ record = []
42
+ else
43
+ record.push(line)
44
+ end
45
+ end
46
+
47
+ commits
48
+ end
49
+
50
+ private
51
+
52
+ def parse_commit(record)
53
+ time = record[4].to_i
54
+ author = build_user(record[2], record[3])
55
+ committer = build_user(record[5], record[6])
56
+ build_commit(record[0], author, committer, record[1], time)
57
+ end
58
+
59
+ def build_user(name, email)
60
+ {"name" => name, "email" => email}
61
+ end
62
+
63
+ def build_commit(sha, author, committer, summary, date)
64
+ {"id" => sha, "author" => author, "committer" => committer, "summary" => summary, "date" => date}
65
+ end
66
+ end
@@ -0,0 +1,119 @@
1
+ # Copyright (c) 2011-2015 Solano Labs All Rights Reserved
2
+
3
+ module Solano
4
+ class SCM
5
+ attr_accessor :default_origin_url
6
+
7
+ def initialize
8
+ @default_origin_url = nil
9
+ end
10
+
11
+ def support_data
12
+ data = Hash.new
13
+ data['scm_name'] = self.scm_name
14
+ if !self.repo? then
15
+ data['is_repo'] = false
16
+ return data
17
+ end
18
+
19
+ %w(scm_name repo? root repo_name origin_url current_branch default_branch changes?).each do |method|
20
+ key = method
21
+ if method =~ /[?]\z/ then
22
+ key = "is_#{method.sub(/[?]\z/, '')}"
23
+ end
24
+
25
+ value = self.send(method.to_sym) rescue nil
26
+
27
+ data[key] = value
28
+ end
29
+
30
+ return data
31
+ end
32
+
33
+ def scm_name
34
+ end
35
+
36
+ def repo?
37
+ return false
38
+ end
39
+
40
+ def root
41
+ return Dir.pwd
42
+ end
43
+
44
+ def repo_name
45
+ return "unknown"
46
+ end
47
+
48
+ def origin_url
49
+ return @default_origin_url
50
+ end
51
+
52
+ def ignore_path
53
+ return nil
54
+ end
55
+
56
+ def current_branch
57
+ return nil
58
+ end
59
+
60
+ def default_branch
61
+ return nil
62
+ end
63
+
64
+ def changes?(options={})
65
+ return false
66
+ end
67
+
68
+ def get_snap_id
69
+ return @snap_id
70
+ end
71
+
72
+ def push_latest(session_data, suite_details, options={})
73
+ return false
74
+ end
75
+
76
+ def create_snapshot(session_id, options={})
77
+ raise Text::Error:SNAPSHOT_NOT_SUPPORTED
78
+ end
79
+
80
+ def create_patch(session_id, options={})
81
+ raise Text::Error:PATCH_NOT_SUPPORTED
82
+ end
83
+
84
+ def upload_file(auth_url, file_path)
85
+ if (`which curl >/dev/null 2>&1 ; echo $?`).to_i == 0 then
86
+ `curl -f --upload-file "#{file_path}" "#{auth_url}"`
87
+ if(`echo $?`).to_i == 22 then
88
+ raise "Failed to upload #{file_path} URL (#{out.code})"
89
+ end
90
+ else
91
+ uri = URI(auth_url)
92
+ body = File.read(file_path)
93
+ out = Net::HTTP.start(uri.host, :use_ssl => true) do |http|
94
+ http.send_request("PUT", uri.request_uri, body, {"content-type" => "",})
95
+ end
96
+ if out.code.to_i != 200
97
+ raise "Failed to upload to #{file_path} (#{out.code})"
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ def current_commit
104
+ return nil
105
+ end
106
+
107
+ def commits
108
+ []
109
+ end
110
+
111
+ def number_of_commits(id_from, id_to)
112
+ return 0
113
+ end
114
+
115
+ def latest_commit
116
+ return nil
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2015 Solano Labs All Rights Reserved
2
+
3
+ module Solano
4
+ class StubSCM < SCM
5
+ def initialize
6
+ super
7
+ end
8
+ end
9
+ end