teamcity-ruby-client 0.1.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 (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