ruby_vsts 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f231587e2fb121259d565337ac2563a0d903b383
4
+ data.tar.gz: 6767463306762c36b6989d39a6edc20e84d3db88
5
+ SHA512:
6
+ metadata.gz: 1b5e22b6d5a3aa91e66fb8f752fc07beefa5dcc05653999586a9b878fbe79f1d0e16b8f9edbe2aacf76132ef52acbd759bc4efa6378c3076f7ed7aa5383817cb
7
+ data.tar.gz: f309cb3aa500a76dd3e16820a35cf5ef11d4cbd7ba83a73b59db3241a52d7d187461023722d86bde807671127b50e5969859798d66579e537c8d70f481e1567d
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ 3��Y���J��\�q'�HnB"0)�� yU.��8 j�%�KX{�w7��_�ыa��0&ޏoV�-Џp���e6PC�p�!Z��P9��P�O�d���"M�R좕�ov��V�cz�ř�.��ag�y�<� ���}n���)�Gmg�z��n�.�)x��ZC�I1��
2
+ h+cX}��\��}�
3
+ ?@�����N�"<ǭ�brԔo�Q���V9�r��,%�Xv �&�u����ܟ>_S��1E���H�g�l"˕b_'-
data.tar.gz.sig ADDED
Binary file
data/.codeclimate.yml ADDED
@@ -0,0 +1,18 @@
1
+ engines:
2
+ duplication:
3
+ enabled: true
4
+ config:
5
+ languages:
6
+ - ruby
7
+ fixme:
8
+ enabled: true
9
+ rubocop:
10
+ enabled: true
11
+ ratings:
12
+ paths:
13
+ - lib/**
14
+ - "**.rb"
15
+
16
+ exclude_paths:
17
+ - spec/**/*
18
+ - vendor/**/*
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ # Gem builds
2
+ pkg/
3
+ *.gem
4
+
5
+ # Bundler files
6
+ .bundle
7
+ Gemfile.lock
8
+
9
+ # Ignore Byebug command history file.
10
+ .byebug_history
11
+
12
+ # SimpleCov code coverage reports
13
+ /coverage
14
+
15
+ # CodeClimate repo token to report code coverage
16
+ # See https://codeclimate.com/repos/58ea190f4e4fc9029400296b/coverage_setup
17
+ .codeclimate_repo_token
18
+
19
+ # Yard documentation files
20
+ .yardoc/
21
+ doc/
22
+
23
+ # Temporary backups, unneeded files
24
+ *.old
25
+ *.orig
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,44 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+
4
+ Rails:
5
+ Enabled: false
6
+
7
+ Style/StringLiterals:
8
+ Enabled: false
9
+ # EnforcedStyle: double_quotes # if enabled, this can be single_quotes or double_quotes
10
+
11
+ Style/SymbolArray:
12
+ Enabled: false
13
+
14
+ Style/WordArray:
15
+ Enabled: false
16
+
17
+ Style/RegexpLiteral:
18
+ Enabled: false
19
+
20
+ Metrics/LineLength:
21
+ Max: 135
22
+ # To make it possible to copy or click on URIs in the code, we allow lines
23
+ # containing a URI to be longer than Max.
24
+ AllowHeredoc: true
25
+ AllowURI: true
26
+ URISchemes:
27
+ - http
28
+ - https
29
+
30
+ Metrics/MethodLength:
31
+ CountComments: false # count full line comments?
32
+ Max: 25
33
+
34
+ Metrics/AbcSize:
35
+ # The ABC size is a calculated magnitude, so this number can be a Fixnum or
36
+ # a Float.
37
+ Max: 40
38
+
39
+ Metrics/CyclomaticComplexity:
40
+ # even 15 may still be acceptable
41
+ Max: 10
42
+
43
+ Metrics/PerceivedComplexity:
44
+ Max: 10
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --charset UTF-8
2
+ --main README.md
3
+ --title 'Ruby VSTS Documentation'
4
+ --no-private
5
+ --markup=markdown
6
+ -
7
+ LICENSE.txt
8
+ README.md
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2017 Gabor Lengyel and Prodexity Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # ruby_vsts
2
+ An unofficial Microsoft Visual Studio Team Services (VSTS) API client in Ruby
3
+
4
+ [![Code Climate](https://codeclimate.com/github/prodexity/ruby_vsts.png)](https://codeclimate.com/github/prodexity/ruby_vsts)
5
+ [![Issue Count](https://codeclimate.com/github/prodexity/ruby_vsts/badges/issue_count.svg)](https://codeclimate.com/github/prodexity/ruby_vsts)
6
+ [![Test Coverage](https://codeclimate.com/github/prodexity/ruby_vsts/badges/coverage.svg)](https://codeclimate.com/github/prodexity/ruby_vsts/coverage)
7
+
8
+ ## About
9
+ This will be a Ruby gem to connect to the Microsoft Visual Studio online (VSTS) Rest API.
10
+ It may also work with recent versions of TFS too. *Work is heavily in progress!*
11
+
12
+ ## Usage
13
+
14
+ ### Setup
15
+ ```ruby
16
+ require 'ruby_vsts'
17
+
18
+ VSTS.configure do |config|
19
+ config.personal_access_token = "YOUR_PERSONAL_ACCESS_TOKEN"
20
+ config.base_url = "https://YOUR_INSTANCE.visualstudio.com/"
21
+ end
22
+ ```
23
+
24
+ ### Finding changesets
25
+ ```ruby
26
+ VSTS::Changeset.find(72300) # find changeset by id
27
+ VSTS::Changeset.find_all(author: "fabrikam13@hotmail.com") # find by author
28
+ VSTS::Changeset.find_all(fromId: 1000, toId: 1200) # find by id range
29
+ VSTS::Changeset.find_all(fromDate: "03-01-2017", toDate: "03-18-2017-2:00PM") # find by date range
30
+ VSTS::Changeset.find_all(itemPath: "$/Fabrikam-Fiber-TFVC/Program.cs") # find by item path
31
+ VSTS::Changeset.find_all(top: 20, skip: 100) # paging
32
+ # ...
33
+ ```
34
+
35
+ ### Getting changes in a changeset
36
+ ```ruby
37
+ changeset = VSTS::Changeset.find(72300)
38
+ changes = changeset.changes
39
+ ```
40
+
41
+ ### Getting change items
42
+ ```ruby
43
+ item = changes[0]
44
+ file_contents = item.get # current version
45
+ ```
46
+
47
+ Please see specs and the source code for further examples.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:test)
5
+
6
+ task test_and_report: [:test, :report_coverage]
7
+
8
+ task :report_coverage do
9
+ ENV["CODECLIMATE_REPO_TOKEN"] = File.read(".codeclimate_repo_token") if File.exist?(".codeclimate_repo_token")
10
+ `codeclimate-test-reporter`
11
+ end
12
+
13
+ desc "Run tests and report coverage to CodeClimate"
14
+ task default: :test_and_report
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDhTCCAm2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMRIwEAYDVQQDDAlydWJ5
3
+ X3ZzdHMxGTAXBgoJkiaJk/IsZAEZFglwcm9kZXhpdHkxEzARBgoJkiaJk/IsZAEZ
4
+ FgNjb20wHhcNMTcwNDEyMDk1MzE1WhcNMTgwNDEyMDk1MzE1WjBEMRIwEAYDVQQD
5
+ DAlydWJ5X3ZzdHMxGTAXBgoJkiaJk/IsZAEZFglwcm9kZXhpdHkxEzARBgoJkiaJ
6
+ k/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnth7a
7
+ Innh/5+zT5rdwHMySmQG2qyuNh5ammn4ZleFvkZxDPpFb5Kn+BeoR8O3OWEe5WEs
8
+ 4FUR/43Ow1HzYMIJIIb6MxNZyZQj6Bm+cKZPctL/h0KjC7kG+2aRdUCsfFKoZvMZ
9
+ 69yHxtArNtbt6dIRsic8CHioQe0i6/7BVD/1OKKt600dt1K1zf7j7T8xWIdCwbO8
10
+ zWE4GpEBnEA4mBPMKqAZmd+DsqrbCWPie8TdfGeWo71/7rUuCbAUpMq4Rh3SpmfV
11
+ t0OQMShhuAaLoRLuIZ48hiC3ELAr9ZCK8rn5Ci2trLEVjyOvbq/QnwnGspydlyaN
12
+ xzGpH5p82DwcUP5TAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAd
13
+ BgNVHQ4EFgQUYZTJdcOOpive/ZTgo5EYhS98qUUwIgYDVR0RBBswGYEXcnVieV92
14
+ c3RzQHByb2RleGl0eS5jb20wIgYDVR0SBBswGYEXcnVieV92c3RzQHByb2RleGl0
15
+ eS5jb20wDQYJKoZIhvcNAQEFBQADggEBAFiM7TEAsjlwjCyCMlzw0Yq/igWgaaFP
16
+ of+iPXZUC49YMTpXnQjNl9sE+cxHzkJzyM00YdeJ18DDtquIZ44Hdd30J9oleJ5g
17
+ DgGCX4bCKg5WTBwqvd0ivATn9uxDxLF1VP/cl1MJPXhW8+Bhq2FzbyWvQuxHeFsI
18
+ jJNJdpaL4UgxvhYECxAd1gzvIpRFbSqJJZVr8T4tYjfxyaGJxf9T5GbtYazYcRmP
19
+ Pfk9fa2jjnmyUPewuJZHmwArB9oRryAdwWtOsvVZHZ1ulcmW+Pbo2IiYQHvl1zQH
20
+ Z5Mw91gFnDov+9F9be4W5sZmbj640vetlJGLdMFheEZ2HSX+4fEZu1k=
21
+ -----END CERTIFICATE-----
data/lib/ruby_vsts.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'vsts/version'
2
+ require 'vsts/configuration'
3
+ require 'vsts/api_client'
4
+ require 'vsts/api_response'
5
+ require 'vsts/base_model'
6
+ require 'vsts/identity'
7
+ require 'vsts/item'
8
+ require 'vsts/change'
9
+ require 'vsts/changeset'
10
+
11
+ # Base namespace for ruby_vsts
12
+ module VSTS
13
+ class << self
14
+ attr_accessor :configuration
15
+ attr_accessor :logger
16
+ end
17
+
18
+ def self.configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+
22
+ def self.reset
23
+ @configuration = Configuration.new
24
+ end
25
+
26
+ def self.configure
27
+ yield(configuration)
28
+ end
29
+
30
+ def self.logger
31
+ @logger ||= Logger.new(STDOUT)
32
+ end
33
+ end
@@ -0,0 +1,150 @@
1
+ require 'rest-client'
2
+ require 'base64'
3
+
4
+ # VSTS namespace
5
+ module VSTS
6
+ # API client for Visual Studio Team Services (VSTS)
7
+ # Manages access tokens and API versions, builds proper requests as expected by the VSTS API
8
+ class APIClient
9
+ # Make an API request
10
+ #
11
+ # @param method [Symbol] the method to be used, can be :get, :put, :post, :delete or :head (will be passed to RestClient)
12
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
13
+ # @param opts [Hash] options for the request
14
+ # @option opts [Hash] :payload payload for the request (if any)
15
+ # @option opts [String] :api_version
16
+ # @option opts [String] :collection
17
+ # @option opts [String] :team_project
18
+ # @option opts [String] :area
19
+ # @option opts [Hash] :urlparams
20
+ # @return [Hash] request results as parsed from json
21
+ def self.request(method, resource, opts = {})
22
+ url = build_url(resource, opts)
23
+ VSTS.logger.debug("VSTS request: #{method} #{url}") if VSTS.configuration.debug
24
+ req = {
25
+ method: method,
26
+ url: url,
27
+ payload: opts[:payload],
28
+ headers: {
29
+ Authorization: authz_header_value,
30
+ Accept: "application/json",
31
+ "Content-Type" => "application/json"
32
+ }
33
+ }
34
+ resp = RestClient::Request.execute(req)
35
+ APIResponse.new(req, resp)
36
+ end
37
+
38
+ # Helper method for GET requests, calls #request
39
+ #
40
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
41
+ # @param opts [Hash] query options, see #request
42
+ # @return [Hash] request results as parsed from json
43
+ def self.get(resource, opts = {})
44
+ request(:get, resource, opts)
45
+ end
46
+
47
+ # Helper method for POST requests, calls #request
48
+ #
49
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
50
+ # @param payload [Hash] payload to be sent with the request, takes precedence over opts[:payload]
51
+ # @param opts [Hash] query options, see #request
52
+ # @return [Hash] request results as parsed from json
53
+ def self.post(resource, payload, opts = {})
54
+ opts[:payload] = payload
55
+ request(:post, resource, opts)
56
+ end
57
+
58
+ # Helper method for PUT requests, calls #request
59
+ #
60
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
61
+ # @param payload [Hash] payload to be sent with the request, takes precedence over opts[:payload]
62
+ # @param opts [Hash] query options, see #request
63
+ # @return [Hash] request results as parsed from json
64
+ def self.put(resource, payload, opts = {})
65
+ opts[:payload] = payload
66
+ request(:put, resource, opts)
67
+ end
68
+
69
+ # Helper method for PATCH requests, calls #request
70
+ #
71
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
72
+ # @param payload [Hash] payload to be sent with the request, takes precedence over opts[:payload]
73
+ # @param opts [Hash] query options, see #request
74
+ # @return [Hash] request results as parsed from json
75
+ def self.patch(resource, payload, opts = {})
76
+ opts[:payload] = payload
77
+ request(:patch, resource, opts)
78
+ end
79
+
80
+ # Helper method for DELETE requests, calls #request
81
+ #
82
+ # @param resource [String] the resource to request under the base_url (ie. "/changesets")
83
+ # @param opts [Hash] query options, see #request
84
+ # @return [Hash] request results as parsed from json
85
+ def self.delete(resource, opts = {})
86
+ request(:delete, resource, opts)
87
+ end
88
+
89
+ # Private class methods
90
+
91
+ # Builds VSTS url as described in https://www.visualstudio.com/en-us/docs/integrate/get-started/rest/basics
92
+ #
93
+ # @param resource [String] the VSTS resource
94
+ # @param opts [Hash] options hash, see #request
95
+ # @return [String] the request URL
96
+ # @private
97
+ def self.build_url(resource, opts = {})
98
+ base_url = VSTS.configuration.base_url.sub(%r{\/+$}, "")
99
+ api_version = opts[:api_version] || VSTS.configuration.api_version
100
+ collection = opts[:collection] || VSTS.configuration.collection
101
+ team_project = opts[:team_project] || VSTS.configuration.team_project
102
+ urlparams = opts[:urlparams] || {}
103
+ area = opts[:area] || VSTS.configuration.area
104
+ resource.sub!(%r{^\/+}, "")
105
+
106
+ base = [base_url, collection, team_project, "_apis", area, resource].compact.join("/")
107
+ urlparams["api-version"] ||= api_version
108
+ url_encoded_params = URI.encode_www_form(urlparams) # makes url params from Hash
109
+
110
+ base + "?" + url_encoded_params
111
+ end
112
+
113
+ # Calculate the Authorization header for the API based on the personal access token
114
+ #
115
+ # @return [String] the Authorization header value for Basic auth, ie. "Basic jrigf9404vvxsoi48t048fdj=="
116
+ # @private
117
+ def self.authz_header_value
118
+ "Basic " + Base64.strict_encode64(":" + VSTS.configuration.personal_access_token)
119
+ end
120
+
121
+ # Build URL parameters hash from options hash (used internally)
122
+ #
123
+ # @param opts [Hash] options hash with Symbol keys to build url parameters from
124
+ # @param paramnames [Array<String>, Array<Symbol>, Array<Array<String, String>>, Array<Hash>]
125
+ # list of VSTS URL parameter names and VSTS prefixes to filter from opts
126
+ # @return [Hash] url parameters hash
127
+ # @private
128
+ def self.build_params(opts, paramnames)
129
+ urlparams = {}
130
+ paramnames.each do |paramname_with_prefix|
131
+ case paramname_with_prefix
132
+ when String, Symbol
133
+ prefix = ""
134
+ paramname = paramname_with_prefix
135
+ when Array
136
+ prefix = paramname_with_prefix[0]
137
+ paramname = paramname_with_prefix[1]
138
+ when Hash
139
+ prefix = paramname_with_prefix.first[0]
140
+ paramname = paramname_with_prefix.first[1]
141
+ else
142
+ VSTS.logger.warn("Invalid type in paramlist in APIClient##build_params: #{paramname_with_prefix.class}")
143
+ next
144
+ end
145
+ urlparams["#{prefix}#{paramname}"] = opts[paramname] if opts[paramname]
146
+ end
147
+ urlparams
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,24 @@
1
+ require 'json'
2
+
3
+ # VSTS namespace
4
+ module VSTS
5
+ # VSTS API response
6
+ class APIResponse
7
+ attr_accessor :request, :code, :body, :parsed
8
+
9
+ # Constructor
10
+ #
11
+ # @param request [Hash] the hash that was passed to RestClient as the request descriptor
12
+ # @param response [RestClient::Response]
13
+ def initialize(request, response)
14
+ @request = request
15
+ @code = response.code
16
+ @body = response.body
17
+ begin
18
+ @parsed = JSON.parse(@body)
19
+ rescue JSON::ParserError
20
+ @parsed = nil
21
+ end
22
+ end
23
+ end
24
+ end