teamcity-ruby-client 0.1.0 → 0.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 (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