teamcity-ruby-client 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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