tc4r 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +7 -0
- data/bin/tc +4 -0
- data/bin/tc-setup +3 -0
- data/lib/tc4r.rb +11 -0
- data/lib/tc4r/build.rb +27 -0
- data/lib/tc4r/build_type.rb +32 -0
- data/lib/tc4r/client.rb +109 -0
- data/lib/tc4r/helpers.rb +23 -0
- data/lib/tc4r/version.rb +3 -0
- data/lib/tc4r_base.rb +120 -0
- data/lib/tc4r_setup.rb +48 -0
- data/spec/client_spec.rb +105 -0
- data/spec/requests/build_5733.json +1 -0
- data/spec/requests/build_types.json +36 -0
- data/spec/requests/builds_bt1.json +167 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/tc_client_spec.rb +5 -0
- data/tc4r.gemspec +28 -0
- metadata +204 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Paul Morton
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Tc4r
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'tc4r'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install tc4r
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/tc
ADDED
data/bin/tc-setup
ADDED
data/lib/tc4r.rb
ADDED
data/lib/tc4r/build.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Tc4r
|
2
|
+
class Build
|
3
|
+
include ActiveModel::Serializers::JSON
|
4
|
+
self.include_root_in_json = false
|
5
|
+
|
6
|
+
attr_reader :id, :number, :status, :build_type_id, :start_date, :href, :client
|
7
|
+
def initialize(options,client)
|
8
|
+
options = Tc4r::Helpers.symbolize(options)
|
9
|
+
@id = options[:id]
|
10
|
+
@number = options[:number]
|
11
|
+
@status = options[:status]
|
12
|
+
@build_type_id = options[:build_type_id]
|
13
|
+
@start_date = Time.parse(options[:start_date])
|
14
|
+
@href = options[:href]
|
15
|
+
@client = client
|
16
|
+
end
|
17
|
+
|
18
|
+
def attributes
|
19
|
+
{ :id => @id, :number => @number, :status => @status, :build_type_id => @build_type_id, :start_date => @start_date, :href => @href }
|
20
|
+
end
|
21
|
+
|
22
|
+
def download_file(file, options = {})
|
23
|
+
client.download_file(build_type_id,number,file,options)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Tc4r
|
2
|
+
class BuildType
|
3
|
+
include ActiveModel::Serializers::JSON
|
4
|
+
self.include_root_in_json = false
|
5
|
+
|
6
|
+
attr_reader :id,:name,:project_name,:project_id, :href, :client
|
7
|
+
|
8
|
+
def initialize(options = {},client)
|
9
|
+
options = Tc4r::Helpers.symbolize(options)
|
10
|
+
@id = options[:id]
|
11
|
+
@name = options[:name]
|
12
|
+
@project_name = options[:project_name] || options[:project][:name]
|
13
|
+
@project_id = options[:project_id] || options[:project][:id]
|
14
|
+
@href = options[:href]
|
15
|
+
@client = client
|
16
|
+
end
|
17
|
+
|
18
|
+
def attributes
|
19
|
+
{ :id => @id, :name => @name, :project_name => @project_name, :project_id => @project_id, :href => @href }
|
20
|
+
end
|
21
|
+
|
22
|
+
def builds
|
23
|
+
client.query_builds(id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def build(number)
|
27
|
+
client.build(id,number)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/tc4r/client.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nestful'
|
3
|
+
require 'commander'
|
4
|
+
module Tc4r
|
5
|
+
|
6
|
+
class Client
|
7
|
+
attr_reader :server
|
8
|
+
attr_reader :port
|
9
|
+
attr_reader :username
|
10
|
+
attr_reader :password
|
11
|
+
attr_reader :transport
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
default_options = { :server => 'localhost',
|
15
|
+
:port => 8111,
|
16
|
+
:username => nil,
|
17
|
+
:password => nil,
|
18
|
+
:transport => :http
|
19
|
+
}
|
20
|
+
options = default_options.merge(options)
|
21
|
+
|
22
|
+
@server = options[:server]
|
23
|
+
@port = options[:port]
|
24
|
+
@username = options[:username]
|
25
|
+
@password = options[:password]
|
26
|
+
@transport = options[:transport]
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_url
|
30
|
+
@base_url ||= "#{transport}://#{server}:#{port}/httpAuth"
|
31
|
+
end
|
32
|
+
|
33
|
+
def rest_url(path)
|
34
|
+
"#{base_url}/app/rest/#{path}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def download_url(path)
|
38
|
+
"#{base_url}/repository/download/#{path}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def merge_options(options)
|
42
|
+
{ :user => username,
|
43
|
+
:password => password,
|
44
|
+
:auth_type => :basic }.merge(options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_types
|
48
|
+
bts = Nestful.get rest_url('buildTypes') , merge_options( :format => :json )
|
49
|
+
bts['buildType'].collect do |bt|
|
50
|
+
BuildType.new(Tc4r::Helpers.sym_score(bt), self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_type(bt)
|
55
|
+
build_type = Nestful.get rest_url("buildTypes/id:#{bt}") , merge_options( :format => :json )
|
56
|
+
BuildType.new(Tc4r::Helpers.sym_score(build_type), self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def query_builds(bt, options = {})
|
60
|
+
parameters = {}
|
61
|
+
parameters[:status] = 'SUCCESS' if options[:status] == :success
|
62
|
+
parameters[:status] = 'ERROR' if options[:status] == :error
|
63
|
+
parameters[:tag] = options[:tag] if options[:tag]
|
64
|
+
builds = Nestful.get rest_url("buildTypes/id:#{bt}/builds") , merge_options( :format => :json, :params => parameters )
|
65
|
+
builds['build'].collect do |build|
|
66
|
+
Build.new(Tc4r::Helpers.sym_score(build),self)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def build(bt,number)
|
71
|
+
build = Nestful.get rest_url("buildTypes/id:#{bt}/builds/number:#{number}") , merge_options( :format => :json )
|
72
|
+
Tc4r::Build.new(Tc4r::Helpers.sym_score(build), self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def download_file(bt,number,file,options = {})
|
76
|
+
default_options = {:with_progress => true, :destination => File.expand_path("./#{File.basename(file)}")}
|
77
|
+
options = default_options.merge(options)
|
78
|
+
|
79
|
+
download_parameters = {:buffer => true}
|
80
|
+
if options[:with_progress]
|
81
|
+
download_parameters[:progress] = progress_bar
|
82
|
+
end
|
83
|
+
|
84
|
+
build = build(bt,number)
|
85
|
+
f = Nestful.get download_url("#{bt}/#{build.id}:id/#{file}"), merge_options( download_parameters )
|
86
|
+
f.close
|
87
|
+
FileUtils.mv(f.path,options[:destination])
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def progress_bar
|
92
|
+
Proc.new do |conn, total, size|
|
93
|
+
@progress ||= Commander::UI::ProgressBar.new total, :title => "Downloading Build", :complete_message => "File download complete"
|
94
|
+
@last_pct ||= 0
|
95
|
+
current_pct = ((size.to_f/total.to_f)*100).floor
|
96
|
+
@progress.instance_variable_set('@step',size)
|
97
|
+
if current_pct != @last_pct
|
98
|
+
@progress.show
|
99
|
+
@last_pct = current_pct
|
100
|
+
end
|
101
|
+
|
102
|
+
if @progress.finished?
|
103
|
+
@progress = nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/tc4r/helpers.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tc4r
|
2
|
+
module Helpers
|
3
|
+
def self.symbolize(obj)
|
4
|
+
return obj.inject({}){|memo,(k,v)| memo[k.to_sym] = symbolize(v); memo} if obj.is_a? Hash
|
5
|
+
return obj.inject([]){|memo,v | memo << symbolize(v); memo} if obj.is_a? Array
|
6
|
+
return obj
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.underscore(obj)
|
10
|
+
obj.gsub(/::/, '/').
|
11
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
12
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
13
|
+
tr("-", "_").
|
14
|
+
downcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.sym_score(obj)
|
18
|
+
return obj.inject({}){|memo,(k,v)| memo[k.underscore.to_sym] = symbolize(v); memo} if obj.is_a? Hash
|
19
|
+
return obj
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/tc4r/version.rb
ADDED
data/lib/tc4r_base.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'tc4r'
|
2
|
+
require 'terminal-table'
|
3
|
+
|
4
|
+
# :name is optional, otherwise uses the basename of this executable
|
5
|
+
program :name, 'tc4r'
|
6
|
+
program :version, '1.0.0'
|
7
|
+
program :description, 'Teamcity Ruby Client'
|
8
|
+
|
9
|
+
default_command :useage
|
10
|
+
|
11
|
+
command :useage do |c|
|
12
|
+
c.syntax = 'tc4r useage'
|
13
|
+
c.description = 'Get useage'
|
14
|
+
|
15
|
+
c.action do |args, options|
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_config(file)
|
21
|
+
if File.exist? File.expand_path(file)
|
22
|
+
return Tc4r::Helpers.symbolize(YAML.load(File.read(File.expand_path(file))))
|
23
|
+
else
|
24
|
+
abort ("Configuration file does not exist #{file}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
global_option('-c', '--config FILE', 'Load config data for your commands to use') do |file|
|
29
|
+
$config = load_config(file)
|
30
|
+
end
|
31
|
+
|
32
|
+
unless $config
|
33
|
+
$config = load_config('~/.teamcity.yml')
|
34
|
+
end
|
35
|
+
|
36
|
+
command :bt do |c|
|
37
|
+
c.syntax = 'tc4r bt'
|
38
|
+
c.description = 'List all build types'
|
39
|
+
c.option '--format FORMAT', String, 'Output format (TEXT)|JSON'
|
40
|
+
|
41
|
+
c.action do |args, options|
|
42
|
+
tc = Tc4r::Client.new($config)
|
43
|
+
format = options.format || 'text'
|
44
|
+
format = format.downcase.to_sym
|
45
|
+
|
46
|
+
case format
|
47
|
+
when :json
|
48
|
+
say tc.build_types.to_json
|
49
|
+
else
|
50
|
+
table = Terminal::Table.new :headings => ['ID','Name','Project'] do |t|
|
51
|
+
tc.build_types.each do |build|
|
52
|
+
t.add_row [build.id,build.name,build.project_name]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
puts table
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
command :builds do |c|
|
61
|
+
c.syntax = 'tc4r builds'
|
62
|
+
c.description = 'List all builds for a build type'
|
63
|
+
c.option '--bt BUILD_TYPE_ID', String, 'The build type ID to list builds for'
|
64
|
+
c.option '--format FORMAT', String, 'Output format (TEXT)|JSON'
|
65
|
+
c.option '--status STRING', String, 'Status of the build (BOTH)|ERROR|SUCCESS'
|
66
|
+
|
67
|
+
c.action do |args, options|
|
68
|
+
options.default :format => 'text'
|
69
|
+
options.default :status => 'both'
|
70
|
+
|
71
|
+
tc = Tc4r::Client.new($config)
|
72
|
+
|
73
|
+
format = options.format.downcase.to_sym
|
74
|
+
|
75
|
+
params = {}
|
76
|
+
|
77
|
+
status = options.status
|
78
|
+
status = status.downcase.to_sym
|
79
|
+
|
80
|
+
case status
|
81
|
+
when :error
|
82
|
+
params[:status] = :error
|
83
|
+
when :success
|
84
|
+
params[:status] = :success
|
85
|
+
end
|
86
|
+
|
87
|
+
case format
|
88
|
+
when :json
|
89
|
+
say tc.build_type(options.bt).builds.to_json
|
90
|
+
else
|
91
|
+
table = Terminal::Table.new :headings => ['ID','Number','Status','Start Date'] do |t|
|
92
|
+
tc.build_type(options.bt).builds.each do |build|
|
93
|
+
t.add_row [build.id,build.number,build.status,build.start_date]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
puts table
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
command :download do |c|
|
103
|
+
c.syntax = 'tc4r download'
|
104
|
+
c.description = 'Download a file from the build'
|
105
|
+
c.option '--bt BUILD_TYPE_ID', String, 'The build type ID to list builds for'
|
106
|
+
c.option '--number NUMBER', String, 'The build version number'
|
107
|
+
c.option '--file FILE', String, 'The file to download'
|
108
|
+
c.option '--dest FILE', String, 'The destination file name'
|
109
|
+
|
110
|
+
c.action do |args, options|
|
111
|
+
tc = Tc4r::Client.new($config)
|
112
|
+
bt = tc.build_type(options.bt)
|
113
|
+
build = bt.build(options.number)
|
114
|
+
download_options = {}
|
115
|
+
download_options[:destination] = options.dest if options.dest
|
116
|
+
|
117
|
+
tc.download_file(options.bt,options.number,options.file, download_options)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
data/lib/tc4r_setup.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'tc4r'
|
2
|
+
require 'commander/import'
|
3
|
+
|
4
|
+
# :name is optional, otherwise uses the basename of this executable
|
5
|
+
program :name, 'tc4r-setup'
|
6
|
+
program :version, '1.0.0'
|
7
|
+
program :description, 'Teamcity Ruby Client Setup Utility'
|
8
|
+
|
9
|
+
|
10
|
+
command :setup do |c|
|
11
|
+
c.syntax = 'tc4r bt'
|
12
|
+
c.description = 'List all build types'
|
13
|
+
c.option '--server SERVER', String, 'Teamcity Server'
|
14
|
+
c.option '--port PORT', Integer, 'The port to connect to'
|
15
|
+
c.option '--username USERNAME', String, 'Your teamcity username'
|
16
|
+
c.option '--password PASSWORD', String, 'Your teamcity password'
|
17
|
+
c.option '--transport (HTTP|HTTPS)', String, 'The transport to connect to teamcity'
|
18
|
+
|
19
|
+
c.action do |args, options|
|
20
|
+
if File.exist? File.expand_path('~/.teamcity.yml')
|
21
|
+
old_config = YAML.load(File.read(File.expand_path('~/.teamcity.yml')))
|
22
|
+
else
|
23
|
+
old_config = { 'server' => 'localhost',
|
24
|
+
'port' => 8111,
|
25
|
+
'transport' => 'http' }
|
26
|
+
end
|
27
|
+
|
28
|
+
c = {}
|
29
|
+
c['server'] = options.server || ask("Teamcity Server [#{old_config['server']}]: ")
|
30
|
+
c['port'] = options.port || ask("Port[#{old_config ['port']}]: ").to_i
|
31
|
+
c['transport'] = options.transport || choice = choose("Transport:", 'http', 'https')
|
32
|
+
c['username'] = options.username || ask("Username [#{old_config['username']}]: ")
|
33
|
+
c['password'] = options.password || ask("Password: ") { |q| q.echo = "*" }
|
34
|
+
|
35
|
+
c.each do |k,v|
|
36
|
+
if v.is_a? String and v.empty?
|
37
|
+
c[k] = old_config[k]
|
38
|
+
elsif v.is_a? Fixnum and v.eql? 0
|
39
|
+
c[k] = old_config[k]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
File.open(File.expand_path('~/.teamcity.yml'), "w") {|file|
|
44
|
+
YAML.dump(c,file)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require_relative 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Tc4r::Client do
|
4
|
+
let(:client) { Tc4r::Client.new( :username => 'username', :password => 'password') }
|
5
|
+
|
6
|
+
it 'should initialize and setup attr_readers' do
|
7
|
+
client = Tc4r::Client.new(:server => 'notlocalhost',
|
8
|
+
:port => 8112,
|
9
|
+
:username => 'username',
|
10
|
+
:password => 'password',
|
11
|
+
:transport => :https)
|
12
|
+
client.server.should == 'notlocalhost'
|
13
|
+
client.port.should == 8112
|
14
|
+
client.password.should == 'password'
|
15
|
+
client.transport.should == :https
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should merge options into defaults' do
|
19
|
+
client = Tc4r::Client.new( :port => 8112,
|
20
|
+
:username => 'username',
|
21
|
+
:password => 'password')
|
22
|
+
client.port.should == 8112
|
23
|
+
client.server.should == 'localhost'
|
24
|
+
client.username.should == 'username'
|
25
|
+
client.password.should == 'password'
|
26
|
+
client.transport.should == :http
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should generate urls' do
|
30
|
+
client = Tc4r::Client.new()
|
31
|
+
client.base_url.should == 'http://localhost:8111/httpAuth'
|
32
|
+
client.rest_url('some_endpoint').should == 'http://localhost:8111/httpAuth/app/rest/some_endpoint'
|
33
|
+
client.download_url('some_endpoint').should == 'http://localhost:8111/httpAuth/repository/download/some_endpoint'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should merge global parameters' do
|
37
|
+
options = client.merge_options(:test_parameter => 'test')
|
38
|
+
options[:test_parameter].should == 'test'
|
39
|
+
options[:user].should == 'username'
|
40
|
+
options[:password].should == 'password'
|
41
|
+
options[:auth_type].should == :basic
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should query for successful builds for a build type' do
|
45
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds?status=SUCCESS", :body => File.read('spec/requests/builds_bt1.json'), :content_type => "application/json")
|
46
|
+
build_types = client.query_builds 'bt1', :status => :success
|
47
|
+
FakeWeb.should have_requested(:get, 'http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds?status=SUCCESS')
|
48
|
+
build_types.each do |b|
|
49
|
+
b.should be_a_kind_of Tc4r::Build
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should query for errored builds for a build type' do
|
54
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds?status=ERROR", :body => File.read('spec/requests/builds_bt1.json'), :content_type => "application/json")
|
55
|
+
build_types = client.query_builds 'bt1', :status => :error
|
56
|
+
FakeWeb.should have_requested(:get, 'http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds?status=ERROR')
|
57
|
+
build_types.each do |b|
|
58
|
+
b.should be_a_kind_of Tc4r::Build
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
it 'should query build types' do
|
64
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes", :body => File.read('spec/requests/build_types.json'), :content_type => "application/json")
|
65
|
+
build_types = client.build_types
|
66
|
+
FakeWeb.should have_requested(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes")
|
67
|
+
build_types.each do |bt|
|
68
|
+
bt.should be_a_kind_of Tc4r::BuildType
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should query builds for a build type' do
|
73
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds", :body => File.read('spec/requests/builds_bt1.json'), :content_type => "application/json")
|
74
|
+
build_types = client.query_builds 'bt1'
|
75
|
+
FakeWeb.should have_requested(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds")
|
76
|
+
build_types.each do |b|
|
77
|
+
b.should be_a_kind_of Tc4r::Build
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should get a specific build number' do
|
82
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds/number:3.0.85", :body => File.read('spec/requests/build_5733.json'), :content_type => "application/json")
|
83
|
+
build = client.build 'bt1', '3.0.85'
|
84
|
+
FakeWeb.should have_requested(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds/number:3.0.85")
|
85
|
+
build.should be_a_kind_of Tc4r::Build
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should download a build to a specific destination' do
|
89
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds/number:3.0.85", :body => File.read('spec/requests/build_5733.json'), :content_type => "application/json")
|
90
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/repository/download/bt1/5733:id/test.zip", :body => {}.to_json, :content_length => 1234 )
|
91
|
+
FileUtils.stub(:mv) {}
|
92
|
+
FileUtils.should_receive(:mv).with(kind_of(String),'/tmp/test.zip')
|
93
|
+
client.download_file 'bt1', '3.0.85', 'test.zip', {:destination => '/tmp/test.zip'}
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should download a build to a my working directory' do
|
97
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/app/rest/buildTypes/id:bt1/builds/number:3.0.85", :body => File.read('spec/requests/build_5733.json'), :content_type => "application/json")
|
98
|
+
FakeWeb.register_uri(:get, "http://username:password@localhost:8111/httpAuth/repository/download/bt1/5733:id/test.zip", :body => {}.to_json, :content_length => 1234 )
|
99
|
+
FileUtils.stub(:mv) {}
|
100
|
+
FileUtils.should_receive(:mv).with(kind_of(String),File.expand_path('./test.zip'))
|
101
|
+
client.download_file 'bt1', '3.0.85', 'test.zip'
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":5733,"number":"3.0.85","status":"SUCCESS","href":"/httpAuth/app/rest/builds/id:5733","webUrl":"http://localhost:8111/viewLog.html?buildId=5733&buildTypeId=bt22","personal":false,"history":false,"pinned":false,"statusText":"Tests passed: 258","buildType":{"id":"bt1","name":"Product","href":"/httpAuth/app/rest/buildTypes/id:bt1","projectName":"Product","projectId":"project4","webUrl":"http://localhost:8111/viewType.html?buildTypeId=bt22"},"startDate":"20120824T094107-0700","finishDate":"20120824T095006-0700","agent":{"href":"/httpAuth/app/rest/agents/id:15","id":15,"name":"localhost"},"tags":null,"properties":null,"snapshot-dependencies":null,"artifact-dependencies":null,"revisions":{"revision":[{"version":"69748fea9e0aaf358ba227060107c4025cd6fb47","vcs-root-instance":{"id":"4843","vcs-root-id":"58","name":"rails","href":"/httpAuth/app/rest/vcs-roots/id:58/instances/id:4843"}}]},"triggered":{"type":"vcs","details":"jetbrains.git","date":"20120824T094107-0700"},"changes":{"count":2,"href":"/httpAuth/app/rest/changes?build=id:5733"}}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"buildType":[
|
3
|
+
{
|
4
|
+
"id":"bt1",
|
5
|
+
"name":"Code Analysis",
|
6
|
+
"href":"/httpAuth/app/rest/buildTypes/id:bt1",
|
7
|
+
"projectName":"Code Analysis",
|
8
|
+
"projectId":"project1",
|
9
|
+
"webUrl":"http://localhost:8111/viewType.html?buildTypeId=bt1"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"id":"bt2",
|
13
|
+
"name":"Product",
|
14
|
+
"href":"/httpAuth/app/rest/buildTypes/id:bt3",
|
15
|
+
"projectName":"Product",
|
16
|
+
"projectId":"project2",
|
17
|
+
"webUrl":"http://localhost:8111/viewType.html?buildTypeId=bt2"
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"id":"bt3",
|
21
|
+
"name":"Tools",
|
22
|
+
"href":"/httpAuth/app/rest/buildTypes/id:bt2",
|
23
|
+
"projectName":"Tools",
|
24
|
+
"projectId":"project3",
|
25
|
+
"webUrl":"http://localhost:8111/viewType.html?buildTypeId=bt3"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"id":"bt4",
|
29
|
+
"name":"Deployment",
|
30
|
+
"href":"/httpAuth/app/rest/buildTypes/id:bt6",
|
31
|
+
"projectName":"Deployment",
|
32
|
+
"projectId":"project4",
|
33
|
+
"webUrl":"http://localhost:8111/viewType.html?buildTypeId=bt4"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
@@ -0,0 +1,167 @@
|
|
1
|
+
{
|
2
|
+
"count":18,
|
3
|
+
"build":[
|
4
|
+
{
|
5
|
+
"id":5733,
|
6
|
+
"number":"3.0.85",
|
7
|
+
"status":"SUCCESS",
|
8
|
+
"buildTypeId":"bt1",
|
9
|
+
"startDate":"20120824T094107-0700",
|
10
|
+
"href":"/httpAuth/app/rest/builds/id:5733",
|
11
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5733&buildTypeId=bt1"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"id":5731,
|
15
|
+
"number":"3.0.84",
|
16
|
+
"status":"SUCCESS",
|
17
|
+
"buildTypeId":"bt1",
|
18
|
+
"startDate":"20120823T163729-0700",
|
19
|
+
"href":"/httpAuth/app/rest/builds/id:5731",
|
20
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5731&buildTypeId=bt1"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"id":5730,
|
24
|
+
"number":"3.0.83",
|
25
|
+
"status":"FAILURE",
|
26
|
+
"buildTypeId":"bt1",
|
27
|
+
"startDate":"20120823T155053-0700",
|
28
|
+
"href":"/httpAuth/app/rest/builds/id:5730",
|
29
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5730&buildTypeId=bt1"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"id":5724,
|
33
|
+
"number":"3.0.82",
|
34
|
+
"status":"SUCCESS",
|
35
|
+
"buildTypeId":"bt1",
|
36
|
+
"startDate":"20120823T114241-0700",
|
37
|
+
"href":"/httpAuth/app/rest/builds/id:5724",
|
38
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5724&buildTypeId=bt1"
|
39
|
+
},
|
40
|
+
{
|
41
|
+
"id":5720,
|
42
|
+
"number":"3.0.80",
|
43
|
+
"status":"SUCCESS",
|
44
|
+
"buildTypeId":"bt1",
|
45
|
+
"startDate":"20120822T202718-0700",
|
46
|
+
"href":"/httpAuth/app/rest/builds/id:5720",
|
47
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5720&buildTypeId=bt1"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"id":5719,
|
51
|
+
"number":"3.0.79",
|
52
|
+
"status":"SUCCESS",
|
53
|
+
"buildTypeId":"bt1",
|
54
|
+
"startDate":"20120822T201451-0700",
|
55
|
+
"href":"/httpAuth/app/rest/builds/id:5719",
|
56
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5719&buildTypeId=bt1"
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"id":5717,
|
60
|
+
"number":"1.0.78",
|
61
|
+
"status":"SUCCESS",
|
62
|
+
"buildTypeId":"bt1",
|
63
|
+
"startDate":"20120822T193726-0700",
|
64
|
+
"href":"/httpAuth/app/rest/builds/id:5717",
|
65
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5717&buildTypeId=bt1"
|
66
|
+
},
|
67
|
+
{
|
68
|
+
"id":5716,
|
69
|
+
"number":"1.0.77",
|
70
|
+
"status":"FAILURE",
|
71
|
+
"buildTypeId":"bt1",
|
72
|
+
"startDate":"20120822T165610-0700",
|
73
|
+
"href":"/httpAuth/app/rest/builds/id:5716",
|
74
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5716&buildTypeId=bt1"
|
75
|
+
},
|
76
|
+
{
|
77
|
+
"id":5715,
|
78
|
+
"number":"1.0.76",
|
79
|
+
"status":"FAILURE",
|
80
|
+
"buildTypeId":"bt1",
|
81
|
+
"startDate":"20120822T165101-0700",
|
82
|
+
"href":"/httpAuth/app/rest/builds/id:5715",
|
83
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5715&buildTypeId=bt1"
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"id":5369,
|
87
|
+
"number":"1.0.30",
|
88
|
+
"status":"ERROR",
|
89
|
+
"buildTypeId":"bt1",
|
90
|
+
"startDate":"20120628T134853-0700",
|
91
|
+
"href":"/httpAuth/app/rest/builds/id:5369",
|
92
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5369&buildTypeId=bt1"
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"id":5368,
|
96
|
+
"number":"1.0.29",
|
97
|
+
"status":"ERROR",
|
98
|
+
"buildTypeId":"bt1",
|
99
|
+
"startDate":"20120628T134635-0700",
|
100
|
+
"href":"/httpAuth/app/rest/builds/id:5368",
|
101
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5368&buildTypeId=bt1"
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"id":5362,
|
105
|
+
"number":"1.0.27",
|
106
|
+
"status":"ERROR",
|
107
|
+
"buildTypeId":"bt1",
|
108
|
+
"startDate":"20120628T100316-0700",
|
109
|
+
"href":"/httpAuth/app/rest/builds/id:5362",
|
110
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5362&buildTypeId=bt1"
|
111
|
+
},
|
112
|
+
{
|
113
|
+
"id":5361,
|
114
|
+
"number":"1.0.26",
|
115
|
+
"status":"ERROR",
|
116
|
+
"buildTypeId":"bt1",
|
117
|
+
"startDate":"20120628T095945-0700",
|
118
|
+
"href":"/httpAuth/app/rest/builds/id:5361",
|
119
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5361&buildTypeId=bt1"
|
120
|
+
},
|
121
|
+
{
|
122
|
+
"id":5360,
|
123
|
+
"number":"1.0.25",
|
124
|
+
"status":"ERROR",
|
125
|
+
"buildTypeId":"bt1",
|
126
|
+
"startDate":"20120628T095039-0700",
|
127
|
+
"href":"/httpAuth/app/rest/builds/id:5360",
|
128
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5360&buildTypeId=bt1"
|
129
|
+
},
|
130
|
+
{
|
131
|
+
"id":5359,
|
132
|
+
"number":"1.0.24",
|
133
|
+
"status":"ERROR",
|
134
|
+
"buildTypeId":"bt1",
|
135
|
+
"startDate":"20120628T094752-0700",
|
136
|
+
"href":"/httpAuth/app/rest/builds/id:5359",
|
137
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5359&buildTypeId=bt1"
|
138
|
+
},
|
139
|
+
{
|
140
|
+
"id":5358,
|
141
|
+
"number":"1.0.23",
|
142
|
+
"status":"ERROR",
|
143
|
+
"buildTypeId":"bt1",
|
144
|
+
"startDate":"20120628T094616-0700",
|
145
|
+
"href":"/httpAuth/app/rest/builds/id:5358",
|
146
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5358&buildTypeId=bt1"
|
147
|
+
},
|
148
|
+
{
|
149
|
+
"id":5357,
|
150
|
+
"number":"1.0.22",
|
151
|
+
"status":"ERROR",
|
152
|
+
"buildTypeId":"bt1",
|
153
|
+
"startDate":"20120628T094510-0700",
|
154
|
+
"href":"/httpAuth/app/rest/builds/id:5357",
|
155
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5357&buildTypeId=bt1"
|
156
|
+
},
|
157
|
+
{
|
158
|
+
"id":5356,
|
159
|
+
"number":"1.0.21",
|
160
|
+
"status":"ERROR",
|
161
|
+
"buildTypeId":"bt1",
|
162
|
+
"startDate":"20120628T083310-0700",
|
163
|
+
"href":"/httpAuth/app/rest/builds/id:5356",
|
164
|
+
"webUrl":"http://localhost:8111/viewLog.html?buildId=5356&buildTypeId=bt1"
|
165
|
+
}
|
166
|
+
]
|
167
|
+
}
|
data/spec/spec_helper.rb
ADDED
data/tc4r.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/tc4r/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Paul Morton"]
|
6
|
+
gem.email = ["pmorton@biaprotect.com"]
|
7
|
+
gem.description = %q{Teamcity Client for Ruby}
|
8
|
+
gem.summary = %q{A Teamcity Client for Ruby}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "tc4r"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.bindir = ['bin']
|
17
|
+
gem.executables = ['tc', 'tc-setup']
|
18
|
+
gem.version = Tc4r::VERSION
|
19
|
+
gem.add_dependency 'commander'
|
20
|
+
gem.add_dependency "nestful"
|
21
|
+
gem.add_dependency 'terminal-table'
|
22
|
+
gem.add_dependency 'activemodel'
|
23
|
+
|
24
|
+
gem.add_development_dependency 'rspec'
|
25
|
+
gem.add_development_dependency 'fakeweb'
|
26
|
+
gem.add_development_dependency 'fakeweb-matcher'
|
27
|
+
gem.add_development_dependency 'simplecov'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tc4r
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Morton
|
9
|
+
autorequire:
|
10
|
+
bindir:
|
11
|
+
- bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-08-27 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: commander
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: nestful
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: terminal-table
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: activemodel
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: rspec
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :development
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: fakeweb
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: fakeweb-matcher
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: simplecov
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
type: :development
|
136
|
+
prerelease: false
|
137
|
+
version_requirements: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
description: Teamcity Client for Ruby
|
144
|
+
email:
|
145
|
+
- pmorton@biaprotect.com
|
146
|
+
executables:
|
147
|
+
- tc
|
148
|
+
- tc-setup
|
149
|
+
extensions: []
|
150
|
+
extra_rdoc_files: []
|
151
|
+
files:
|
152
|
+
- .gitignore
|
153
|
+
- Gemfile
|
154
|
+
- LICENSE
|
155
|
+
- README.md
|
156
|
+
- Rakefile
|
157
|
+
- bin/tc
|
158
|
+
- bin/tc-setup
|
159
|
+
- lib/tc4r.rb
|
160
|
+
- lib/tc4r/build.rb
|
161
|
+
- lib/tc4r/build_type.rb
|
162
|
+
- lib/tc4r/client.rb
|
163
|
+
- lib/tc4r/helpers.rb
|
164
|
+
- lib/tc4r/version.rb
|
165
|
+
- lib/tc4r_base.rb
|
166
|
+
- lib/tc4r_setup.rb
|
167
|
+
- spec/client_spec.rb
|
168
|
+
- spec/requests/build_5733.json
|
169
|
+
- spec/requests/build_types.json
|
170
|
+
- spec/requests/builds_bt1.json
|
171
|
+
- spec/spec_helper.rb
|
172
|
+
- spec/tc_client_spec.rb
|
173
|
+
- tc4r.gemspec
|
174
|
+
homepage: ''
|
175
|
+
licenses: []
|
176
|
+
post_install_message:
|
177
|
+
rdoc_options: []
|
178
|
+
require_paths:
|
179
|
+
- lib
|
180
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
181
|
+
none: false
|
182
|
+
requirements:
|
183
|
+
- - ! '>='
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
none: false
|
188
|
+
requirements:
|
189
|
+
- - ! '>='
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
requirements: []
|
193
|
+
rubyforge_project:
|
194
|
+
rubygems_version: 1.8.24
|
195
|
+
signing_key:
|
196
|
+
specification_version: 3
|
197
|
+
summary: A Teamcity Client for Ruby
|
198
|
+
test_files:
|
199
|
+
- spec/client_spec.rb
|
200
|
+
- spec/requests/build_5733.json
|
201
|
+
- spec/requests/build_types.json
|
202
|
+
- spec/requests/builds_bt1.json
|
203
|
+
- spec/spec_helper.rb
|
204
|
+
- spec/tc_client_spec.rb
|