teamcity-ruby-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +18 -0
  3. data/.rvmrc +48 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +153 -0
  8. data/Rakefile +16 -0
  9. data/lib/faraday/null_response_body.rb +17 -0
  10. data/lib/teamcity/api.rb +19 -0
  11. data/lib/teamcity/client/build_types.rb +93 -0
  12. data/lib/teamcity/client/builds.rb +36 -0
  13. data/lib/teamcity/client/common.rb +24 -0
  14. data/lib/teamcity/client/projects.rb +46 -0
  15. data/lib/teamcity/client.rb +14 -0
  16. data/lib/teamcity/configuration.rb +47 -0
  17. data/lib/teamcity/connection.rb +27 -0
  18. data/lib/teamcity/request.rb +40 -0
  19. data/lib/teamcity/version.rb +3 -0
  20. data/lib/teamcity.rb +24 -0
  21. data/spec/cassettes/BuildTypes/GET/_buildtype/should_fetch_the_details_of_a_buildtype_by_id.yml +49 -0
  22. data/spec/cassettes/BuildTypes/GET/_buildtype/should_raise_an_error_if_the_buildtype_does_not_exist.yml +50 -0
  23. data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_fetch_the_build_configuration_agent_requirements_for_a_buildtype.yml +44 -0
  24. data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_return_an_array.yml +44 -0
  25. data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_return_nil_if_there_are_no_agent_requirements_defined.yml +44 -0
  26. data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_fetch_the_build_configuration_artifact_dependencies_for_a_buildtype.yml +44 -0
  27. data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_return_an_array.yml +44 -0
  28. data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_return_nil_if_there_are_no_artifact_dependencies_defined.yml +44 -0
  29. data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_fetch_the_build_configuration_features_for_a_buildtype.yml +44 -0
  30. data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_return_an_array.yml +44 -0
  31. data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_return_nil_if_there_are_no_features_defined.yml +44 -0
  32. data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_fetch_the_build_configuration_parameters_for_a_buildtype.yml +44 -0
  33. data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_return_an_array.yml +44 -0
  34. data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_return_nil_if_there_are_no_parameters_defined.yml +44 -0
  35. data/spec/cassettes/BuildTypes/GET/_buildtype_settings/should_fetch_the_settings_for_a_given_buildtype.yml +44 -0
  36. data/spec/cassettes/BuildTypes/GET/_buildtype_settings/should_return_an_array.yml +44 -0
  37. data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_fetch_the_build_configuration_snapshot_dependencies_for_a_buildtype.yml +44 -0
  38. data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_return_an_array.yml +44 -0
  39. data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_return_nil_if_there_are_no_snapshot_dependencies_defined.yml +44 -0
  40. data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_fetch_the_build_configuration_steps_for_a_buildtype.yml +46 -0
  41. data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_return_an_array.yml +46 -0
  42. data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_return_nil_if_there_are_no_steps_defined.yml +44 -0
  43. data/spec/cassettes/BuildTypes/GET/_buildtype_template/should_raise_an_exception_if_the_response_is_not_due_to_a_template_not_assigned.yml +50 -0
  44. data/spec/cassettes/BuildTypes/GET/_buildtype_template/should_return_nil_if_the_buildtype_is_not_associated_with_a_template.yml +50 -0
  45. data/spec/cassettes/BuildTypes/GET/_buildtype_template/should_return_the_attributes_of_the_associated_template.yml +45 -0
  46. data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_fetch_the_build_configuration_triggers_for_a_buildtype.yml +44 -0
  47. data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_return_an_array.yml +44 -0
  48. data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_return_nil_if_there_are_no_triggers_defined.yml +44 -0
  49. data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_fetch_the_build_configuration_vcs_root_entries_for_a_buildtype.yml +45 -0
  50. data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_return_an_array.yml +45 -0
  51. data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_return_nil_if_there_are_no_vcs_root_entries_defined.yml +44 -0
  52. data/spec/cassettes/BuildTypes/GET/_buildtypes/should_fetch_all_the_buildtypes.yml +49 -0
  53. data/spec/cassettes/Builds/GET/_build/should_fetch_the_build_details.yml +49 -0
  54. data/spec/cassettes/Builds/GET/_build/should_raise_an_error_if_the_build_does_not_exist.yml +50 -0
  55. data/spec/cassettes/Builds/GET/_build_tags/should_fetch_the_build_tags.yml +44 -0
  56. data/spec/cassettes/Builds/GET/_build_tags/should_return_nil_if_there_are_no_build_tags_defined_for_a_build.yml +44 -0
  57. data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_filter_by_multiple_build_locators.yml +44 -0
  58. data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_filter_results_by_build_locators.yml +44 -0
  59. data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_search_by_locator.yml +44 -0
  60. data/spec/cassettes/Builds/GET/_builds/should_fetch_all_the_builds.yml +44 -0
  61. data/spec/cassettes/Projects/GET/_project/should_fetch_a_single_project_by_id.yml +47 -0
  62. data/spec/cassettes/Projects/GET/_project/should_raise_an_error_if_the_project_does_not_exist.yml +50 -0
  63. data/spec/cassettes/Projects/GET/_project_buildtypes/should_fetch_all_the_buildTypes_for_a_project.yml +45 -0
  64. data/spec/cassettes/Projects/GET/_project_buildtypes/should_return_nil_if_the_project_does_not_have_any_build_build_types.yml +44 -0
  65. data/spec/cassettes/Projects/GET/_project_parameters/should_fetch_all_the_paramters_for_a_given_project.yml +44 -0
  66. data/spec/cassettes/Projects/GET/_project_parameters/should_return_nil_if_there_are_no_parameters_defined_for_a_project.yml +44 -0
  67. data/spec/cassettes/Projects/GET/_projects/should_fetch_projects.yml +46 -0
  68. data/spec/cassettes/Projects/GET/_projects/should_return_nil_if_there_are_no_projects.yml +44 -0
  69. data/spec/faraday/null_response_body_spec.rb +18 -0
  70. data/spec/spec_helper.rb +13 -0
  71. data/spec/support/vcr_setup.rb +9 -0
  72. data/spec/teamcity/api_spec.rb +63 -0
  73. data/spec/teamcity/client/builds_spec.rb +62 -0
  74. data/spec/teamcity/client/buildtypes_spec.rb +106 -0
  75. data/spec/teamcity/client/projects_spec.rb +82 -0
  76. data/spec/teamcity/client_spec.rb +10 -0
  77. data/spec/teamcity/version_spec.rb +7 -0
  78. data/spec/teamcity_spec.rb +90 -0
  79. data/teamcity-ruby-client.gemspec +32 -0
  80. metadata +334 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NGU0NzgwMGI5OGY5MmE3OWI3MWJhMDA0ODhlNDY3NjYzOGE2Yzk5ZA==
5
+ data.tar.gz: !binary |-
6
+ YTc5ZDA0NDdjZmRjZDlkNTVmZmYyNWNiMGFiNTczNTQzZmFmZmZmMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ N2UzYjg1MGE5YTA1NmU1YjQ5NjkxMmJmNzY2YjE4YmUwZGVkOTRmNjNlOWU2
10
+ YzQ5YmViNzQ1MWEyNWIxYmQyNjZiYzVlMDRlOTVjMTE5MjdkYmI2NWZjYzhi
11
+ NjcwNzEwYmE5YWQ4NzAxYWY5ZjNmNjUxNjZmYTlhOTY1NTY3ZGI=
12
+ data.tar.gz: !binary |-
13
+ ZjdlM2M3ZDI2ZDM3ZmU3OTgyZmI3NzM0ODAwNjExNDU4MTk5OGI1ZTliZDg3
14
+ NTU1NTk4Y2EyYzk0ZGJmN2NjODEyYzdlZDYyZDhjY2UxYzI4YzYwYjE0ZjFk
15
+ YzI3ZGEzYTc2ZGY1ZWQ1MDBkMjJiYmFlNDM4OWZhMDNiZDJiNDA=
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p362@teamcity-ruby-client"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.14.2 (latest)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
35
+
36
+ # If you use bundler, this might be useful to you:
37
+ # if [[ -s Gemfile ]] && {
38
+ # ! builtin command -v bundle >/dev/null ||
39
+ # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
40
+ # }
41
+ # then
42
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
43
+ # gem install bundler
44
+ # fi
45
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
46
+ # then
47
+ # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
48
+ # fi
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## 0.1.0 (April 28, 2012)
2
+
3
+ Features:
4
+
5
+ - added GET support for projects
6
+ - added GET support for build types (build configurations)
7
+ - added GET support for builds
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teamcity-ruby-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jason Perry
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,153 @@
1
+ # The TeamCity Ruby Gem [![Build Status](https://secure.travis-ci.org/jperry/teamcity-ruby-client.png?branch=master)](http://travis-ci.org/jperry/teamcity-ruby-client) [![Code Climate](https://codeclimate.com/github/jperry/teamcity-ruby-client.png)](https://codeclimate.com/github/jperry/teamcity-ruby-client) [![Dependency Status](https://gemnasium.com/jperry/teamcity-ruby-client.png)](https://gemnasium.com/jperry/teamcity-ruby-client)
2
+
3
+ Ruby wrapper for the TeamCity Rest API
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'teamcity-ruby-client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install teamcity-ruby-client
18
+
19
+ ## API Usage Examples
20
+
21
+ * Tested on TeamCity 7.0 and higher
22
+ * Most of the api calls return either an array of Hashie::Mash objects or a single Hashie::Mash object which allows you to send messages to retreive an attribute easily.
23
+ * See the spec tests for more examples
24
+
25
+ ### Configuration
26
+
27
+ * See [configuration](lib/teamcity/configuration.rb) source or api doc for more configuration options
28
+
29
+ ```ruby
30
+ require 'teamcity'
31
+
32
+ # Currently only guest authentication is supported, next version will
33
+ # support authentication which will allow write api calls. This only needs
34
+ # to be set once per Ruby execution.
35
+ TeamCity.configure do |config|
36
+ config.endpoint = 'http://my-teamcity-server:8111/guestAuth/app/rest'
37
+ end
38
+ ```
39
+
40
+ ### Projects
41
+
42
+ ```ruby
43
+ # Get a list of projects
44
+ puts TeamCity.projects
45
+
46
+ # Get a project by id
47
+ puts TeamCity.project(id: 'project1')
48
+
49
+ # Get a list of buildtypes for a project
50
+ puts TeamCity.project_buildtypes(id: 'project1')
51
+
52
+ # Each item returned is a Hashie::Mash object which allows you to send messages
53
+ # to retreive an attribute easily. For example, get the name of
54
+ # the first buildtype in a project
55
+ puts TeamCity.project_buildtypes(id: 'project1').first.name
56
+ ```
57
+
58
+ ### Build Types (Build Configurations)
59
+
60
+ ```ruby
61
+ # Get a list of buildtypes (build configurations)
62
+ puts TeamCity.buildtypes
63
+
64
+ # Get buildtype details (build configuration)
65
+ puts TeamCity.buildtype(id: 'bt1')
66
+
67
+ # Get buildtype steps
68
+ puts TeamCity.buildtype_steps(id: 'bt1')
69
+
70
+ # See the api docs for more api calls
71
+ ```
72
+
73
+ ### Builds ###
74
+
75
+ ```ruby
76
+ # Get build details
77
+ puts TeamCity.build(id: 1)
78
+
79
+ # Get build tags
80
+ puts TeamCity.build_tags(id: 1)
81
+
82
+ # Fetch all the builds (defaults to the last 100 builds, use the 'count' build locator to return more)
83
+ puts TeamCity.builds
84
+
85
+ # Filter builds by multiple criteria's using the build locator
86
+ puts TeamCity.builds(count: 1, status: 'SUCCESS') # This will return the most recent build that passed
87
+
88
+ puts TeamCity.builds(count: 1).first.name
89
+
90
+ puts TeamCity.builds(buildType: 'bt3') # Fetch all builds where buildType=bt4
91
+
92
+ puts TeamCity.builds(status: 'FAILURE') # Fetch all builds that failed
93
+
94
+ # Passing the output to another to fetch additional information
95
+ puts TeamCity.build(id: TeamCity.builds(count: 1).first.id).buildType.name # Fetch the name of the last build to run
96
+
97
+ ```
98
+
99
+ ## Documentation
100
+
101
+ ### Generating API Docs
102
+
103
+ 1. Pull the source down
104
+ 2. ```bundle install```
105
+ 3. ```rake yard```
106
+ 4. open doc/index.html
107
+
108
+ ### TeamCity Rest API Plugin
109
+
110
+ [Link](http://confluence.jetbrains.com/display/TW/REST+API+Plugin)
111
+
112
+ ## Contributing
113
+
114
+ Ways to contribute:
115
+
116
+ * report a bug
117
+ * fix an issue that is logged
118
+ * suggest enhancements
119
+ * suggest a new feature
120
+ * cleaning up code
121
+ * refactoring code
122
+ * fix documentation errors
123
+ * test on a new versions of teamcity
124
+ * Use the gem :)
125
+
126
+ ## Submitting an issue
127
+
128
+ I use issue tracker to track bugs, features, enhancements, etc. Please check the list of issues to confirm
129
+ it hasn't already been reported. Please tag the the issue with an appropriate tag. If submitting a bug please
130
+ include any output that will help me in diagnosing the issue, link to a gist if you have multiple outputs
131
+ (client output, teamcity server output). Please include the version of teamcity you are using
132
+ the client against as well as the gem and ruby versions.
133
+
134
+ ## Submitting a Pull Request
135
+
136
+ 1. Fork the project.
137
+ 2. Create a topic branch.
138
+ 3. Implement your feature or bug fix.
139
+ 4. Add documentation for your feature or bug fix.
140
+ 5. Run ```rake doc:yard```. If your changes are not 100% documented, go back to step 4.
141
+ 6. Add specs for your feature or bug fix.
142
+ 7. If the rspec test is making a request use VCR to record the response, see the other examples.
143
+ 7. Run ```rake spec```. If your changes are not 100% covered, go back to step 6.
144
+ 8. Commit and push your changes.
145
+ 9. Submit a pull request.
146
+
147
+ ## Debugging Tips
148
+
149
+ * Enable debug-rest in TeamCity to see all the rest api requests come through in the `teamcity-rest.log`, you can find this on the Diagnostics page under Server Administration
150
+
151
+ ## Questions/Comments
152
+
153
+ Feel free to contact me directly through github. Enjoy!
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
+ require 'yard/rake/yardoc_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+
10
+ YARD::Rake::YardocTask.new do |yardoc|
11
+ yardoc.name = 'yard'
12
+ yardoc.options = ['--verbose']
13
+ yardoc.files = [
14
+ 'lib/**/*.rb'
15
+ ]
16
+ end
@@ -0,0 +1,17 @@
1
+ module FaradayMiddleware
2
+ # This middleware handles any responses where the body
3
+ # is 'null' which is the case when asking teamcity for
4
+ # an empty collection. When this is encountered we
5
+ # set the response to an empty json object
6
+ class NullResponseBody < Faraday::Middleware
7
+ # Faraday Middleware
8
+ # @note - should only be called by Faraday
9
+ def call(env)
10
+ @app.call(env).on_complete do |response|
11
+ if response[:body] == "null"
12
+ response[:body] = {}
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'connection'
2
+ require_relative 'request'
3
+
4
+ module TeamCity
5
+ class API
6
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
7
+
8
+ # Creates a new API
9
+ def initialize(options={})
10
+ options = TeamCity.options.merge(options)
11
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
12
+ send("#{key}=", options[key])
13
+ end
14
+ end
15
+
16
+ include Connection
17
+ include Request
18
+ end
19
+ end
@@ -0,0 +1,93 @@
1
+ require 'linguistics'
2
+
3
+ module TeamCity
4
+ class Client
5
+ # Defines methods related to build types (or build configurations)
6
+ module BuildTypes
7
+
8
+ Linguistics.use :en
9
+
10
+ # HTTP GET
11
+
12
+ # List of build types
13
+ #
14
+ # @return [Array<Hashie::Mash>, nil] of buildtypes or nil if no buildtypes exist
15
+ def buildtypes
16
+ response = get('buildTypes')
17
+ response['buildType']
18
+ end
19
+
20
+ # Get build configuration details
21
+ #
22
+ # @param options [Hash] option keys, :id => buildtype_id
23
+ # @return [Hashie::Mash] of build configuration details
24
+ def buildtype(options={})
25
+ assert_options(options)
26
+ get("buildTypes/#{locator(options)}")
27
+ end
28
+
29
+ # TODO: File jetbrains ticket, this call doesn't work
30
+ #def buildtype_state(options={})
31
+ # assert_options(options)
32
+ # get("buildTypes/#{locator(options)}/paused")
33
+ #end
34
+
35
+ # Get build configuration settings
36
+ #
37
+ # @param (see #buildtype)
38
+ # @return [Array<Hashie::Mash>] of build configuration settings
39
+ def buildtype_settings(options={})
40
+ assert_options(options)
41
+ response = get("buildTypes/#{locator(options)}/settings")
42
+ response['property']
43
+ end
44
+
45
+ # Get build configuration parameters
46
+ #
47
+ # @param (see #buildtype)
48
+ # @return [Array<Hashie::Mash>] of build configuration parameters
49
+ def buildtype_parameters(options={})
50
+ assert_options(options)
51
+ response = get("buildTypes/#{locator(options)}/parameters")
52
+ response['property']
53
+ end
54
+
55
+ # Get template associated with build configuration
56
+ #
57
+ # @param (see #buildtype)
58
+ # @return [Hashie::Mash, nil] of build configuration parameters or nil if
59
+ def buildtype_template(options={})
60
+ assert_options(options)
61
+ begin
62
+ get("buildTypes/#{locator(options)}/template")
63
+ rescue StandardError => e
64
+ /No template associated/.match(e.to_s) ? nil : raise
65
+ end
66
+ end
67
+
68
+ # @macro [attach] build configuration settings
69
+ # @method buildtype_$1(options = {})
70
+ # Get build configuration $1
71
+ # @param options [Hash] option keys, :id => buildtype_id
72
+ # @return [Array<Hashie::Mash>] of build configuration $1
73
+ def self.make_method(name)
74
+ define_method("buildtype_#{name}".to_sym) do |options|
75
+ name_has_dashes = name.to_s.gsub('_', '-')
76
+ assert_options(options)
77
+ response = get("buildTypes/#{locator(options)}/#{name_has_dashes}")
78
+ response[name_has_dashes.en.plural]
79
+ end
80
+ end
81
+ private_class_method :make_method
82
+
83
+ make_method :features
84
+ make_method :triggers
85
+ make_method :steps
86
+ make_method :agent_requirements
87
+ make_method :artifact_dependencies
88
+ make_method :snapshot_dependencies
89
+ make_method :vcs_root_entries
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,36 @@
1
+ module TeamCity
2
+ class Client
3
+ # Defines methods related to builds
4
+ module Builds
5
+
6
+ # HTTP GET
7
+
8
+ # List of builds
9
+ #
10
+ # @param options [Hash] list of build locators to filter build results on
11
+ # @return [Array<Hashie::Mash>, nil] of builds or nil if no builds exist
12
+ def builds(options={})
13
+ url_params = options.empty? ? '' : "?locator=#{locator(options)}"
14
+ response = get("builds#{url_params}")
15
+ response['build']
16
+ end
17
+
18
+ # Get build details
19
+ #
20
+ # @param options [Hash] option keys, :id => build_id
21
+ # @return [Hashie::Mash] of build details
22
+ def build(options={})
23
+ assert_options(options)
24
+ get("builds/#{locator(options)}")
25
+ end
26
+
27
+ def build_tags(options={})
28
+ assert_options(options)
29
+ response = get("builds/#{locator(options)}/tags")
30
+ response['tag']
31
+ end
32
+
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,24 @@
1
+ module TeamCity
2
+ class Client
3
+ # Defines some common methods shared across the other
4
+ # teamcity api modules
5
+ module Common
6
+
7
+ private
8
+
9
+ def assert_options(options)
10
+ !options[:id] and raise ArgumentError, "Must provide an id", caller
11
+ end
12
+
13
+ # Take a list of locators to search on multiple criterias
14
+ #
15
+ def locator(options={})
16
+ test = options.inject([]) do |locators, locator|
17
+ key, value = locator
18
+ locators << "#{key}:#{value}"
19
+ end.join(',')
20
+ test
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ module TeamCity
2
+ class Client
3
+ # Defines methods related to projects
4
+ module Projects
5
+
6
+ # HTTP GET
7
+
8
+ # List of projects
9
+ #
10
+ # @return [Array<Hashie::Mash>, nil] of projects or nil if no projects exist
11
+ def projects
12
+ response = get('projects')
13
+ response['project']
14
+ end
15
+
16
+ # Get project details
17
+ #
18
+ # @param options [Hash] option keys, :id => project_id
19
+ # @return [Hashie::Mash] of project details
20
+ def project(options={})
21
+ assert_options(options)
22
+ get("projects/#{locator(options)}")
23
+ end
24
+
25
+ # List of Build Configurations of a project
26
+ #
27
+ # @param (see #project)
28
+ # @return [Array<Hashie::Mash>, nil] of build types or nil if no build types exist
29
+ def project_buildtypes(options={})
30
+ assert_options(options)
31
+ response = get("projects/#{locator(options)}/buildTypes")
32
+ response['buildType']
33
+ end
34
+
35
+ # List of parameters defined on a project
36
+ #
37
+ # @param (see #project)
38
+ # @return [Array<Hashie::Mash>, nil] of parameters or nil if no parameters are defined
39
+ def project_parameters(options={})
40
+ assert_options(options)
41
+ response = get("projects/#{locator(options)}/parameters")
42
+ response['property']
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'api'
2
+
3
+ module TeamCity
4
+ # Wrapper for the TeamCity REST API
5
+ #
6
+ class Client < API
7
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f}
8
+
9
+ include TeamCity::Client::Projects
10
+ include TeamCity::Client::BuildTypes
11
+ include TeamCity::Client::Builds
12
+ include TeamCity::Client::Common
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ require 'faraday'
2
+ require_relative 'version'
3
+
4
+ module TeamCity
5
+ module Configuration
6
+ VALID_OPTIONS_KEYS = [
7
+ :adapter,
8
+ :endpoint,
9
+ :user_agent,
10
+ :format
11
+ ].freeze
12
+
13
+ VALID_FORMATS = [:json].freeze
14
+
15
+ DEFAULT_ADAPTER = Faraday.default_adapter
16
+
17
+ DEFAULT_ENDPOINT = 'http://teamcity:8111/guestAuth/app/rest/7.0/'.freeze
18
+
19
+ DEFAULT_USER_AGENT = "TeamCity Ruby Client #{TeamCity::VERSION}".freeze
20
+
21
+ DEFAULT_FORMAT = :json
22
+
23
+ attr_accessor *VALID_OPTIONS_KEYS
24
+
25
+ def self.extended(base)
26
+ base.reset
27
+ end
28
+
29
+ def configure
30
+ yield self
31
+ end
32
+
33
+ def options
34
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
35
+ option.merge!(key => send(key))
36
+ end
37
+ end
38
+
39
+ # Reset all configuration options to defaults
40
+ def reset
41
+ self.adapter = DEFAULT_ADAPTER
42
+ self.endpoint = DEFAULT_ENDPOINT
43
+ self.user_agent = DEFAULT_USER_AGENT
44
+ self.format = DEFAULT_FORMAT
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ require 'faraday_middleware'
2
+ Dir[File.expand_path('../../faraday/*.rb', __FILE__)].each{|f| require f}
3
+
4
+ module TeamCity
5
+ # @private
6
+ module Connection
7
+ private
8
+
9
+ def connection
10
+ options = {
11
+ :headers => {'Accept' => "application/#{format}; charset=utf-8", 'User-Agent' => user_agent},
12
+ :ssl => {:verify => false},
13
+ :url => endpoint
14
+ }
15
+
16
+ Faraday::Connection.new(options) do |connection|
17
+ connection.use Faraday::Request::UrlEncoded
18
+ connection.use FaradayMiddleware::Mashify
19
+ case format.to_s.downcase
20
+ when 'json' then connection.use FaradayMiddleware::ParseJson
21
+ end
22
+ connection.use FaradayMiddleware::NullResponseBody
23
+ connection.adapter(adapter)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ module TeamCity
2
+ # Defines HTTP request methods
3
+ module Request
4
+ # Perform an HTTP GET request
5
+ def get(path, options={})
6
+ request(:get, path, options)
7
+ end
8
+
9
+ # Perform an HTTP POST request
10
+ def post(path, options={})
11
+ request(:post, path, options)
12
+ end
13
+
14
+ # Perform an HTTP PUT request
15
+ def put(path, options={})
16
+ request(:put, path, options)
17
+ end
18
+
19
+ # Perform an HTTP DELETE request
20
+ def delete(path, options={})
21
+ request(:delete, path, options)
22
+ end
23
+
24
+ private
25
+
26
+ # Perform an HTTP request
27
+ def request(method, path, options)
28
+ response = connection.send(method) do |request|
29
+ case method
30
+ when :get, :delete
31
+ request.url(path, options)
32
+ when :post, :put
33
+ request.path = path
34
+ request.body = options unless options.empty?
35
+ end
36
+ end
37
+ response.body
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module TeamCity
2
+ VERSION = '0.1.0'
3
+ end