teamcity-ruby-client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/.rvmrc +48 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +153 -0
- data/Rakefile +16 -0
- data/lib/faraday/null_response_body.rb +17 -0
- data/lib/teamcity/api.rb +19 -0
- data/lib/teamcity/client/build_types.rb +93 -0
- data/lib/teamcity/client/builds.rb +36 -0
- data/lib/teamcity/client/common.rb +24 -0
- data/lib/teamcity/client/projects.rb +46 -0
- data/lib/teamcity/client.rb +14 -0
- data/lib/teamcity/configuration.rb +47 -0
- data/lib/teamcity/connection.rb +27 -0
- data/lib/teamcity/request.rb +40 -0
- data/lib/teamcity/version.rb +3 -0
- data/lib/teamcity.rb +24 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype/should_fetch_the_details_of_a_buildtype_by_id.yml +49 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype/should_raise_an_error_if_the_buildtype_does_not_exist.yml +50 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_fetch_the_build_configuration_agent_requirements_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_agent_requirements/should_return_nil_if_there_are_no_agent_requirements_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_fetch_the_build_configuration_artifact_dependencies_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_artifact_dependencies/should_return_nil_if_there_are_no_artifact_dependencies_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_fetch_the_build_configuration_features_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_features/should_return_nil_if_there_are_no_features_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_fetch_the_build_configuration_parameters_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_parameters/should_return_nil_if_there_are_no_parameters_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_settings/should_fetch_the_settings_for_a_given_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_settings/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_fetch_the_build_configuration_snapshot_dependencies_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_snapshot_dependencies/should_return_nil_if_there_are_no_snapshot_dependencies_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_fetch_the_build_configuration_steps_for_a_buildtype.yml +46 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_return_an_array.yml +46 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_steps/should_return_nil_if_there_are_no_steps_defined.yml +44 -0
- 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
- data/spec/cassettes/BuildTypes/GET/_buildtype_template/should_return_nil_if_the_buildtype_is_not_associated_with_a_template.yml +50 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_template/should_return_the_attributes_of_the_associated_template.yml +45 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_fetch_the_build_configuration_triggers_for_a_buildtype.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_return_an_array.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_triggers/should_return_nil_if_there_are_no_triggers_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_fetch_the_build_configuration_vcs_root_entries_for_a_buildtype.yml +45 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_return_an_array.yml +45 -0
- data/spec/cassettes/BuildTypes/GET/_buildtype_vcs_root_entries/should_return_nil_if_there_are_no_vcs_root_entries_defined.yml +44 -0
- data/spec/cassettes/BuildTypes/GET/_buildtypes/should_fetch_all_the_buildtypes.yml +49 -0
- data/spec/cassettes/Builds/GET/_build/should_fetch_the_build_details.yml +49 -0
- data/spec/cassettes/Builds/GET/_build/should_raise_an_error_if_the_build_does_not_exist.yml +50 -0
- data/spec/cassettes/Builds/GET/_build_tags/should_fetch_the_build_tags.yml +44 -0
- data/spec/cassettes/Builds/GET/_build_tags/should_return_nil_if_there_are_no_build_tags_defined_for_a_build.yml +44 -0
- data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_filter_by_multiple_build_locators.yml +44 -0
- data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_filter_results_by_build_locators.yml +44 -0
- data/spec/cassettes/Builds/GET/_builds/should_allow_you_to_search_by_locator.yml +44 -0
- data/spec/cassettes/Builds/GET/_builds/should_fetch_all_the_builds.yml +44 -0
- data/spec/cassettes/Projects/GET/_project/should_fetch_a_single_project_by_id.yml +47 -0
- data/spec/cassettes/Projects/GET/_project/should_raise_an_error_if_the_project_does_not_exist.yml +50 -0
- data/spec/cassettes/Projects/GET/_project_buildtypes/should_fetch_all_the_buildTypes_for_a_project.yml +45 -0
- data/spec/cassettes/Projects/GET/_project_buildtypes/should_return_nil_if_the_project_does_not_have_any_build_build_types.yml +44 -0
- data/spec/cassettes/Projects/GET/_project_parameters/should_fetch_all_the_paramters_for_a_given_project.yml +44 -0
- data/spec/cassettes/Projects/GET/_project_parameters/should_return_nil_if_there_are_no_parameters_defined_for_a_project.yml +44 -0
- data/spec/cassettes/Projects/GET/_projects/should_fetch_projects.yml +46 -0
- data/spec/cassettes/Projects/GET/_projects/should_return_nil_if_there_are_no_projects.yml +44 -0
- data/spec/faraday/null_response_body_spec.rb +18 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/vcr_setup.rb +9 -0
- data/spec/teamcity/api_spec.rb +63 -0
- data/spec/teamcity/client/builds_spec.rb +62 -0
- data/spec/teamcity/client/buildtypes_spec.rb +106 -0
- data/spec/teamcity/client/projects_spec.rb +82 -0
- data/spec/teamcity/client_spec.rb +10 -0
- data/spec/teamcity/version_spec.rb +7 -0
- data/spec/teamcity_spec.rb +90 -0
- data/teamcity-ruby-client.gemspec +32 -0
- 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
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
data/Gemfile
ADDED
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
|
data/lib/teamcity/api.rb
ADDED
@@ -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
|