teamcity-ruby-client 1.1.0 → 1.2.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 (35) hide show
  1. checksums.yaml +8 -8
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +15 -3
  4. data/Guardfile +9 -0
  5. data/lib/teamcity.rb +1 -0
  6. data/lib/teamcity/client.rb +1 -2
  7. data/lib/teamcity/client/build_types.rb +94 -23
  8. data/lib/teamcity/client/projects.rb +37 -8
  9. data/lib/teamcity/client/vcs_roots.rb +9 -16
  10. data/lib/teamcity/element_builder.rb +27 -0
  11. data/lib/teamcity/version.rb +1 -1
  12. data/spec/cassettes/BuildTypes/POST/_attach_vcs_root/should_attach_a_vcs_root_to_a_buildtype.yml +12 -10
  13. data/spec/cassettes/BuildTypes/POST/_create_agent_requirement/should_create_an_agent_requirement_for_a_buildtype.yml +11 -11
  14. data/spec/cassettes/BuildTypes/POST/_create_build_step/should_create_a_build_step_for_a_given_build_type.yml +46 -0
  15. data/spec/cassettes/BuildTypes/POST/_create_build_trigger/should_create_a_build_trigger_for_a_given_build_type.yml +46 -0
  16. data/spec/cassettes/BuildTypes/POST/_create_buildtype/should_create_a_build_type.yml +86 -0
  17. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_setting/should_set_if_it_should_perform_clean_builds.yml +46 -0
  18. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_setting/should_set_what_is_the_timeout_in_minutes_when_executing_builds.yml +46 -0
  19. data/spec/cassettes/BuildTypes/PUT/_set_buildtype_setting/should_set_where_the_checkout_happens_when_building.yml +46 -0
  20. data/spec/cassettes/Projects/GET/_parent_project/should_fetch_the_parent_project_for_a_given_project.yml +46 -0
  21. data/spec/cassettes/Projects/GET/_parent_project/should_return_nil_if_there_is_no_parent_project_for_a_given_project.yml +46 -0
  22. data/spec/cassettes/Projects/POST/_copy_project/should_copy_a_project.yml +27 -24
  23. data/spec/cassettes/Projects/PUT/_set_parent_project/should_set_a_parent_project_for_a_given_project.yml +134 -0
  24. data/spec/cassettes/VCSRoots/POST/_create_vcs_root/should_create_a_git_vcs_root_that_is_shared_with_the_project_and_sub-projects.yml +89 -0
  25. data/spec/cassettes/VCSRoots/POST/_create_vcs_root/should_create_a_subversion_vcs_root_that_is_shared_with_the_project_and_sub-projects.yml +89 -0
  26. data/spec/teamcity/api_spec.rb +1 -1
  27. data/spec/teamcity/client/buildtypes_spec.rb +58 -2
  28. data/spec/teamcity/client/projects_spec.rb +36 -2
  29. data/spec/teamcity/client/vcs_roots_spec.rb +17 -3
  30. data/spec/teamcity/client_spec.rb +2 -2
  31. data/spec/teamcity/element_builder_spec.rb +30 -0
  32. data/spec/teamcity/headers_spec.rb +2 -2
  33. data/teamcity-ruby-client.gemspec +2 -3
  34. metadata +44 -33
  35. data/spec/cassettes/VCSRoots/POST/_create_vcs_root/should_create_a_vcs_root_that_is_shared_with_the_project_and_sub-projects.yml +0 -90
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDMzYTI1MjZhMzBkNDAyODIzMDdhY2ZkMWJjNTllZjc4NDQ2N2U1Nw==
4
+ NTkyNmMwZWJmYjU4MWRhNzkwNjQwOWMzYjZlNmIxZmVhZWE0NTIyMw==
5
5
  data.tar.gz: !binary |-
6
- YzJlNjc1ZWE0YTIxYmEyMjZhZmMyZTQ1NDdjYzg0ZGQ5MjZhMjMzZA==
6
+ NTkzYzA4NTNlZWQ5MjliYzU5ODkxYTMwOThmMmE5YTdhNzFjYjI0Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmNiZGQ3ZTM2NGQ3ZGJmOTJhNWI5NjgxNTczOTc0OTJiYmY4NDdhOWEyODky
10
- NTE2ZTQ4NzQzYzgyOWQwMGQ5Zjg3NWRiNjE4MmI3NDQzYWM0YzkzYjdkYjQ5
11
- ZmUzNDc3NDczMzFmOWI0ZWRlOTdiZDgyMTA3YjU4MTY2ZDk4NjI=
9
+ YWM1NWY4NDA2YzU3Y2U5NTNhNTA3ZGI0ZDNkYTkyOWQ5ZjdmMDQ3MTc4Njgx
10
+ NDMzODRhYzJiNWZjZWNlYjc3Njc4ZDQ1ZDQzZDRiYjViOGQxNDM5OGI5OGNh
11
+ YTJhOTZjMTk0NGQ5MGJlNmNjZTNiYzNlYzQwNjIzMWU4MGUxYzE=
12
12
  data.tar.gz: !binary |-
13
- Nzk1MjM0MWIyOGYzOGVkMDYzYTUzZWNiOGRmODkzOTU0NTE2ZWM4MzA1OTRm
14
- NDc2MGY4NjIxMWYwMzU5ZTFmN2NiZjVlYzNkNWQzYTNlMjI4NDBkYmNjZTE1
15
- Mzk2NDRjMTIxNTFkOWVhNzRiYzgxMTNlMWEwYmZjZmQzMmQ5NzM=
13
+ YjJiNmE0YzU4NTllYzdlOTIxOWI3NDc2ZjMyOTM0NWM3NjkyZTBmNGJmMTkz
14
+ MjM5NDljMGI3ODVmMjNhY2YxNzhmNmM5ZDU1MWUzZTFiMjc5ZWM2OTE0YWRl
15
+ NjYxNTBiNmUwMDJlMWQzNmE3MTFiNDIzNzgwN2FhMDg4YmE3OTk=
@@ -0,0 +1 @@
1
+ --tag rest_api_version:"REST API VERSION"
@@ -1,12 +1,24 @@
1
+ ## 1.2.0 (Dec 7, 2013)
2
+
3
+ * BuildType: Added ```.set_buildtype_setting```, provides the ability to set build configuration settings [@jeffersongirao]
4
+ * BuildType: Added ```.create_buildtype```, provides the ability to create a new build configuration [@jeffersongirao]
5
+ * BuildType: Added ```.create_build_trigger```, provides the ability to create build configuration trigger [@jeffersongirao], [@nskboy]
6
+ * BuildType: Added ```.set_buildtype_setting```, adds ability to set build configuration settings [@jeffersongirao]
7
+ * BuildType: Added ```.create_build_step```, provides the ability to create a build step in a build configuration [@jeffersongirao]
8
+ * Project: Added ```.set_parent_project``` and ```.parent_project``` for setting and getting parent project. (TeamCity8 only) [@jeffersongirao]
9
+ * Bug: Fix ```.create_vcs_root``` to work for svn [@jeffersongirao]
10
+ * Cleanup: Remove dependency on xmlbuilder and linguistics [@jeffersongirao]
11
+ * Testing: Upgrade to rspec 2.14.1 and added guard-rspec gem
12
+ * Documentation: Added *rest_api_version* tag for specify teamcity api compatibility
13
+
1
14
  ## 1.1.0 (Nov 1, 2013)
2
15
 
3
16
  * Features:
4
17
  * Added ```build_artifacts``` (Provides the ability to fetch the
5
- contents of an aritfact), courtesy of [@orikremer](https://github.com/orikremer)
18
+ contents of an aritfact) [@orikremer]
6
19
 
7
20
  * Gem Updates
8
- * Upgraded webmock to remove deprecation warning, courtesy of
9
- [@akiellor](https://github.com/akiellor)
21
+ * Upgraded webmock to remove deprecation warning [@akiellor]
10
22
 
11
23
  ## 1.0.1 (Nov 1, 2013)
12
24
 
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ #
4
+
5
+ guard :rspec do
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+ end
@@ -1,6 +1,7 @@
1
1
  require_relative 'teamcity/configuration'
2
2
  require_relative 'teamcity/client'
3
3
  require_relative 'teamcity/headers'
4
+ require_relative 'teamcity/element_builder'
4
5
 
5
6
  module TeamCity
6
7
  extend Configuration
@@ -1,5 +1,4 @@
1
1
  require_relative 'api'
2
- require 'builder'
3
2
 
4
3
  module TeamCity
5
4
  # Wrapper for the TeamCity REST API
@@ -13,4 +12,4 @@ module TeamCity
13
12
  include TeamCity::Client::Common
14
13
  include TeamCity::Client::VCSRoots
15
14
  end
16
- end
15
+ end
@@ -1,12 +1,7 @@
1
- require 'linguistics'
2
-
3
1
  module TeamCity
4
2
  class Client
5
3
  # Defines methods related to build types (or build configurations)
6
4
  module BuildTypes
7
-
8
- Linguistics.use :en
9
-
10
5
  # HTTP GET
11
6
 
12
7
  # List of build types
@@ -26,6 +21,17 @@ module TeamCity
26
21
  get("buildTypes/#{locator(options)}")
27
22
  end
28
23
 
24
+ # Create a Build Configuration
25
+ #
26
+ # @param project_id [String] id of the project you are adding the build configuration
27
+ # @param name [String] name of the buildtype you wish to create
28
+ # @return [Hashie::Mash] of build configuration details
29
+ def create_buildtype(project_id, name)
30
+ post("projects/#{project_id}/buildTypes", :content_type => :text) do |req|
31
+ req.body = name
32
+ end
33
+ end
34
+
29
35
  # Get whether the build is paused or not
30
36
  #
31
37
  # @param options [Hash] option keys, :id => buildtype_id
@@ -87,10 +93,11 @@ module TeamCity
87
93
  define_method("buildtype_#{name}".to_sym) do |options|
88
94
  name_has_dashes = name.to_s.gsub('_', '-')
89
95
  assert_options(options)
90
- response = get("buildTypes/#{locator(options)}/#{name_has_dashes}")
91
- response[name_has_dashes.en.plural]
96
+ response = get("buildTypes/#{locator(options)}/#{name_has_dashes}", accept: :json)
97
+ response[response.keys.first]
92
98
  end
93
99
  end
100
+
94
101
  private_class_method :make_method
95
102
 
96
103
  make_method :features
@@ -108,13 +115,10 @@ module TeamCity
108
115
  # @param vcs_root_id [String, Numeric] id of vcs root
109
116
  # @return [Hashie::Mash] vcs root object that was attached
110
117
  def attach_vcs_root(buildtype_id, vcs_root_id)
111
- builder = Builder::XmlMarkup.new
112
- builder.tag!('vcs-root-entry'.to_sym) do |node|
113
- node.tag!('vcs-root'.to_sym, :id => vcs_root_id)
114
- end
115
- post("buildTypes/#{buildtype_id}/vcs-root-entries") do |req|
116
- req.headers['Content-Type'] = 'application/xml'
117
- req.body = builder.target!
118
+ payload = { 'vcs-root' => { :id => vcs_root_id } }
119
+
120
+ post("buildTypes/#{buildtype_id}/vcs-root-entries", :content_type => :json) do |req|
121
+ req.body = payload.to_json
118
122
  end
119
123
  end
120
124
 
@@ -155,16 +159,14 @@ module TeamCity
155
159
  #
156
160
  # @note Check the TeamCity UI for supported conditions
157
161
  def create_agent_requirement(buildtype_id, parameter_name, parameter_value, condition)
158
- builder = Builder::XmlMarkup.new
159
- builder.tag!('agent-requirement'.to_sym, :id => parameter_name, :type => condition) do |node|
160
- node.properties do |p|
161
- p.property(:name => 'property-name', :value => parameter_name)
162
- p.property(:name => 'property-value', :value => parameter_value)
163
- end
162
+ builder = TeamCity::ElementBuilder.new(:id => parameter_name, :type => condition) do |properties|
163
+ properties['property-name'] = parameter_name
164
+ properties['property-value'] = parameter_value
164
165
  end
166
+
165
167
  path = "buildTypes/#{buildtype_id}/agent-requirements"
166
- post(path, :accept => :json, :content_type => :xml) do |req|
167
- req.body = builder.target!
168
+ post(path, :accept => :json, :content_type => :json) do |req|
169
+ req.body = builder.to_request_body
168
170
  end
169
171
  end
170
172
 
@@ -197,6 +199,23 @@ module TeamCity
197
199
  end
198
200
  end
199
201
 
202
+ # Set buildtype settings
203
+ #
204
+ # @example Cleaning all files between the builds
205
+ # TeamCity.set_buildtype_setting('bt3', 'cleanBuild', 'true')
206
+ # @example Checkout on the server
207
+ # TeamCity.set_buildtype_setting('bt3', 'checkoutMode', 'ON_SERVER')
208
+ # @example Fail the build after 10 Minutes
209
+ # Teamcity.set_buildtype_setting('bt3', 'executionTimeoutMin', '10')
210
+ #
211
+ # @param buidltype_id [String] the buildtype id
212
+ # @param setting_name [String] the settings name
213
+ # @param setting_value [String] the value to set the settings to
214
+ # @return setting_value [String] value that was set
215
+ def set_buildtype_setting(buildtype_id, setting_name, setting_value)
216
+ set_buildtype_field(buildtype_id, "settings/#{setting_name}", setting_value)
217
+ end
218
+
200
219
  # Delete buildtype (build configuration)
201
220
  #
202
221
  # @param buildtype_id [String] the id of the buildtype
@@ -218,6 +237,58 @@ module TeamCity
218
237
  req.body = field_value
219
238
  end
220
239
  end
240
+
241
+ # Create Build Step
242
+ #
243
+ # @param buildtype_id [String] :buildtype_id to create the step under
244
+ # @option options [String] :name for the step definition (optional)
245
+ # @option options [String] :type Type of Build Step: 'Maven', 'Ant', etc
246
+ # @yield [Hash] properties to set on the step, view the official documentation for supported properties
247
+ # @return [Hashie::Mash] step object that was created
248
+ #
249
+ # @example Create a Maven2 step that executes the target verify
250
+ # TeamCity.create_build_step(:buildtype_id => 'my-build-type-id', :type => 'Maven', name: 'Unit Tests') do |properties|
251
+ # properties['goals'] = 'verify'
252
+ # properties['mavenSelection'] = 'mavenSelection:default'
253
+ # properties['pomLocation'] = 'pom.xml'
254
+ # end
255
+ def create_build_step(buildtype_id, options = {}, &block)
256
+ attributes = {
257
+ :type => options.fetch(:type),
258
+ :name => options.fetch(:name) { nil }
259
+ }
260
+
261
+ builder = TeamCity::ElementBuilder.new(attributes, &block)
262
+
263
+ post("buildTypes/#{buildtype_id}/steps", :content_type => :json) do |req|
264
+ req.body = builder.to_request_body
265
+ end
266
+ end
267
+
268
+ # Create Build Trigger
269
+ #
270
+ # @param buildtype_id [String] :buildtype_id to create the trigger under
271
+ # @option options [String] :type Type of Build Trigger: 'vcsTrigger', 'schedulingTrigger', etc
272
+ # @yield [Hash] properties to set on the trigger, view the official documentation for supported properties
273
+ # @return [Hashie::Mash] trigger object that was created
274
+ #
275
+ # @example Create a a VCS build trigger for checkins
276
+ # TeamCity.create_build_step(:buildtype_id => 'my-build-type-id', :type => 'vcsTrigger', name: 'Every Checkin') do |properties|
277
+ # properties['groupCheckkinsByCommitter'] = 'true'
278
+ # properties['perCheckinTriggering'] = 'true'
279
+ # properties['quietPeriodMode'] = 'DO_NOT_USE'
280
+ # end
281
+ def create_build_trigger(buildtype_id, options = {}, &block)
282
+ attributes = {
283
+ :type => options.fetch(:type),
284
+ }
285
+
286
+ builder = TeamCity::ElementBuilder.new(attributes, &block)
287
+
288
+ post("buildTypes/#{buildtype_id}/triggers", :content_type => :json) do |req|
289
+ req.body = builder.to_request_body
290
+ end
291
+ end
221
292
  end
222
293
  end
223
- end
294
+ end
@@ -41,6 +41,18 @@ module TeamCity
41
41
  response['property']
42
42
  end
43
43
 
44
+ # Get parent project
45
+ #
46
+ # @param (see #project)
47
+ # @return [Hashie::Mash] of the parent project details
48
+ # @rest_api_version >= 8.0
49
+ def parent_project(options={})
50
+ assert_options(options)
51
+ response = get("projects/#{locator(options)}/parentProject")
52
+ return nil if response['id'] == '_Root'
53
+ response
54
+ end
55
+
44
56
  # Create an empty project
45
57
  #
46
58
  # @param name [String] Name of the project
@@ -64,12 +76,11 @@ module TeamCity
64
76
  attributes = {
65
77
  :name => target_project_name
66
78
  }
67
- builder = Builder::XmlMarkup.new
68
- builder.tag!(:newProjectDescription ,options.merge(attributes)) do |node|
69
- node.tag!(:sourceProject, locator: source_project_id)
70
- end
71
- post("projects", :content_type => :xml) do |req|
72
- req.body = builder.target!
79
+
80
+ payload = { 'sourceProject' => { locator: source_project_id } }.merge(attributes)
81
+
82
+ post("projects", :content_type => :json, :accept => :json) do |req|
83
+ req.body = payload.to_json
73
84
  end
74
85
  end
75
86
 
@@ -80,7 +91,7 @@ module TeamCity
80
91
  def delete_project(project_id)
81
92
  delete("projects/#{project_id}")
82
93
  end
83
-
94
+
84
95
  # Delete a project parameter
85
96
  #
86
97
  # @param project_id [String] the project id
@@ -124,6 +135,24 @@ module TeamCity
124
135
  req.body = field_value
125
136
  end
126
137
  end
138
+
139
+ # Set a parent for a given project
140
+ #
141
+ # @example Set project1 as parent for project2
142
+ # TeamCity.set_parent_project('project2', 'project1')
143
+ #
144
+ # @param project_id [String] the project id
145
+ # @param parent_project_id [String] the parent project id
146
+ # @return [Hashie::Mash] of child project details
147
+ # @rest_api_version >= 8.0
148
+ def set_parent_project(project_id, parent_project_id)
149
+ path = "projects/#{project_id}/parentProject"
150
+ payload = { :id => parent_project_id }
151
+
152
+ put(path, :content_type => :json, :accept => :json) do |req|
153
+ req.body = payload.to_json
154
+ end
155
+ end
127
156
  end
128
157
  end
129
- end
158
+ end
@@ -2,6 +2,8 @@ module TeamCity
2
2
  class Client
3
3
  module VCSRoots
4
4
 
5
+ VCS_TYPES = { 'git' => 'jetbrains.git' }
6
+
5
7
  # List of VCS Roots
6
8
  #
7
9
  # @return [Array<Hashie::Mash>, nil] of vcs roots or nil if no vcs roots exist
@@ -36,25 +38,16 @@ module TeamCity
36
38
  def create_vcs_root(options = {}, &block)
37
39
  attributes = {
38
40
  :name => options.fetch(:vcs_name),
39
- :vcsName => "jetbrains.#{options.fetch(:vcs_type)}",
41
+ :vcsName => VCS_TYPES[options.fetch(:vcs_type)] || options.fetch(:vcs_type),
40
42
  :projectLocator => options.fetch(:project_id)
41
43
  }
42
- builder = Builder::XmlMarkup.new
43
- builder.tag!('vcs-root'.to_sym, attributes) do |node|
44
- node.properties do |p|
45
- if block_given?
46
- properties = {}
47
- yield(properties)
48
- properties.each do |name, value|
49
- p.property(:name => name, :value => value)
50
- end
51
- end
52
- end
53
- end
54
- post("vcs-roots", :content_type => :xml) do |req|
55
- req.body = builder.target!
44
+
45
+ builder = TeamCity::ElementBuilder.new(attributes, &block)
46
+
47
+ post("vcs-roots", :content_type => :json) do |req|
48
+ req.body = builder.to_request_body
56
49
  end
57
50
  end
58
51
  end
59
52
  end
60
- end
53
+ end
@@ -0,0 +1,27 @@
1
+ module TeamCity
2
+ class ElementBuilder
3
+ def initialize(attributes = {}, &block)
4
+ @payload = attributes
5
+
6
+ if block_given?
7
+ @payload['properties'] ||= {}
8
+ @payload['properties']['property'] ||= []
9
+
10
+ properties = {}
11
+
12
+ yield(properties)
13
+
14
+ properties.each do |name, value|
15
+ @payload['properties']['property'] << {
16
+ :name => name,
17
+ :value => value
18
+ }
19
+ end
20
+ end
21
+ end
22
+
23
+ def to_request_body
24
+ @payload.to_json
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module TeamCity
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -4,15 +4,17 @@ http_interactions:
4
4
  method: post
5
5
  uri: http://teamcity-ruby-client:teamcity@localhost:8111/httpAuth/app/rest/buildTypes/BuildTypeTests_PostBuildTypeTests/vcs-root-entries
6
6
  body:
7
- encoding: US-ASCII
8
- string: <vcs-root-entry><vcs-root id="teamcity_ruby_client"/></vcs-root-entry>
7
+ encoding: UTF-8
8
+ string: '{"vcs-root":{"id":"teamcity_ruby_client"}}'
9
9
  headers:
10
10
  User-Agent:
11
- - TeamCity Ruby Client 0.4.0
11
+ - TeamCity Ruby Client 1.1.0
12
12
  Accept:
13
13
  - application/json; charset=utf-8
14
14
  Content-Type:
15
- - application/xml
15
+ - application/json
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
18
  response:
17
19
  status:
18
20
  code: 200
@@ -22,7 +24,7 @@ http_interactions:
22
24
  - Apache-Coyote/1.1
23
25
  Set-Cookie:
24
26
  - RememberMe=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; HttpOnly
25
- - TCSESSIONID=2C57E65BDB7952BC8CE5ED7E65BCBB2E; Path=/; HttpOnly
27
+ - TCSESSIONID=5762F45291C27BA5471781C5667AE23A; Path=/; HttpOnly
26
28
  Pragma:
27
29
  - no-cache
28
30
  Expires:
@@ -35,11 +37,11 @@ http_interactions:
35
37
  Transfer-Encoding:
36
38
  - chunked
37
39
  Date:
38
- - Wed, 14 Aug 2013 13:26:41 GMT
40
+ - Wed, 27 Nov 2013 19:01:47 GMT
39
41
  body:
40
- encoding: US-ASCII
41
- string: ! '{"id":"teamcity_ruby_client","vcs-root":{"id":"teamcity_ruby_client","name":"teamcity
42
- ruby client","href":"/httpAuth/app/rest/vcs-roots/id:teamcity_ruby_client"},"checkout-rules":""}'
42
+ encoding: UTF-8
43
+ string: '{"id":"teamcity_ruby_client","vcs-root":{"id":"teamcity_ruby_client","name":"TeamCity
44
+ Ruby Client","href":"/httpAuth/app/rest/vcs-roots/id:teamcity_ruby_client"},"checkout-rules":""}'
43
45
  http_version:
44
- recorded_at: Wed, 14 Aug 2013 13:26:41 GMT
46
+ recorded_at: Wed, 27 Nov 2013 19:01:47 GMT
45
47
  recorded_with: VCR 2.4.0