teamcity-ruby-client 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +4 -0
  3. data/lib/teamcity/client.rb +2 -0
  4. data/lib/teamcity/client/build_types.rb +92 -0
  5. data/lib/teamcity/client/common.rb +13 -2
  6. data/lib/teamcity/client/projects.rb +82 -3
  7. data/lib/teamcity/client/vcs_roots.rb +62 -0
  8. data/lib/teamcity/configuration.rb +10 -2
  9. data/lib/teamcity/connection.rb +1 -0
  10. data/lib/teamcity/request.rb +10 -9
  11. data/lib/teamcity/version.rb +1 -1
  12. data/spec/cassettes/BuildTypes/DELETE/_delete_agent_requirement/should_delete_the_agent_requirement.yml +38 -0
  13. data/spec/cassettes/BuildTypes/DELETE/_delete_buildtype_parameter/should_delete_a_buildtype_parameter.yml +38 -0
  14. data/spec/cassettes/BuildTypes/POST/_attach_vcs_root/should_attach_a_vcs_root_to_a_buildtype.yml +45 -0
  15. data/spec/cassettes/BuildTypes/POST/_create_agent_requirement/should_create_an_agent_requirement_for_a_buildtype.yml +45 -0
  16. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_field/should_pause_a_project.yml +40 -0
  17. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_field/should_set_a_projects_description.yml +40 -0
  18. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_field/should_set_the_buildtype_name.yml +40 -0
  19. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_parameter/should_set_a_buildtype_parameter.yml +40 -0
  20. data/spec/cassettes/Projects/DELETE/_delete_project/should_delete_a_project.yml +79 -0
  21. data/spec/cassettes/Projects/DELETE/_delete_project_parameter/should_delete_a_project_parameter.yml +38 -0
  22. data/spec/cassettes/Projects/POST/_copy_project/should_copy_a_project.yml +86 -0
  23. data/spec/cassettes/Projects/POST/_create_project/should_create_a_project.yml +44 -0
  24. data/spec/cassettes/Projects/PUT/_set_project_field/should_archive_a_project.yml +40 -0
  25. data/spec/cassettes/Projects/PUT/_set_project_field/should_set_a_projects_description.yml +40 -0
  26. data/spec/cassettes/Projects/PUT/_set_project_field/should_set_a_projects_name.yml +40 -0
  27. data/spec/cassettes/Projects/PUT/_set_project_field/should_un-archive_a_project.yml +50 -0
  28. data/spec/cassettes/Projects/PUT/_set_project_parameter/should_set_a_project_parameter.yml +40 -0
  29. data/spec/cassettes/VCSRoots/GET/_vcs_root_details/should_fetch_the_vcs_root_details.yml +44 -0
  30. data/spec/cassettes/VCSRoots/GET/_vcs_roots/should_fetch_vcs_roots.yml +44 -0
  31. data/spec/cassettes/VCSRoots/POST/_create_vcs_root/should_create_a_shared_vcs_root.yml +45 -0
  32. data/spec/cassettes/VCSRoots/POST/_create_vcs_root/should_create_a_vcs_root_that_is_only_shared_within_a_project.yml +48 -0
  33. data/spec/spec_helper.rb +9 -0
  34. data/spec/teamcity/api_spec.rb +2 -0
  35. data/spec/teamcity/client/buildtypes_spec.rb +79 -6
  36. data/spec/teamcity/client/projects_spec.rb +85 -7
  37. data/spec/teamcity/client/vcs_roots_spec.rb +64 -0
  38. data/spec/teamcity_spec.rb +26 -0
  39. data/teamcity-ruby-client.gemspec +2 -1
  40. metadata +62 -3
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NGU0NzgwMGI5OGY5MmE3OWI3MWJhMDA0ODhlNDY3NjYzOGE2Yzk5ZA==
4
+ NmM2N2RlMmE3MDVlOTM4NjVlYmI5ZTgyNjRhNDAzY2FhNWM2YjZiYw==
5
5
  data.tar.gz: !binary |-
6
- YTc5ZDA0NDdjZmRjZDlkNTVmZmYyNWNiMGFiNTczNTQzZmFmZmZmMQ==
6
+ MzE2NGViZjYxNzNkY2VmY2ViYTliYzJmYWIwZGU0MDVkZGYyYjMyYg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- N2UzYjg1MGE5YTA1NmU1YjQ5NjkxMmJmNzY2YjE4YmUwZGVkOTRmNjNlOWU2
10
- YzQ5YmViNzQ1MWEyNWIxYmQyNjZiYzVlMDRlOTVjMTE5MjdkYmI2NWZjYzhi
11
- NjcwNzEwYmE5YWQ4NzAxYWY5ZjNmNjUxNjZmYTlhOTY1NTY3ZGI=
9
+ ZGI0MWYxNGY0YmU1ZDNhNzc3ZmVlODIxZTRmMjE0NGNkMTk4YjllMDNkZDY4
10
+ NDcxOTM3ZTg0ZGZjOWIxMWVhN2U1MDc1ZTQ2M2JmMWQxMGFkODBjMzRiNGMz
11
+ ZjZmM2E0YzlmOWIzNDdmYzg2YmY5MDNiYzdjZjczNTBlNzRlMWE=
12
12
  data.tar.gz: !binary |-
13
- ZjdlM2M3ZDI2ZDM3ZmU3OTgyZmI3NzM0ODAwNjExNDU4MTk5OGI1ZTliZDg3
14
- NTU1NTk4Y2EyYzk0ZGJmN2NjODEyYzdlZDYyZDhjY2UxYzI4YzYwYjE0ZjFk
15
- YzI3ZGEzYTc2ZGY1ZWQ1MDBkMjJiYmFlNDM4OWZhMDNiZDJiNDA=
13
+ ZDJhZTBjNzQ2NjU3MTcwOTFmYzY0MzU0M2NiOWM5YTU5ZWUwOTY1NjQzNmMw
14
+ YzdhNDYwYzBjMDY2ZWE0YzgwYzg4ODVmM2RmZWFlODQ5YTQyZjFiMmE4NjJi
15
+ OTM4ZTEwZTNkMzMzYjUzMTMzMjg3ZDg4Njg3ZTJhYjc2ZWFkZDQ=
data/README.md CHANGED
@@ -98,6 +98,10 @@ puts TeamCity.build(id: TeamCity.builds(count: 1).first.id).buildType.name # Fet
98
98
 
99
99
  ## Documentation
100
100
 
101
+ ### API Docs
102
+
103
+ [Latest](http://rubydoc.info/gems/teamcity-ruby-client/0.1.0/frames)
104
+
101
105
  ### Generating API Docs
102
106
 
103
107
  1. Pull the source down
@@ -1,4 +1,5 @@
1
1
  require_relative 'api'
2
+ require 'builder'
2
3
 
3
4
  module TeamCity
4
5
  # Wrapper for the TeamCity REST API
@@ -10,5 +11,6 @@ module TeamCity
10
11
  include TeamCity::Client::BuildTypes
11
12
  include TeamCity::Client::Builds
12
13
  include TeamCity::Client::Common
14
+ include TeamCity::Client::VCSRoots
13
15
  end
14
16
  end
@@ -88,6 +88,98 @@ module TeamCity
88
88
  make_method :snapshot_dependencies
89
89
  make_method :vcs_root_entries
90
90
 
91
+ # Attach a vcs root to a build type (build configuration_)
92
+ #
93
+ #
94
+ # @param buildtype_id [String] the buildtype id
95
+ # @param vcs_root_id [String, Numeric] id of vcs root
96
+ # @return [Hashie::Mash] vcs root object that was attached
97
+ def attach_vcs_root(buildtype_id, vcs_root_id)
98
+ builder = Builder::XmlMarkup.new
99
+ builder.tag!('vcs-root-entry'.to_sym) do |node|
100
+ node.tag!('vcs-root'.to_sym, :id => vcs_root_id)
101
+ end
102
+ post("buildTypes/#{buildtype_id}/vcs-root-entries") do |req|
103
+ req.headers['Content-Type'] = 'application/xml'
104
+ req.body = builder.target!
105
+ end
106
+ end
107
+
108
+ # Set a buildtype parameter (Create or Update)
109
+ #
110
+ #
111
+ # @param buildtype_id [String] the buildtype id
112
+ # @param parameter_name [String] name of the parameter to set
113
+ # @param parameter_value [String] value of the parameter
114
+ # @return [nil]
115
+ def set_buildtype_parameter(buildtype_id, parameter_name, parameter_value)
116
+ path = "buildTypes/#{buildtype_id}/parameters/#{parameter_name}"
117
+ put_text_request(path, parameter_value)
118
+ end
119
+
120
+ # Delete a buildtype parameter
121
+ #
122
+ # @param buildtype_id [String] the buildtype id
123
+ # @param parameter_name [String] name of the parameter to delete
124
+ # @return [nil]
125
+ def delete_buildtype_parameter(buildtype_id, parameter_name)
126
+ delete("buildTypes/#{buildtype_id}/parameters/#{parameter_name}") do |req|
127
+ # only accepts text/plain
128
+ req.headers['Accept'] = 'text/plain'
129
+ end
130
+ end
131
+
132
+ # Create a buildtype agent requirement (Create)
133
+ #
134
+ # @param buildtype_id [String] the buildtype id
135
+ # @param parameter_name [String] name of the parameter to set
136
+ # @param parameter_value [String] value of the parameter
137
+ # @param condition [String] the condition for which to check against
138
+ # @return [nil]
139
+ #
140
+ # @example Create a condition where a system property equals something
141
+ # TeamCity.create_agent_requirement('bt1', 'system.os.name', 'Linux', 'equals')
142
+ #
143
+ # @note Check the TeamCity UI for supported conditions
144
+ def create_agent_requirement(buildtype_id, parameter_name, parameter_value, condition)
145
+ builder = Builder::XmlMarkup.new
146
+ builder.tag!('agent-requirement'.to_sym, :id => parameter_name, :type => condition) do |node|
147
+ node.properties do |p|
148
+ p.property(:name => 'property-name', :value => parameter_name)
149
+ p.property(:name => 'property-value', :value => parameter_value)
150
+ end
151
+ end
152
+ post("buildTypes/#{buildtype_id}/agent-requirements") do |req|
153
+ req.headers['Content-Type'] = 'application/xml'
154
+ req.body = builder.target!
155
+ end
156
+ end
157
+
158
+ # Delete an agent requirement for a buildtype
159
+ #
160
+ # @param buildtype_id [String] the buildtype_id
161
+ # @param parameter_name [String] name of the requirement to delete
162
+ # @return [nil]
163
+ def delete_agent_requirement(buildtype_id, parameter_name)
164
+ delete("buildTypes/#{buildtype_id}/agent-requirements/#{parameter_name}")
165
+ end
166
+
167
+ # Set a buildtype field
168
+ #
169
+ # @example Change buildtype name
170
+ # TeamCity.set_buildtype_field('bt3', 'name', 'new-name')
171
+ # @example Set buildtype description
172
+ # TeamCity.set_buildtype_field('bt3', 'description', 'new-description')
173
+ # @example Pause/Unpause a buildtype
174
+ # Teamcity.set_buildtype_field('buildtype', 'paused', 'true|false')
175
+ #
176
+ # @param buidltype_id [String] the buildtype id
177
+ # @param field_name [String] the field name
178
+ # @param field_value [String] the value to set the field to
179
+ def set_buildtype_field(buildtype_id, field_name, field_value)
180
+ path = "buildTypes/#{buildtype_id}/#{field_name}"
181
+ put_text_request(path, field_value)
182
+ end
91
183
  end
92
184
  end
93
185
  end
@@ -13,11 +13,22 @@ module TeamCity
13
13
  # Take a list of locators to search on multiple criterias
14
14
  #
15
15
  def locator(options={})
16
- test = options.inject([]) do |locators, locator|
16
+ options.inject([]) do |locators, locator|
17
17
  key, value = locator
18
18
  locators << "#{key}:#{value}"
19
19
  end.join(',')
20
- test
20
+ end
21
+
22
+ # Put request helper where the body is text
23
+ #
24
+ # @param path [String] request path
25
+ # @param body [String] body contents of the request
26
+ # @return [nil]
27
+ def put_text_request(path, body)
28
+ put(path) do |req|
29
+ req.headers['Content-Type'] = 'text/plain'
30
+ req.body = body
31
+ end
21
32
  end
22
33
  end
23
34
  end
@@ -3,8 +3,6 @@ module TeamCity
3
3
  # Defines methods related to projects
4
4
  module Projects
5
5
 
6
- # HTTP GET
7
-
8
6
  # List of projects
9
7
  #
10
8
  # @return [Array<Hashie::Mash>, nil] of projects or nil if no projects exist
@@ -15,7 +13,8 @@ module TeamCity
15
13
 
16
14
  # Get project details
17
15
  #
18
- # @param options [Hash] option keys, :id => project_id
16
+ # @param options [Hash] The options hash,
17
+ # @option options [String] :id the project id
19
18
  # @return [Hashie::Mash] of project details
20
19
  def project(options={})
21
20
  assert_options(options)
@@ -41,6 +40,86 @@ module TeamCity
41
40
  response = get("projects/#{locator(options)}/parameters")
42
41
  response['property']
43
42
  end
43
+
44
+ # Create an empty project
45
+ #
46
+ # @param name [String] Name of the project
47
+ # @return [Hashie::Mash] project details
48
+ def create_project(name)
49
+ post("projects") do |req|
50
+ req.headers['Content-Type'] = 'text/plain'
51
+ req.body = name
52
+ end
53
+ end
54
+
55
+ # Copy another project
56
+ #
57
+ # @param source_project_id [String] id of the project you wish to copy
58
+ # @param target_project_name [String] name of the project you want to create
59
+ # @param options [Hash] copy project options
60
+ # @option options [Boolean] :copyAllAssociatedSettings copy all associated settings
61
+ # @options options[Boolean] :shareVCSRoots when true the vcs roots will be shared, otherwise they will be copied
62
+ # @return [Hashie::Mash] project details
63
+ def copy_project(source_project_id, target_project_name, options={})
64
+ attributes = {
65
+ :name => target_project_name,
66
+ :sourceProjectLocator => "id:#{source_project_id}",
67
+ }
68
+ post("projects") do |req|
69
+ req.headers['Content-Type'] = 'application/xml'
70
+ builder = Builder::XmlMarkup.new
71
+ builder.newProjectDescription(options.merge(attributes))
72
+ req.body = builder.target!
73
+ end
74
+ end
75
+
76
+ # Delete a project
77
+ #
78
+ # @param project_id [String] the id of the project
79
+ # @return [nil]
80
+ def delete_project(project_id)
81
+ delete("projects/#{project_id}")
82
+ end
83
+
84
+ # Delete a project parameter
85
+ #
86
+ # @param project_id [String] the project id
87
+ # @param parameter_name [String] name of the parameter to delete
88
+ # @return [nil]
89
+ def delete_project_parameter(project_id, parameter_name)
90
+ delete("projects/#{project_id}/parameters/#{parameter_name}") do |req|
91
+ # only accepts text/plain
92
+ req.headers['Accept'] = 'text/plain'
93
+ end
94
+ end
95
+
96
+ # Set a project parameter (Create or Update)
97
+ #
98
+ #
99
+ # @param project_id [String] the project id
100
+ # @param parameter_name [String] name of the parameter to set
101
+ # @param parameter_value [String] value of the parameter
102
+ def set_project_parameter(project_id, parameter_name, parameter_value)
103
+ path = "projects/#{project_id}/parameters/#{parameter_name}"
104
+ put_text_request(path, parameter_value)
105
+ end
106
+
107
+ # Set a project field
108
+ #
109
+ # @example Set a projects name
110
+ # TeamCity.set_project_field('project1', 'name', 'new-name')
111
+ # @example Set a projects description
112
+ # TeamCity.set_project_field('project1', 'description', 'new-description')
113
+ # @example Archive/Unarchive a project
114
+ # Teamcity.set_project_field('project1', 'archived', 'true|false')
115
+ #
116
+ # @param project_id [String] the project id
117
+ # @param field_name [String] the field name: 'name', 'description', 'archived'
118
+ # @param field_value [String] the value to set the field to
119
+ def set_project_field(project_id, field_name, field_value)
120
+ path = "projects/#{project_id}/#{field_name}"
121
+ put_text_request(path, field_value)
122
+ end
44
123
  end
45
124
  end
46
125
  end
@@ -0,0 +1,62 @@
1
+ module TeamCity
2
+ class Client
3
+ module VCSRoots
4
+
5
+ # List of VCS Roots
6
+ #
7
+ # @return [Array<Hashie::Mash>, nil] of vcs roots or nil if no vcs roots exist
8
+ def vcs_roots
9
+ response = get('vcs-roots')
10
+ response['vcs-root']
11
+ end
12
+
13
+ # Get VCS Root details
14
+ #
15
+ # @param vcs_root_id [String, Numeric]
16
+ # @return [Hashie::Mash]
17
+ def vcs_root_details(vcs_root_id)
18
+ get("vcs-roots/id:#{vcs_root_id}")
19
+ end
20
+
21
+ # Create VCS Root
22
+ #
23
+ # @param vcs_name [String] Name of the vcs root
24
+ # @param vcs_type [String] Type of VCS: 'git', 'perforce', etc
25
+ # @param options [Hash] VCS root options
26
+ # @option options [String] :projectLocator the project id (not required if :shared => true)
27
+ # @option options [Boolean] :shared whether the vcs root is shared across projects
28
+ # @yield [Hash] properties to set on the vcs root, view the page source of the vcs root page for the id and value of a property
29
+ # @return [Hashie::Mash] vcs root object that was created
30
+ #
31
+ # @example Create a Git VCS Root that pulls from master that is only shared within a project and uses the default private key
32
+ # TeamCity.create_vcs_root('my-git-vcs-root', 'git', :projectLocator => 'project2') do |properties|
33
+ # properties['branch'] = 'master'
34
+ # properties['url'] = 'git@github.com:jperry/teamcity-ruby-client.git'
35
+ # properties['authMethod'] = 'PRIVATE_KEY_DEFAULT'
36
+ # properties['ignoreKnownHosts'] = true
37
+ # end
38
+ def create_vcs_root(vcs_name, vcs_type, options = {}, &block)
39
+ attributes = {
40
+ :name => vcs_name,
41
+ :vcsName => "jetbrains.#{vcs_type}"
42
+ }
43
+ builder = Builder::XmlMarkup.new
44
+ builder.tag!('vcs-root'.to_sym, options.merge(attributes)) do |node|
45
+ node.properties do |p|
46
+ if block_given?
47
+ properties = {}
48
+ yield(properties)
49
+ properties.each do |name, value|
50
+ p.property(:name => name, :value => value)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ post("vcs-roots") do |req|
56
+ req.headers['Content-Type'] = 'application/xml'
57
+ req.body = builder.target!
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -7,17 +7,23 @@ module TeamCity
7
7
  :adapter,
8
8
  :endpoint,
9
9
  :user_agent,
10
- :format
10
+ :format,
11
+ :http_user,
12
+ :http_password
11
13
  ].freeze
12
14
 
13
15
  VALID_FORMATS = [:json].freeze
14
16
 
15
17
  DEFAULT_ADAPTER = Faraday.default_adapter
16
18
 
17
- DEFAULT_ENDPOINT = 'http://teamcity:8111/guestAuth/app/rest/7.0/'.freeze
19
+ DEFAULT_ENDPOINT = 'http://teamcity:8111/httpAuth/app/rest/7.0/'.freeze
18
20
 
19
21
  DEFAULT_USER_AGENT = "TeamCity Ruby Client #{TeamCity::VERSION}".freeze
20
22
 
23
+ DEFAULT_HTTP_USER = nil
24
+
25
+ DEFAULT_HTTP_PASSWORD = nil
26
+
21
27
  DEFAULT_FORMAT = :json
22
28
 
23
29
  attr_accessor *VALID_OPTIONS_KEYS
@@ -42,6 +48,8 @@ module TeamCity
42
48
  self.endpoint = DEFAULT_ENDPOINT
43
49
  self.user_agent = DEFAULT_USER_AGENT
44
50
  self.format = DEFAULT_FORMAT
51
+ self.http_user = DEFAULT_HTTP_USER
52
+ self.http_password = DEFAULT_HTTP_PASSWORD
45
53
  end
46
54
  end
47
55
  end
@@ -21,6 +21,7 @@ module TeamCity
21
21
  end
22
22
  connection.use FaradayMiddleware::NullResponseBody
23
23
  connection.adapter(adapter)
24
+ connection.basic_auth(http_user, http_password)
24
25
  end
25
26
  end
26
27
  end
@@ -2,30 +2,31 @@ module TeamCity
2
2
  # Defines HTTP request methods
3
3
  module Request
4
4
  # Perform an HTTP GET request
5
- def get(path, options={})
6
- request(:get, path, options)
5
+ def get(path, options={}, &block)
6
+ request(:get, path, options, &block)
7
7
  end
8
8
 
9
9
  # Perform an HTTP POST request
10
- def post(path, options={})
11
- request(:post, path, options)
10
+ def post(path, options={}, &block)
11
+ request(:post, path, options, &block)
12
12
  end
13
13
 
14
14
  # Perform an HTTP PUT request
15
- def put(path, options={})
16
- request(:put, path, options)
15
+ def put(path, options={}, &block)
16
+ request(:put, path, options, &block)
17
17
  end
18
18
 
19
19
  # Perform an HTTP DELETE request
20
- def delete(path, options={})
21
- request(:delete, path, options)
20
+ def delete(path, options={}, &block)
21
+ request(:delete, path, options, &block)
22
22
  end
23
23
 
24
24
  private
25
25
 
26
26
  # Perform an HTTP request
27
- def request(method, path, options)
27
+ def request(method, path, options, &block)
28
28
  response = connection.send(method) do |request|
29
+ block.call(request) if block_given?
29
30
  case method
30
31
  when :get, :delete
31
32
  request.url(path, options)
@@ -1,3 +1,3 @@
1
1
  module TeamCity
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,38 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: http://teamcity-ruby-client:teamcity@localhost:8111/httpAuth/app/rest/7.0/buildTypes/bt3/agent-requirements/test
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json; charset=utf-8
12
+ User-Agent:
13
+ - TeamCity Ruby Client 0.2.0
14
+ response:
15
+ status:
16
+ code: 204
17
+ message: No Content
18
+ headers:
19
+ Server:
20
+ - Apache-Coyote/1.1
21
+ Set-Cookie:
22
+ - JSESSIONID=7D5C309BD50232088662586230C9FE5B; Path=/; HttpOnly
23
+ - RememberMe=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
24
+ Pragma:
25
+ - no-cache
26
+ Expires:
27
+ - Thu, 01 Jan 1970 00:00:00 GMT
28
+ Cache-Control:
29
+ - no-cache
30
+ - no-store
31
+ Date:
32
+ - Mon, 06 May 2013 19:35:55 GMT
33
+ body:
34
+ encoding: US-ASCII
35
+ string: ''
36
+ http_version:
37
+ recorded_at: Mon, 06 May 2013 19:35:55 GMT
38
+ recorded_with: VCR 2.4.0