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.
- 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 [](http://travis-ci.org/jperry/teamcity-ruby-client) [](https://codeclimate.com/github/jperry/teamcity-ruby-client) [](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
|