travis 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/README.md +786 -86
  2. data/Rakefile +3 -0
  3. data/lib/travis/cli/api_command.rb +22 -0
  4. data/lib/travis/cli/command.rb +36 -15
  5. data/lib/travis/cli/console.rb +13 -0
  6. data/lib/travis/cli/disable.rb +13 -0
  7. data/lib/travis/cli/enable.rb +29 -0
  8. data/lib/travis/cli/encrypt.rb +17 -4
  9. data/lib/travis/cli/history.rb +43 -0
  10. data/lib/travis/cli/logs.rb +18 -0
  11. data/lib/travis/cli/open.rb +36 -0
  12. data/lib/travis/cli/parser.rb +3 -3
  13. data/lib/travis/cli/repo_command.rb +16 -1
  14. data/lib/travis/cli/restart.rb +14 -0
  15. data/lib/travis/cli/show.rb +50 -0
  16. data/lib/travis/cli/status.rb +17 -0
  17. data/lib/travis/cli/sync.rb +28 -0
  18. data/lib/travis/cli/whatsup.rb +16 -0
  19. data/lib/travis/cli.rb +11 -0
  20. data/lib/travis/client/artifact.rb +25 -0
  21. data/lib/travis/client/build.rb +41 -0
  22. data/lib/travis/client/commit.rb +26 -0
  23. data/lib/travis/client/entity.rb +47 -3
  24. data/lib/travis/client/job.rb +52 -0
  25. data/lib/travis/client/methods.rb +22 -1
  26. data/lib/travis/client/repository.rb +70 -5
  27. data/lib/travis/client/session.rb +40 -8
  28. data/lib/travis/client/states.rb +85 -0
  29. data/lib/travis/client/user.rb +6 -0
  30. data/lib/travis/client.rb +5 -0
  31. data/lib/travis/tools/formatter.rb +38 -0
  32. data/lib/travis/version.rb +1 -1
  33. data/spec/cli/encrypt_spec.rb +16 -1
  34. data/spec/cli/history_spec.rb +28 -0
  35. data/spec/cli/logs_spec.rb +8 -0
  36. data/spec/cli/open_spec.rb +33 -0
  37. data/spec/cli/restart_spec.rb +15 -0
  38. data/spec/cli/show_spec.rb +9 -0
  39. data/spec/cli/status_spec.rb +28 -0
  40. data/spec/client/build_spec.rb +31 -0
  41. data/spec/client/commit_spec.rb +18 -0
  42. data/spec/client/job_spec.rb +30 -0
  43. data/spec/client/repository_spec.rb +15 -0
  44. data/spec/client/session_spec.rb +4 -0
  45. data/spec/spec_helper.rb +4 -1
  46. data/spec/support/fake_api.rb +616 -1
  47. data/travis.gemspec +37 -3
  48. metadata +66 -2
@@ -0,0 +1,26 @@
1
+ require 'travis/client'
2
+
3
+ module Travis
4
+ module Client
5
+ class Commit < Entity
6
+ # @!parse attr_reader :sha, :branch, :message, :committed_at, :author_name, :author_email, :committer_name, :committer_email, :compare_url
7
+ attributes :sha, :branch, :message, :committed_at, :author_name, :author_email, :committer_name, :committer_email, :compare_url
8
+ time :committed_at
9
+
10
+ one :commit
11
+ many :commits
12
+
13
+ def subject
14
+ message.to_s.lines.first.strip
15
+ end
16
+
17
+ def short_sha
18
+ sha.to_s[0..6]
19
+ end
20
+
21
+ def inspect_info
22
+ short_sha + " " + subject.inspect
23
+ end
24
+ end
25
+ end
26
+ end
@@ -9,6 +9,10 @@ module Travis
9
9
 
10
10
  MAP = {}
11
11
 
12
+ def self.relations
13
+ @relations ||= []
14
+ end
15
+
12
16
  def self.subclasses
13
17
  MAP.values.uniq
14
18
  end
@@ -17,6 +21,10 @@ module Travis
17
21
  MAP.fetch(key)
18
22
  end
19
23
 
24
+ def self.aka(name)
25
+ MAP[name.to_s] = self
26
+ end
27
+
20
28
  def self.one(key = nil)
21
29
  MAP[key.to_s] = self if key
22
30
  @one ||= key.to_s
@@ -29,16 +37,33 @@ module Travis
29
37
 
30
38
  def self.attributes(*list)
31
39
  @attributes ||= []
40
+
32
41
  list.each do |name|
33
42
  name = name.to_s
43
+ fail "can't call an attribute id" if name == "id"
44
+
34
45
  @attributes << name
35
46
  define_method(name) { load_attribute(name) }
36
47
  define_method("#{name}=") { |value| set_attribute(name, value) }
37
48
  define_method("#{name}?") { !!send(name) }
38
49
  end
50
+
39
51
  @attributes
40
52
  end
41
53
 
54
+ def self.time(*list)
55
+ list.each do |name|
56
+ define_method("#{name}=") { |value| set_attribute(name, time(value)) }
57
+ end
58
+ end
59
+
60
+ def self.has(*list)
61
+ list.each do |name|
62
+ relations << name
63
+ define_method(name) { relation(name.to_s) }
64
+ end
65
+ end
66
+
42
67
  def self.inspect_info(name)
43
68
  alias_method(:inspect_info, name)
44
69
  private(:inspect_info)
@@ -73,11 +98,12 @@ module Travis
73
98
  end
74
99
 
75
100
  def reload
76
- session.reload(self)
101
+ relations.each { |e| session.reset(e) }
102
+ session.reset(self)
77
103
  end
78
104
 
79
105
  def load
80
- reload unless complete?
106
+ session.reload(self) unless complete?
81
107
  end
82
108
 
83
109
  def missing?(key)
@@ -95,8 +121,26 @@ module Travis
95
121
  "#<#{klass}: #{inspect_info}>"
96
122
  end
97
123
 
124
+ def relations
125
+ self.class.relations.map { |r| public_send(r) }.flatten(1)
126
+ end
127
+
98
128
  private
99
129
 
130
+ def relation(name)
131
+ name = name.to_s
132
+ entity = Entity.subclass_for(name)
133
+
134
+ if entity.many == name
135
+ Array(send("#{entity.one}_ids")).map do |id|
136
+ session.find_one(entity, id)
137
+ end
138
+ else
139
+ id = send("#{name}_id")
140
+ session.find_one(entity, id) unless id.nil?
141
+ end
142
+ end
143
+
100
144
  def inspect_info
101
145
  id
102
146
  end
@@ -106,7 +150,7 @@ module Travis
106
150
  end
107
151
 
108
152
  def load_attribute(name)
109
- reload if missing? name
153
+ session.reload(self) if missing? name
110
154
  attributes[name.to_s]
111
155
  end
112
156
 
@@ -0,0 +1,52 @@
1
+ require 'travis/client'
2
+
3
+ module Travis
4
+ module Client
5
+ class Job < Entity
6
+ include States
7
+
8
+ # @!parse attr_reader :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at, :queue, :allow_failure, :tags
9
+ attributes :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at, :queue, :allow_failure, :tags
10
+ time :started_at, :finished_at
11
+
12
+ alias allow_failure? allow_failure
13
+
14
+ # @!parse attr_reader :commit, :repository, :build
15
+ has :commit, :repository, :build, :log
16
+
17
+ one :job
18
+ many :jobs
19
+
20
+ def restart
21
+ session.restart(self)
22
+ end
23
+
24
+ def pull_request?
25
+ build.pull_request?
26
+ end
27
+
28
+ def push?
29
+ build.push?
30
+ end
31
+
32
+ def allow_failures?
33
+ return false unless config.include? 'matrix' and config['matrix'].include? 'allow_failures'
34
+ config['matrix']['allow_failures'].any? do |allow|
35
+ allow.all? { |key, value| config[key] == value }
36
+ end
37
+ end
38
+
39
+ def duration
40
+ attributes['duration'] ||= begin
41
+ start = started_at || Time.now
42
+ finish = finished_at || Time.now
43
+ (finish - start).to_i
44
+ end
45
+ end
46
+
47
+ def inspect_info
48
+ "#{repository.slug}##{number}"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -16,7 +16,7 @@ module Travis
16
16
  end
17
17
 
18
18
  def github_auth(github_token)
19
- reply = session.post_raw("/auth/github?github_token=#{github_token}")
19
+ reply = session.post_raw("/auth/github", :github_token => github_token)
20
20
  session.access_token = reply["access_token"]
21
21
  end
22
22
 
@@ -37,9 +37,30 @@ module Travis
37
37
  session.find_one(Repository, id_or_slug)
38
38
  end
39
39
 
40
+ def build(id)
41
+ session.find_one(Build, id)
42
+ end
43
+
44
+ def job(id)
45
+ session.find_one(Job, id)
46
+ end
47
+
48
+ def artifact(id)
49
+ session.find_one(Artifact, id)
50
+ end
51
+
52
+ alias log artifact
53
+
40
54
  def user
41
55
  session.find_one(User)
42
56
  end
57
+
58
+ def restart(entity)
59
+ # btw, internally we call this reset, not restart, as it resets the state machine
60
+ # but we thought that would be too confusing
61
+ session.post_raw('/requests', "#{entity.class.one}_id" => entity.id)
62
+ entity.reload
63
+ end
43
64
  end
44
65
  end
45
66
  end
@@ -29,11 +29,17 @@ module Travis
29
29
  end
30
30
  end
31
31
 
32
- attributes :slug, :description, :last_build_id, :last_build_number, :last_build_state, :last_build_duration, :last_build_language, :last_build_started_at, :last_build_finished_at
32
+ include States
33
+
34
+ # @!parse attr_reader :slug, :description
35
+ attributes :slug, :description, :last_build_id, :last_build_number, :last_build_state, :last_build_duration, :last_build_started_at, :last_build_finished_at
33
36
  inspect_info :slug
34
37
 
38
+ time :last_build_finished_at, :last_build_started_at
39
+
35
40
  one :repo
36
41
  many :repos
42
+ aka :repository
37
43
 
38
44
  def public_key
39
45
  attributes["public_key"] ||= begin
@@ -54,13 +60,72 @@ module Travis
54
60
  key.encrypt(value)
55
61
  end
56
62
 
57
- def last_build_started_at=(time)
58
- set_attribute(:last_build_started_at, time(time))
63
+ # @!parse attr_reader :last_build
64
+ def last_build
65
+ return unless last_build_id
66
+ attributes['last_build'] ||= begin
67
+ last_build = session.find_one(Build, last_build_id)
68
+ last_build.number = last_build_number
69
+ last_build.state = last_build_state
70
+ last_build.duration = last_build_duration
71
+ last_build.started_at = last_build_started_at
72
+ last_build.finished_at = last_build_finished_at
73
+ last_build.repository_id = id
74
+ last_build
75
+ end
76
+ end
77
+
78
+ def builds(params = nil)
79
+ return each_build unless params
80
+ session.find_many(Build, params.merge(:repository_id => id))
59
81
  end
60
82
 
61
- def last_build_finished_at=(time)
62
- set_attribute(:last_build_finished_at, time(time))
83
+ def build(number)
84
+ builds(:number => number.to_s).first
63
85
  end
86
+
87
+ def recent_builds
88
+ builds({})
89
+ end
90
+
91
+ def each_build(params = nil, &block)
92
+ return enum_for(__method__, params) unless block_given?
93
+ params ||= {}
94
+ chunk = builds(params)
95
+ until chunk.empty?
96
+ chunk.each(&block)
97
+ number = chunk.last.number
98
+ chunk = number == '1' ? [] : builds(params.merge(:after_number => number))
99
+ end
100
+ self
101
+ end
102
+
103
+ def job(number)
104
+ build_number = number.to_s[/^\d+/]
105
+ build = build(build_number)
106
+ job = build.jobs.detect { |j| j.number == number } if number != build_number
107
+ job ||= build.jobs.first if build.jobs.size == 1
108
+ job
109
+ end
110
+
111
+ def set_hook(flag)
112
+ result = session.put_raw('/hooks/', :hook => { :id => id, :active => flag })
113
+ result['result']
114
+ end
115
+
116
+ def disable
117
+ set_hook(false)
118
+ end
119
+
120
+ def enable
121
+ set_hook(true)
122
+ end
123
+
124
+ private
125
+
126
+ def state
127
+ last_build_state
128
+ end
64
129
  end
65
130
  end
66
131
  end
@@ -9,11 +9,13 @@ module Travis
9
9
  class Session
10
10
  SSL_OPTIONS = { :ca_file => File.expand_path("../../cacert.pem", __FILE__) }
11
11
  include Methods
12
- attr_reader :connection, :headers, :access_token
12
+ attr_reader :connection, :headers, :access_token, :instruments
13
13
 
14
14
  def initialize(options = Travis::Client::ORG_URI)
15
- @headers = {}
16
- @cache = {}
15
+ @headers = {}
16
+ @cache = {}
17
+ @instruments = []
18
+ @config = nil
17
19
 
18
20
  options = { :uri => options } unless options.respond_to? :each_pair
19
21
  options.each_pair { |key, value| public_send("#{key}=", value) }
@@ -29,7 +31,7 @@ module Travis
29
31
  def uri=(uri)
30
32
  clear_cache!
31
33
  self.connection = Faraday.new(:url => uri, :ssl => SSL_OPTIONS) do |faraday|
32
- faraday.request :json
34
+ faraday.request :url_encoded
33
35
  faraday.response :json
34
36
  faraday.response :follow_redirects
35
37
  faraday.response :raise_error
@@ -47,6 +49,7 @@ module Travis
47
49
  def connection=(connection)
48
50
  clear_cache!
49
51
  connection.headers.merge! headers
52
+ @config = nil
50
53
  @connection = connection
51
54
  @headers = connection.headers
52
55
  end
@@ -84,12 +87,22 @@ module Travis
84
87
  end
85
88
  end
86
89
 
90
+ def reset(entity)
91
+ entity.attributes.clear
92
+ entity
93
+ end
94
+
87
95
  def reload(entity)
96
+ reset(entity)
88
97
  result = fetch_one(entity.class, entity.id)
89
98
  entity.update_attributes(result.attributes) if result.attributes != entity.attributes
90
99
  result
91
100
  end
92
101
 
102
+ def config
103
+ @config ||= get_raw('/config')['config']
104
+ end
105
+
93
106
  def get(*args)
94
107
  result = {}
95
108
  get_raw(*args).each_pair do |key, value|
@@ -104,13 +117,19 @@ module Travis
104
117
  end
105
118
 
106
119
  def get_raw(*args)
107
- connection.get(*args).body
108
- rescue Faraday::Error::ClientError => e
109
- handle_error(e)
120
+ raw(:get, *args)
110
121
  end
111
122
 
112
123
  def post_raw(*args)
113
- connection.post(*args).body
124
+ raw(:post, *args)
125
+ end
126
+
127
+ def put_raw(*args)
128
+ raw(:put, *args)
129
+ end
130
+
131
+ def raw(verb, *args)
132
+ instrumented(verb.to_s.upcase, *args) { connection.public_send(verb, *args).body }
114
133
  rescue Faraday::Error::ClientError => e
115
134
  handle_error(e)
116
135
  end
@@ -135,8 +154,21 @@ module Travis
135
154
  self
136
155
  end
137
156
 
157
+ def instrument(&block)
158
+ instruments << block
159
+ end
160
+
138
161
  private
139
162
 
163
+ def instrumented(name, *args)
164
+ name = [name, *args.map(&:inspect)].join(" ") if args.any?
165
+ result = nil
166
+ chain = instruments + [proc { |n,l| result = yield }]
167
+ lift = proc { chain.shift.call(name, lift) }
168
+ lift.call
169
+ result
170
+ end
171
+
140
172
  def create_entity(type, data)
141
173
  id = Integer(data.fetch('id'))
142
174
  entity = cached(type, :id, id) { type.new(self, id) }
@@ -0,0 +1,85 @@
1
+ require 'travis/client'
2
+
3
+ module Travis
4
+ module Client
5
+ module States
6
+ STATES = %w[created queued started passed failed errored canceled]
7
+
8
+ def pending?
9
+ check_state
10
+ %w[created started queued].include? state
11
+ end
12
+
13
+ def started?
14
+ check_state
15
+ state != 'created' and state != 'queued'
16
+ end
17
+
18
+ def queued?
19
+ check_state
20
+ state != 'created'
21
+ end
22
+
23
+ def finished?
24
+ not pending?
25
+ end
26
+
27
+ def passed?
28
+ check_state
29
+ state == 'passed'
30
+ end
31
+
32
+ def errored?
33
+ check_state
34
+ state == 'errored'
35
+ end
36
+
37
+ def failed?
38
+ check_state
39
+ state == 'failed'
40
+ end
41
+
42
+ def canceled?
43
+ check_state
44
+ state == 'canceled'
45
+ end
46
+
47
+ def unsuccessful?
48
+ errored? or failed? or canceled?
49
+ end
50
+
51
+ def created?
52
+ check_state
53
+ !!state
54
+ end
55
+
56
+ def color
57
+ pending? ? 'yellow' : passed? ? 'green' : 'red'
58
+ end
59
+
60
+ def yellow?
61
+ color == 'yellow'
62
+ end
63
+
64
+ def green?
65
+ color == 'green'
66
+ end
67
+
68
+ def red?
69
+ color == 'red'
70
+ end
71
+
72
+ def running?
73
+ state == 'started'
74
+ end
75
+
76
+ alias successful? passed?
77
+
78
+ private
79
+
80
+ def check_state
81
+ raise Error, "unknown state %p for %p" % [state, self] unless STATES.include? state
82
+ end
83
+ end
84
+ end
85
+ end
@@ -3,6 +3,7 @@ require 'travis/client'
3
3
  module Travis
4
4
  module Client
5
5
  class User < Entity
6
+ # @!parse attr_reader :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes
6
7
  attributes :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes
7
8
  inspect_info :login
8
9
 
@@ -13,6 +14,11 @@ module Travis
13
14
  set_attribute(:synced_at, time(time))
14
15
  end
15
16
 
17
+ def sync
18
+ session.post_raw('/users/sync')
19
+ reload
20
+ end
21
+
16
22
  alias syncing? is_syncing
17
23
  alias correct_scopes? correct_scopes
18
24
  end
data/lib/travis/client.rb CHANGED
@@ -1,10 +1,15 @@
1
1
  require 'backports/1.9.3' if RUBY_VERSION < '1.9.3'
2
2
  require 'travis/client/error'
3
+ require 'travis/client/states'
3
4
  require 'travis/client/methods'
4
5
  require 'travis/client/session'
5
6
  require 'travis/client/entity'
6
7
  require 'travis/client/user'
7
8
  require 'travis/client/repository'
9
+ require 'travis/client/build'
10
+ require 'travis/client/artifact'
11
+ require 'travis/client/commit'
12
+ require 'travis/client/job'
8
13
  require 'travis/client/namespace'
9
14
 
10
15
  module Travis
@@ -0,0 +1,38 @@
1
+ require 'time'
2
+
3
+ module Travis
4
+ module Tools
5
+ class Formatter
6
+ DAY = 24 * 60 * 60
7
+ TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
8
+ CONFIG_KEYS = ['rvm', 'gemfile', 'env', 'jdk', 'otp_release', 'php', 'node_js', 'perl', 'python', 'scala', 'compiler']
9
+
10
+ def duration(seconds, suffix = nil)
11
+ return "none" if seconds.nil?
12
+ seconds = (Time.now - seconds).to_i if seconds.is_a? Time
13
+ output = []
14
+ minutes, seconds = seconds.divmod(60)
15
+ hours, minutes = minutes.divmod(60)
16
+ output << "#{hours } hrs" if hours > 0
17
+ output << "#{minutes} min" if minutes > 0
18
+ output << "#{seconds} sec" if seconds > 0 or output.empty?
19
+ output << suffix if suffix
20
+ output.join(" ")
21
+ end
22
+
23
+ def time(time)
24
+ return "not yet" if time.nil? # or time > Time.now
25
+ #return duration(time, "ago") if Time.now - time < DAY
26
+ time.localtime.strftime(TIME_FORMAT)
27
+ end
28
+
29
+ def job_config(config)
30
+ output = []
31
+ config.each_pair do |key, value|
32
+ output << "#{key}: #{value}" if CONFIG_KEYS.include? key
33
+ end
34
+ output.join(", ")
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Travis
2
- VERSION = '1.0.3'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -18,6 +18,21 @@ describe Travis::CLI::Endpoint do
18
18
 
19
19
  example "cat foo | travis encrypt" do
20
20
  run_cli('encrypt') { |i| i.puts('foo') }
21
- stdout.should match(/^".{60,}"\n$/)
21
+ stdout.should match(/\A".{60,}"\n\Z/)
22
+ end
23
+
24
+ example "cat foo\\nbar | travis encrypt -s" do
25
+ run_cli('encrypt', '-s') { |i| i.puts("foo\nbar") }
26
+ stdout.should match(/\A(".{60,}"\n){2}\Z/)
27
+ end
28
+
29
+ example "cat foo\\nbar | travis encrypt" do
30
+ run_cli('encrypt') { |i| i.puts("foo\nbar") }
31
+ stdout.should match(/\A".{60,}"\n\Z/)
32
+ end
33
+
34
+ example "travis encrypt rails/rails foo" do
35
+ run_cli('encrypt', 'rails/rails', 'foo').should be_success
36
+ stderr.should match(/WARNING/)
22
37
  end
23
38
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Travis::CLI::History do
4
+ example 'travis history' do
5
+ run_cli('history').should be_success
6
+ stdout.should be == "#6180 failed: master Associaton -> Association\n"
7
+ end
8
+
9
+ example 'travis history -a 6180' do
10
+ run_cli('history', '-a', '6180').should be_success
11
+ stdout.should be == ''
12
+ end
13
+
14
+ example 'travis history -b master' do
15
+ run_cli('history', '-b', 'master').should be_success
16
+ stdout.should be == "#6180 failed: master Associaton -> Association\n"
17
+ end
18
+
19
+ example 'travis history -b not-master' do
20
+ run_cli('history', '-b', 'not-master').should be_success
21
+ stdout.should be_empty
22
+ end
23
+
24
+ example 'travis history -p 5' do
25
+ run_cli('history', '-p', '5').should be_success
26
+ stdout.should be_empty
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Travis::CLI::Logs do
4
+ example 'logs 6180.1' do
5
+ run_cli('logs', '6180.1', '-E').should be_success
6
+ stdout.should be == "$ export GEM=railties\n"
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Travis::CLI::Open do
4
+ example 'travis open -p' do
5
+ run_cli('open', '-p').should be_success
6
+ stdout.should be == "https://travis-ci.org/travis-ci/travis\n"
7
+ end
8
+
9
+ example 'travis open 6180 -p' do
10
+ run_cli('open', '6180', '-p').should be_success
11
+ stdout.should be == "https://travis-ci.org/travis-ci/travis/builds/4125095\n"
12
+ end
13
+
14
+ example 'travis open 6180.1 -p' do
15
+ run_cli('open', '6180.1', '-p').should be_success
16
+ stdout.should be == "https://travis-ci.org/travis-ci/travis/jobs/4125096\n"
17
+ end
18
+
19
+ example 'travis open -pg' do
20
+ run_cli('open', '-pg').should be_success
21
+ stdout.should be == "https://github.com/travis-ci/travis\n"
22
+ end
23
+
24
+ example 'travis open 6180 -pg' do
25
+ run_cli('open', '6180', '-pg').should be_success
26
+ stdout.should be == "https://github.com/rails/rails/compare/6581d798e830...a0265b98f16c\n"
27
+ end
28
+
29
+ example 'travis open 6180.1 -pg' do
30
+ run_cli('open', '6180.1', '-pg').should be_success
31
+ stdout.should be == "https://github.com/rails/rails/compare/6581d798e830...a0265b98f16c\n"
32
+ end
33
+ end