semaphore_client 2.3.1 → 2.4.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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/semaphore_client.rb +7 -5
- data/lib/semaphore_client/api/config_file.rb +59 -81
- data/lib/semaphore_client/api/env_var.rb +59 -81
- data/lib/semaphore_client/api/org.rb +15 -27
- data/lib/semaphore_client/api/project.rb +42 -73
- data/lib/semaphore_client/api/shared_config.rb +81 -108
- data/lib/semaphore_client/api/team.rb +50 -85
- data/lib/semaphore_client/api/user.rb +34 -64
- data/lib/semaphore_client/exceptions.rb +34 -2
- data/lib/semaphore_client/http_client.rb +73 -53
- data/lib/semaphore_client/version.rb +1 -1
- data/semaphore_client.gemspec +3 -1
- metadata +21 -7
@@ -5,101 +5,71 @@ class SemaphoreClient
|
|
5
5
|
@http_client = http_client
|
6
6
|
end
|
7
7
|
|
8
|
-
def list_for_org(org_id, query = nil)
|
9
|
-
list_for_org!(org_id, query)
|
10
|
-
rescue SemaphoreClient::Exceptions::RequestFailed
|
11
|
-
end
|
12
8
|
|
13
|
-
def
|
14
|
-
|
15
|
-
rescue SemaphoreClient::Exceptions::
|
9
|
+
def list_for_org(org_id, params = nil, options = {})
|
10
|
+
list_for_org!(org_id, params, options)
|
11
|
+
rescue SemaphoreClient::Exceptions::ResponseError
|
16
12
|
end
|
17
13
|
|
18
|
-
def
|
19
|
-
|
20
|
-
rescue SemaphoreClient::Exceptions::RequestFailed
|
21
|
-
end
|
14
|
+
def list_for_org!(org_id, params = nil, options = {})
|
15
|
+
path = "/orgs/#{org_id}/users"
|
22
16
|
|
23
|
-
|
24
|
-
detach_from_team!(user_id, team_id)
|
25
|
-
rescue SemaphoreClient::Exceptions::RequestFailed
|
17
|
+
@http_client.get(path, params, options = {}).body.map { |e| SemaphoreClient::Model::User.load(e) }
|
26
18
|
end
|
27
19
|
|
28
|
-
def list_for_project(project_id, query = nil)
|
29
|
-
list_for_project!(project_id, query)
|
30
|
-
rescue SemaphoreClient::Exceptions::RequestFailed
|
31
|
-
end
|
32
20
|
|
33
|
-
def list_for_org!(org_id, query = nil)
|
34
|
-
query_string =
|
35
|
-
unless query.nil? || query.empty?
|
36
|
-
"?" + query.map { |key, value| "#{key}=#{value}" }.join("&")
|
37
|
-
end
|
38
21
|
|
39
|
-
|
40
|
-
|
41
|
-
|
22
|
+
def list_for_team(team_id, params = nil, options = {})
|
23
|
+
list_for_team!(team_id, params, options)
|
24
|
+
rescue SemaphoreClient::Exceptions::ResponseError
|
25
|
+
end
|
42
26
|
|
43
|
-
|
27
|
+
def list_for_team!(team_id, params = nil, options = {})
|
28
|
+
path = "/teams/#{team_id}/users"
|
44
29
|
|
45
|
-
|
46
|
-
SemaphoreClient::Model::User.load(entity)
|
47
|
-
end
|
30
|
+
@http_client.get(path, params, options = {}).body.map { |e| SemaphoreClient::Model::User.load(e) }
|
48
31
|
end
|
49
32
|
|
50
|
-
def list_for_team!(team_id, query = nil)
|
51
|
-
query_string =
|
52
|
-
unless query.nil? || query.empty?
|
53
|
-
"?" + query.map { |key, value| "#{key}=#{value}" }.join("&")
|
54
|
-
end
|
55
33
|
|
56
|
-
response = @http_client.get([:teams, team_id, :users, query_string].compact)
|
57
34
|
|
58
|
-
|
35
|
+
def attach_to_team(user_id, team_id, params = nil, options = {})
|
36
|
+
attach_to_team!(user_id, team_id, params, options)
|
37
|
+
rescue SemaphoreClient::Exceptions::ResponseError
|
38
|
+
end
|
59
39
|
|
60
|
-
|
40
|
+
def attach_to_team!(user_id, team_id, params = nil, options = {})
|
41
|
+
path = "/teams/#{team_id}/users/#{user_id}"
|
61
42
|
|
62
|
-
|
63
|
-
SemaphoreClient::Model::User.load(entity)
|
64
|
-
end
|
43
|
+
@http_client.post(path, params, options)
|
65
44
|
end
|
66
45
|
|
67
|
-
def attach_to_team!(user_id, team_id)
|
68
|
-
response = @http_client.post([:teams, team_id, :users, user_id])
|
69
46
|
|
70
|
-
|
47
|
+
|
48
|
+
def detach_from_team(user_id, team_id, params = nil, options = {})
|
49
|
+
detach_from_team!(user_id, team_id, params, options)
|
50
|
+
rescue SemaphoreClient::Exceptions::ResponseError
|
71
51
|
end
|
72
52
|
|
73
|
-
def detach_from_team!(user_id, team_id)
|
74
|
-
|
53
|
+
def detach_from_team!(user_id, team_id, params = nil, options = {})
|
54
|
+
path = "/teams/#{team_id}/users/#{user_id}"
|
75
55
|
|
76
|
-
|
56
|
+
@http_client.delete(path, params, options)
|
77
57
|
end
|
78
58
|
|
79
|
-
def list_for_project!(project_id, query = nil)
|
80
|
-
query_string =
|
81
|
-
unless query.nil? || query.empty?
|
82
|
-
"?" + query.map { |key, value| "#{key}=#{value}" }.join("&")
|
83
|
-
end
|
84
59
|
|
85
|
-
response = @http_client.get([:projects, project_id, :users, query_string].compact)
|
86
60
|
|
87
|
-
|
61
|
+
def list_for_project(project_id, params = nil, options = {})
|
62
|
+
list_for_project!(project_id, params, options)
|
63
|
+
rescue SemaphoreClient::Exceptions::ResponseError
|
64
|
+
end
|
88
65
|
|
89
|
-
|
66
|
+
def list_for_project!(project_id, params = nil, options = {})
|
67
|
+
path = "/projects/#{project_id}/users"
|
90
68
|
|
91
|
-
|
92
|
-
SemaphoreClient::Model::User.load(entity)
|
93
|
-
end
|
69
|
+
@http_client.get(path, params, options = {}).body.map { |e| SemaphoreClient::Model::User.load(e) }
|
94
70
|
end
|
95
71
|
|
96
|
-
private
|
97
72
|
|
98
|
-
def assert_response_status(response, expected_status)
|
99
|
-
return if response.status == expected_status
|
100
|
-
|
101
|
-
raise SemaphoreClient::Exceptions::RequestFailed, response.status
|
102
|
-
end
|
103
73
|
end
|
104
74
|
end
|
105
75
|
end
|
@@ -1,6 +1,38 @@
|
|
1
1
|
class SemaphoreClient
|
2
2
|
class Exceptions
|
3
|
-
class
|
4
|
-
|
3
|
+
class Base < StandardError; end
|
4
|
+
|
5
|
+
class AttributeNotAvailable < Base; end
|
6
|
+
|
7
|
+
class ResponseError < Base
|
8
|
+
attr_reader :env
|
9
|
+
|
10
|
+
def initialize(env)
|
11
|
+
@env = env
|
12
|
+
|
13
|
+
super(env[:message])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# 400
|
18
|
+
class BadRequest < ResponseError; end
|
19
|
+
|
20
|
+
# 401
|
21
|
+
class Unauthorized < ResponseError; end
|
22
|
+
|
23
|
+
# 404
|
24
|
+
class NotFound < ResponseError; end
|
25
|
+
|
26
|
+
# 405
|
27
|
+
class NotAllowed < ResponseError; end
|
28
|
+
|
29
|
+
# 409
|
30
|
+
class Conflict < ResponseError; end
|
31
|
+
|
32
|
+
# 422
|
33
|
+
class UnprocessableEntity < ResponseError; end
|
34
|
+
|
35
|
+
# 500+
|
36
|
+
class ServerError < ResponseError; end
|
5
37
|
end
|
6
38
|
end
|
@@ -1,87 +1,107 @@
|
|
1
1
|
class SemaphoreClient
|
2
|
+
|
2
3
|
class HttpClient
|
3
|
-
class RouteNotSupported < StandardError; end
|
4
4
|
|
5
|
-
|
5
|
+
class ResponseErrorMiddleware < Faraday::Middleware
|
6
|
+
def call(env)
|
7
|
+
@app.call(env).on_complete do |env|
|
8
|
+
case env[:status]
|
9
|
+
when 401
|
10
|
+
raise SemaphoreClient::Exceptions::Unauthorized, env
|
11
|
+
when 404
|
12
|
+
raise SemaphoreClient::Exceptions::NotFound, env
|
13
|
+
when 405
|
14
|
+
raise SemaphoreClient::Exceptions::NotAllowed, env
|
15
|
+
when 409
|
16
|
+
raise SemaphoreClient::Exceptions::Conflict, env
|
17
|
+
when 422
|
18
|
+
raise SemaphoreClient::Exceptions::UnprocessableEntity, env
|
19
|
+
when 400...500
|
20
|
+
raise SemaphoreClient::Exceptions::BadRequest, env
|
21
|
+
when 500...600
|
22
|
+
raise SemaphoreClient::Exceptions::ServerError, env
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(auth_token, api_url, api_version, verbose, logger, auto_paginate)
|
6
29
|
@auth_token = auth_token
|
7
30
|
@api_url = api_url
|
8
31
|
@api_version = api_version
|
9
32
|
@verbose = verbose
|
10
33
|
@logger = logger
|
34
|
+
@auto_paginate = auto_paginate
|
11
35
|
end
|
12
36
|
|
13
|
-
def get(
|
14
|
-
|
37
|
+
def get(path, params = nil, options = {})
|
38
|
+
api_call(:get, path, params, options)
|
39
|
+
end
|
15
40
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
41
|
+
def post(path, params = nil, options = {})
|
42
|
+
api_call(:post, path, params, options)
|
19
43
|
end
|
20
44
|
|
21
|
-
def
|
22
|
-
|
45
|
+
def patch(path, params = nil, options = {})
|
46
|
+
api_call(:patch, path, params, options)
|
47
|
+
end
|
23
48
|
|
24
|
-
|
25
|
-
|
26
|
-
connection.post(route, content)
|
27
|
-
end
|
28
|
-
else
|
29
|
-
trace("POST", route) do
|
30
|
-
connection.post(route)
|
31
|
-
end
|
32
|
-
end
|
49
|
+
def delete(path, params = nil, options = {})
|
50
|
+
api_call(:delete, path, params, options)
|
33
51
|
end
|
34
52
|
|
35
|
-
|
36
|
-
route = route(route_elements)
|
53
|
+
private
|
37
54
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
55
|
+
def api_call(method, path, params = nil, options = {})
|
56
|
+
response = connection.public_send(method, "/#{@api_version}/#{path}", params)
|
57
|
+
|
58
|
+
if auto_paginate?(options)
|
59
|
+
links = parse_links(response)
|
60
|
+
|
61
|
+
if links[:next]
|
62
|
+
# recursivly follow the :next link
|
63
|
+
next_response = api_call(method, links[:next], params, options)
|
64
|
+
|
65
|
+
# append the rest to the body of the original request
|
66
|
+
response.body.concat(next_response.body)
|
45
67
|
end
|
46
68
|
end
|
69
|
+
|
70
|
+
response
|
47
71
|
end
|
48
72
|
|
49
|
-
def
|
50
|
-
|
73
|
+
def auto_paginate?(options)
|
74
|
+
# first check the options, then the global settings
|
75
|
+
options.key?(:auto_paginate) ? options[:auto_paginate] : @auto_paginate
|
76
|
+
end
|
51
77
|
|
52
|
-
|
53
|
-
|
78
|
+
def parse_links(response)
|
79
|
+
links = ( response.headers["Link"] || "" ).split(', ').map do |link|
|
80
|
+
href, name = link.match(/<(.*?)>; rel="(\w+)"/).captures
|
81
|
+
|
82
|
+
[name.to_sym, href.gsub("#{@api_url}/v2", "")]
|
54
83
|
end
|
55
|
-
end
|
56
84
|
|
57
|
-
|
85
|
+
Hash[*links.flatten]
|
86
|
+
end
|
58
87
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
88
|
+
def connection
|
89
|
+
@connection ||= Faraday.new(:url => @api_url, :headers => headers) do |conn|
|
90
|
+
conn.request :json
|
91
|
+
conn.response :json
|
63
92
|
|
64
|
-
@
|
65
|
-
|
93
|
+
if @verbose
|
94
|
+
conn.response :logger, @logger, :headers => false, :bodies => true
|
95
|
+
end
|
66
96
|
|
67
|
-
|
68
|
-
@logger.info "#{id} #{response.status} duration: #{finished_at - started_at}s body: #{response.body}"
|
97
|
+
conn.use SemaphoreClient::HttpClient::ResponseErrorMiddleware
|
69
98
|
|
70
|
-
|
71
|
-
else
|
72
|
-
yield
|
99
|
+
conn.adapter Faraday.default_adapter
|
73
100
|
end
|
74
101
|
end
|
75
102
|
|
76
|
-
def
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
def connection
|
81
|
-
@connection ||= Faraday.new(
|
82
|
-
:url => @api_url,
|
83
|
-
:headers => { "Authorization" => "Token #{@auth_token}" }
|
84
|
-
)
|
103
|
+
def headers
|
104
|
+
{ "Authorization" => "Token #{@auth_token}" }
|
85
105
|
end
|
86
106
|
end
|
87
107
|
end
|
data/semaphore_client.gemspec
CHANGED
@@ -20,7 +20,9 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_dependency "faraday"
|
23
|
+
spec.add_dependency "faraday", "~> 0.13.1"
|
24
|
+
spec.add_dependency "faraday_middleware", "~> 0.12.2"
|
25
|
+
|
24
26
|
spec.add_development_dependency "byebug"
|
25
27
|
spec.add_development_dependency "bundler", "~> 1.14"
|
26
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semaphore_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jovan Ivanović
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.13.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.13.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday_middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.12.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.12.2
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: byebug
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
151
|
version: '0'
|
138
152
|
requirements: []
|
139
153
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.6.13
|
141
155
|
signing_key:
|
142
156
|
specification_version: 4
|
143
157
|
summary: Client for Semaphore's API.
|