veyor 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.
@@ -0,0 +1,206 @@
1
+ require "veyor/version"
2
+ require "veyor/request"
3
+ require 'veyor/utils'
4
+ require 'rexml/document'
5
+ require 'rexml/xpath'
6
+
7
+ # @!macro veyor_params
8
+ # @param account [String] An Appveyor account name
9
+ # @param project [String] An Appveyor project name
10
+ # @param verbose [Boolean] Print request headers to stdout. Default: false
11
+
12
+ # @!macro history_params
13
+ # @param limit [Fixnum] Records per page
14
+ # @param start_build [String] Build version to start at
15
+ # @param branch [String] Branch name
16
+
17
+ # @!macro veyor_options
18
+ # @param options [Hash] Hash of options for configuring the request, passed on to Faraday.new
19
+ # - timeout [Fixnum] open/read timeout Integer in seconds
20
+ # - open_timeout [Fixnum] read timeout Integer in seconds
21
+ # - proxy [Hash] hash of proxy options
22
+ # - uri [String] Proxy Server URI
23
+ # - user [String] Proxy server username
24
+ # - password [String] Proxy server password
25
+ # - params_encoder [Hash] not sure what this is
26
+ # - bind [Hash] A hash with host and port values
27
+ # - boundary [String] of the boundary value
28
+ # - oauth [Hash] A hash with OAuth details
29
+
30
+ ##
31
+ # `Veyor` - The top level module for using methods
32
+ # to access veyor APIs
33
+ #
34
+ # The following methods are provided:
35
+ # * `Veyor.project` - get project by name, branch, or build version
36
+ # * `Veyor.projects` - get all projects
37
+ # * `Veyor.project_history` - get project history
38
+ # * `Veyor.project_deployments` - get project deployments
39
+ # * `Veyor.project_settings` - get project settings
40
+ # * `Veyor.build_start` - start a build
41
+ # * `Veyor.build_cancel` - cancel a build
42
+ #
43
+ # More will be added in future `veyor` versions
44
+ #
45
+ # @see https://www.appVeyor.com/docs/api/ for
46
+ # detailed description of the Appveyor API
47
+
48
+ module Veyor
49
+ extend Configuration
50
+
51
+ define_setting :account_name, ENV['APPVEYOR_ACCOUNT_NAME']
52
+ define_setting :account_token, ENV['APPVEYOR_API_TOKEN']
53
+ define_setting :base_url, "https://ci.appVeyor.com"
54
+
55
+ ##
56
+ # Fetch projects
57
+ #
58
+ # @!macro veyor_options
59
+ # @param verbose [Boolean] Print request headers to stdout. Default: false
60
+ # @return [Array] An array of hashes
61
+ #
62
+ # @example
63
+ # require 'veyor'
64
+ # Veyor.projects()
65
+ def self.projects(options: nil, verbose: false)
66
+ route = prep_route('projects', nil, nil, nil, nil)
67
+ Request.new(route, nil, nil, options, verbose).get
68
+ end
69
+
70
+ ##
71
+ # Get a single project - gets the latest build
72
+ #
73
+ # @!macro veyor_options
74
+ # @!macro veyor_params
75
+ # @param branch [String] Branch name
76
+ # @param version [String] Project version
77
+ # @return [Array] An array of hashes
78
+ #
79
+ # @example
80
+ # require 'veyor'
81
+ # # if account_name already set up
82
+ # Veyor.project(project: 'cowsay')
83
+ #
84
+ # # if not, or to fetch a project not under your account
85
+ # Veyor.project(account: 'sckott', project: 'cowsay')
86
+ #
87
+ # # get by branch
88
+ # Veyor.project(project: 'cowsay', branch: 'changeback')
89
+ #
90
+ # # get by version
91
+ # Veyor.project(project: 'cowsay', version: '1.0.692')
92
+ def self.project(account: nil, project: nil, branch: nil,
93
+ version: nil, options: nil, verbose: false)
94
+
95
+ route = prep_route('projects', get_account(account), project, branch, version)
96
+ Request.new(route, nil, nil, options, verbose).get
97
+ end
98
+
99
+ ##
100
+ # Get project history
101
+ #
102
+ # @!macro veyor_options
103
+ # @!macro veyor_params
104
+ # @!macro history_params
105
+ # @return [Array] An array of hashes
106
+ #
107
+ # @example
108
+ # require 'veyor'
109
+ # # get project history
110
+ # x = Veyor.project_history(project: 'cowsay')
111
+ # x['builds'].collect { |x| x['status'] }
112
+ #
113
+ # # limit results
114
+ # Veyor.project_history(project: 'cowsay', limit: 3)
115
+ #
116
+ # # start by a certain build version
117
+ # Veyor.project_history(project: 'cowsay', start_build: 2872582)
118
+ #
119
+ # # get by branch
120
+ # Veyor.project_history(project: 'cowsay', branch: 'changeback')
121
+ def self.project_history(account: nil, project: nil, limit: 10,
122
+ start_build: nil, branch: nil, options: nil, verbose: false)
123
+
124
+ route = sprintf('/projects/%s/%s/history', get_account(account), project)
125
+ args = prep_args(limit, start_build, branch)
126
+ Request.new(route, args, nil, options, verbose).get
127
+ end
128
+
129
+ ##
130
+ # Get project deployments
131
+ #
132
+ # @!macro veyor_options
133
+ # @!macro veyor_params
134
+ # @return [Array] An array of hashes
135
+ #
136
+ # @example
137
+ # require 'veyor'
138
+ # # get project history
139
+ # x = Veyor.project_deployments(project: 'cowsay')
140
+ # x['deployments']
141
+ def self.project_deployments(account: nil, project: nil, options: nil, verbose: false)
142
+ route = sprintf('/projects/%s/%s/deployments', get_account(account), project)
143
+ Request.new(route, nil, nil, options, verbose).get
144
+ end
145
+
146
+ ##
147
+ # Get project settings
148
+ #
149
+ # @!macro veyor_options
150
+ # @!macro veyor_params
151
+ # @param yaml [Boolean] Return yaml version of project settings. Default: false
152
+ # @return [Array] An array of hashes
153
+ #
154
+ # @example
155
+ # require 'veyor'
156
+ # # get project history
157
+ # x = Veyor.project_settings(project: 'cowsay')
158
+ # x['settings']
159
+ # x['settings']['configuration']
160
+ # # get yaml data
161
+ # x = Veyor.project_settings(project: 'cowsay', yaml: true)
162
+ def self.project_settings(account: nil, project: nil, yaml: false, options: nil, verbose: false)
163
+ route = sprintf('/projects/%s/%s/settings', get_account(account), project)
164
+ if yaml
165
+ route = route + '/yaml'
166
+ end
167
+ Request.new(route, nil, nil, options, verbose).get
168
+ end
169
+
170
+ ##
171
+ # Start build of branch of most recent commit
172
+ #
173
+ # @!macro veyor_options
174
+ # @!macro veyor_params
175
+ # @param branch [String] Branch name
176
+ # @return [Array] An array of hashes
177
+ #
178
+ # @example
179
+ # require 'veyor'
180
+ # # start a build
181
+ # x = Veyor.build_start(project: 'cowsay')
182
+ def self.build_start(account: nil, project:, branch: 'master', options: nil, verbose: false)
183
+ body = { :accountName => get_account(account),
184
+ :projectSlug => project, :branch => branch }
185
+ Request.new('builds', nil, body, options, verbose).post
186
+ end
187
+
188
+ ##
189
+ # Cancel a build
190
+ #
191
+ # @!macro veyor_options
192
+ # @!macro veyor_params
193
+ # @param version [String] Project version
194
+ # @return [Array] An array of hashes
195
+ #
196
+ # @example
197
+ # require 'veyor'
198
+ # # start a build
199
+ # x = Veyor.build_start(project: 'cowsay')
200
+ # x = Veyor.build_cancel(project: 'cowsay', version: '1.0.697')
201
+ def self.build_cancel(account: nil, project:, version:, options: nil, verbose: false)
202
+ route = sprintf('/builds/%s/%s/%s', get_account(account), project, version)
203
+ Request.new(route, nil, nil, options, verbose).delete
204
+ end
205
+
206
+ end
@@ -0,0 +1,22 @@
1
+ module Veyor
2
+ # Custom error class for rescuing from all Veyor errors
3
+ class Error < StandardError; end
4
+
5
+ # Raised when Crossref returns the HTTP status code 400
6
+ class BadRequest < Error; end
7
+
8
+ # Raised when Crossref returns the HTTP status code 404
9
+ class NotFound < Error; end
10
+
11
+ # Raised when Crossref returns the HTTP status code 500
12
+ class InternalServerError < Error; end
13
+
14
+ # Raised when Crossref returns the HTTP status code 502
15
+ class BadGateway < Error; end
16
+
17
+ # Raised when Crossref returns the HTTP status code 503
18
+ class ServiceUnavailable < Error; end
19
+
20
+ # Raised when Crossref returns the HTTP status code 504
21
+ class GatewayTimeout < Error; end
22
+ end
@@ -0,0 +1,71 @@
1
+ require 'faraday'
2
+ require 'multi_json'
3
+
4
+ # @private
5
+ module FaradayMiddleware
6
+ # @private
7
+ class RaiseHttpException < Faraday::Middleware
8
+ def call(env)
9
+ @app.call(env).on_complete do |response|
10
+ case response[:status].to_i
11
+ when 400
12
+ raise Veyor::BadRequest, error_message_400(response)
13
+ when 404
14
+ raise Veyor::NotFound, error_message_400(response)
15
+ when 500
16
+ raise Veyor::InternalServerError, error_message_500(response, "Something is technically wrong.")
17
+ when 502
18
+ raise Veyor::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.")
19
+ when 503
20
+ raise Veyor::ServiceUnavailable, error_message_500(response, "Crossref is rate limiting your requests.")
21
+ when 504
22
+ raise Veyor::GatewayTimeout, error_message_500(response, "504 Gateway Time-out")
23
+ end
24
+ end
25
+ end
26
+
27
+ def initialize(app)
28
+ super app
29
+ @parser = nil
30
+ end
31
+
32
+ private
33
+
34
+ def error_message_400(response)
35
+ "\n #{response[:method].to_s.upcase} #{response[:url].to_s}\n Status #{response[:status]}#{error_body(response[:body])}"
36
+ end
37
+
38
+ def error_body(body)
39
+ if not body.nil? and not body.empty? and body.kind_of?(String)
40
+ if is_json?(body)
41
+ body = ::MultiJson.load(body)
42
+ if body['message'].nil?
43
+ body = nil
44
+ elseif body['message'].length == 1
45
+ body = body['message']
46
+ else
47
+ body = body['message'].collect { |x| x['message'] }.join('; ')
48
+ end
49
+ end
50
+ end
51
+
52
+ if body.nil?
53
+ nil
54
+ else
55
+ ": #{body}"
56
+ end
57
+ end
58
+
59
+ def error_message_500(response, body=nil)
60
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{[response[:status].to_s + ':', body].compact.join(' ')}"
61
+ end
62
+
63
+ def is_json?(string)
64
+ MultiJson.load(string)
65
+ return true
66
+ rescue MultiJson::ParseError => e
67
+ return false
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,26 @@
1
+ # taken from: https://viget.com/extend/easy-gem-configuration-variables-with-defaults
2
+ module Configuration
3
+
4
+ def configuration
5
+ yield self
6
+ end
7
+
8
+ def define_setting(name, default = nil)
9
+ class_variable_set("@@#{name}", default)
10
+ define_class_method "#{name}=" do |value|
11
+ class_variable_set("@@#{name}", value)
12
+ end
13
+ define_class_method name do
14
+ class_variable_get("@@#{name}")
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def define_class_method(name, &block)
21
+ (class << self; self; end).instance_eval do
22
+ define_method name, &block
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,105 @@
1
+ require "faraday"
2
+ require 'faraday_middleware'
3
+ require "multi_json"
4
+
5
+ require 'veyor/faraday'
6
+ require "veyor/error"
7
+ require 'veyor/utils'
8
+ require 'veyor/helpers/configuration'
9
+
10
+ ##
11
+ # veyor::Request
12
+ #
13
+ # Class to perform HTTP requests to the Appveyor API
14
+ module Veyor
15
+ class Request #:nodoc:
16
+
17
+ attr_accessor :route
18
+ attr_accessor :args
19
+ attr_accessor :body
20
+ attr_accessor :options
21
+ attr_accessor :verbose
22
+
23
+ def initialize(route, args, body, options, verbose)
24
+ self.route = route
25
+ self.args = args
26
+ self.body = body
27
+ self.options = options
28
+ self.verbose = verbose
29
+
30
+ self.perform
31
+ end
32
+
33
+ def get
34
+ res = _veyor_get(self.route, self.args)
35
+ return parse_result(res)
36
+ end
37
+
38
+ def post
39
+ res = _veyor_post(self.route, self.body)
40
+ return parse_result(res)
41
+ end
42
+
43
+ def delete
44
+ return _veyor_delete(self.route).status
45
+ end
46
+
47
+ def perform
48
+ if self.args.nil?
49
+ self.args = {}
50
+ end
51
+
52
+ if verbose
53
+ $conn = Faraday.new(:url => Veyor.base_url, :request => options) do |f|
54
+ f.request :url_encoded
55
+ f.response :logger
56
+ f.adapter Faraday.default_adapter
57
+ # f.use FaradayMiddleware::RaiseHttpException
58
+ end
59
+ else
60
+ $conn = Faraday.new(:url => Veyor.base_url, :request => options) do |f|
61
+ f.request :url_encoded
62
+ f.adapter Faraday.default_adapter
63
+ # f.use FaradayMiddleware::RaiseHttpException
64
+ end
65
+ end
66
+
67
+ $conn.headers[:user_agent] = make_ua
68
+ $conn.headers["X-USER-AGENT"] = make_ua
69
+ end
70
+
71
+ def _veyor_get(route, opts)
72
+ $conn.get do |req|
73
+ req.url '/api/' + route
74
+ req.params = opts
75
+ req.headers["Content-Type"] = "application/json"
76
+ req.headers["Authorization"] = "Bearer " + Veyor.account_token
77
+ end
78
+ end
79
+
80
+ def _veyor_post(route, body)
81
+ $conn.post do |req|
82
+ req.url '/api/' + route
83
+ req.body = MultiJson.dump(body)
84
+ req.headers["Content-Type"] = "application/json"
85
+ req.headers["Authorization"] = "Bearer " + Veyor.account_token
86
+ end
87
+ end
88
+
89
+ def _veyor_delete(route)
90
+ $conn.delete do |req|
91
+ req.url '/api/' + route
92
+ req.headers["Authorization"] = "Bearer " + Veyor.account_token
93
+ end
94
+ end
95
+
96
+ def parse_result(z)
97
+ if z.headers['content-type'].match('json').nil?
98
+ return z.body
99
+ else
100
+ return MultiJson.load(z.body)
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,32 @@
1
+ def make_ua
2
+ requa = 'Faraday/v' + Faraday::VERSION
3
+ habua = 'Veyor/v' + Veyor::VERSION
4
+ return requa + ' ' + habua
5
+ end
6
+
7
+ def prep_args(limit, start_build, branch)
8
+ args = { recordsNumber: limit, startBuildId: start_build, branch: branch }
9
+ opts = args.delete_if { |k, v| v.nil? }
10
+ return opts
11
+ end
12
+
13
+ def get_account(x)
14
+ if x.nil?
15
+ x = Veyor.account_name
16
+ if x.nil?
17
+ raise 'no account name found - one must be supplied'
18
+ end
19
+ end
20
+ return x
21
+ end
22
+
23
+ def prep_route(route, account, project, branch, version)
24
+ if branch.nil? && version.nil?
25
+ route = sprintf('%s/%s/%s', route, account, project)
26
+ elsif !branch.nil? && version.nil?
27
+ route = sprintf('%s/%s/%s/branch/%s', route, account, project, branch)
28
+ elsif branch.nil? && !version.nil?
29
+ route = sprintf('%s/%s/%s/build/%s', route, account, project, version)
30
+ end
31
+ return route
32
+ end