bugherd_client 0.0.6 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +2 -1
- data/.travis.yml +4 -1
- data/README.md +23 -38
- data/Rakefile +6 -1
- data/bin/console +17 -0
- data/bugherd_client.gemspec +17 -13
- data/lib/bugherd_client.rb +19 -16
- data/lib/bugherd_client/client.rb +44 -18
- data/lib/bugherd_client/errors.rb +19 -5
- data/lib/bugherd_client/resources/v1/base.rb +2 -2
- data/lib/bugherd_client/resources/v1/comment.rb +1 -1
- data/lib/bugherd_client/resources/v1/project.rb +4 -4
- data/lib/bugherd_client/resources/v1/task.rb +11 -8
- data/lib/bugherd_client/resources/v2/attachment.rb +73 -0
- data/lib/bugherd_client/resources/v2/base.rb +24 -5
- data/lib/bugherd_client/resources/v2/comment.rb +2 -2
- data/lib/bugherd_client/resources/v2/organization.rb +5 -5
- data/lib/bugherd_client/resources/v2/project.rb +22 -13
- data/lib/bugherd_client/resources/v2/task.rb +34 -14
- data/lib/bugherd_client/resources/v2/webhook.rb +54 -0
- data/lib/bugherd_client/version.rb +1 -1
- data/spec/bugherd_client/client_spec.rb +63 -11
- data/spec/bugherd_client/v2/organization_spec.rb +21 -0
- data/spec/bugherd_client/v2/project_spec.rb +66 -0
- data/spec/bugherd_client/v2/task_spec.rb +46 -0
- data/spec/bugherd_client/v2/user_spec.rb +50 -0
- data/spec/bugherd_client/v2/webhook_spec.rb +20 -0
- data/spec/cassettes/guests_all.yml +64 -0
- data/spec/cassettes/members_all.yml +66 -0
- data/spec/cassettes/organizations_get.yml +62 -0
- data/spec/cassettes/projects_active.yml +65 -0
- data/spec/cassettes/projects_all.yml +65 -0
- data/spec/cassettes/projects_find_failure.yml +60 -0
- data/spec/cassettes/projects_find_success.yml +65 -0
- data/spec/cassettes/tasks_all.yml +87 -0
- data/spec/cassettes/tasks_find_success.yml +69 -0
- data/spec/cassettes/users_all.yml +66 -0
- data/spec/cassettes/webhooks_all.yml +64 -0
- data/spec/spec_helper.rb +23 -9
- data/spec/support/http_helper.rb +7 -0
- metadata +130 -23
@@ -12,7 +12,7 @@ module BugherdClient
|
|
12
12
|
STATUSES = ['feedback', 'backlog','todo','doing','done','closed']
|
13
13
|
STATUSES.each.with_index do |status, index|
|
14
14
|
if index == 0
|
15
|
-
Task.const_set("STATUS_#{status.upcase}", nil)
|
15
|
+
Task.const_set("STATUS_#{status.upcase}", nil)
|
16
16
|
else
|
17
17
|
Task.const_set("STATUS_#{status.upcase}", index-1)
|
18
18
|
end
|
@@ -37,15 +37,15 @@ module BugherdClient
|
|
37
37
|
|
38
38
|
#
|
39
39
|
# Create a new Task
|
40
|
-
# attributes:
|
41
|
-
# description, priority, status, tag_names(Array),
|
42
|
-
# requester_id or requester_email,
|
40
|
+
# attributes:
|
41
|
+
# description, priority, status, tag_names(Array),
|
42
|
+
# requester_id or requester_email,
|
43
43
|
# assigned_to_id or assigned_to_email
|
44
44
|
# external_id
|
45
45
|
# if status is null the Task is automatically put in the Feedback panel
|
46
|
-
#
|
47
|
-
# Values for
|
48
|
-
# Values for
|
46
|
+
# 'requester_email' can be any email address while 'assigned_to_email' needs to be of a current project member.
|
47
|
+
# Values for 'priority' are not set, critical, important, normal, and minor.
|
48
|
+
# Values for 'status' are backlog, todo, doing, done, and closed. Omit this field or set as 'null' to send tasks to the Feedback panel.
|
49
49
|
# External ID is an API-only field. It cannot be set from the BugHerd application, only using the API. An external ID can be used to track originating IDs from other systems in BugHerd bugs.
|
50
50
|
def create(project_id, attributes={})
|
51
51
|
raw_response = post_request("projects/#{project_id}/tasks", task: attributes)
|
@@ -57,8 +57,11 @@ module BugherdClient
|
|
57
57
|
parse_response(raw_response)
|
58
58
|
end
|
59
59
|
|
60
|
+
def delete(project_id, task_id)
|
61
|
+
end
|
62
|
+
|
60
63
|
end
|
61
64
|
|
62
65
|
end
|
63
66
|
end
|
64
|
-
end
|
67
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module BugherdClient
|
2
|
+
module Resources
|
3
|
+
module V2
|
4
|
+
|
5
|
+
class Attachment < Base
|
6
|
+
|
7
|
+
# LIST
|
8
|
+
#
|
9
|
+
# Get a paginated list of attachments for a task.
|
10
|
+
# GET /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments.json
|
11
|
+
def all(project_id, task_id)
|
12
|
+
raw_response = get_request("projects/#{project_id}/tasks/#{task_id}/attachments")
|
13
|
+
parse_response(raw_response, :attachments)
|
14
|
+
end
|
15
|
+
|
16
|
+
# SHOW
|
17
|
+
#
|
18
|
+
# Get detail for specific attachment.
|
19
|
+
# GET /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/#{id}.json
|
20
|
+
def find(project_id, task_id, attachment_id)
|
21
|
+
raw_response = get_request("projects/#{project_id}/tasks/#{task_id}/attachments/#{attachment_id}")
|
22
|
+
parse_response(raw_response)
|
23
|
+
end
|
24
|
+
|
25
|
+
# CREATE
|
26
|
+
#
|
27
|
+
# Adds a new attachment to the specified task using an existing URL.
|
28
|
+
# POST /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments.json
|
29
|
+
#
|
30
|
+
# PARAMS
|
31
|
+
# {'attachment':{
|
32
|
+
# 'file_name':'resolution.gif',
|
33
|
+
# 'url':'http://i.imgur.com/U9h3jZI.gif'
|
34
|
+
# }}
|
35
|
+
def create(project_id, task_id, payload)
|
36
|
+
raw_response = post_request("projects/#{project_id}/tasks/#{task_id}/attachments", attachment: payload)
|
37
|
+
parse_response(raw_response, :attachment)
|
38
|
+
end
|
39
|
+
|
40
|
+
# UPLOAD
|
41
|
+
#
|
42
|
+
# Upload a new attachment and add it to the specified task.
|
43
|
+
# The file contents need to be specified as the POST data on this request.
|
44
|
+
#
|
45
|
+
# Note that your upload needs to be reasonable in size as the maximum time the request
|
46
|
+
# may take is around 30 seconds.
|
47
|
+
# If you have larger uploads please create arrange your own file upload
|
48
|
+
# and create the attachment from a URL instead.
|
49
|
+
#
|
50
|
+
# POST /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/upload
|
51
|
+
#
|
52
|
+
# Note in the sample below please specify an existing file name.
|
53
|
+
def upload(project_id, task_id, payload)
|
54
|
+
uri = "projects/#{project_id}/tasks/#{task_id}/attachments/upload"
|
55
|
+
headers = { content_type: 'application/binary' }
|
56
|
+
raw_response = post_request(uri, payload.merge(headers: headers))
|
57
|
+
parse_response(raw_response, :attachment)
|
58
|
+
end
|
59
|
+
|
60
|
+
# DELETE
|
61
|
+
#
|
62
|
+
# Delete an attachment from a task. Note that this action is permanent and cannot be undone.
|
63
|
+
# DELETE /api_v2/projects/#{project_id}/tasks/#{task_id}/attachments/#{id}.json
|
64
|
+
def delete(project_id, task_id, attachment_id)
|
65
|
+
raw_response = delete_request("projects/#{project_id}/tasks/#{task_id}/attachments/#{attachment_id}")
|
66
|
+
parse_response(raw_response)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end # V2
|
72
|
+
end # Resources
|
73
|
+
end # BugherdClient
|
@@ -18,16 +18,22 @@ module BugherdClient
|
|
18
18
|
self.class.instance_methods(false)
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
# store a reference to the HTTP connection
|
22
|
+
attr_accessor :connection
|
23
|
+
|
24
|
+
attr_accessor :options
|
25
|
+
|
22
26
|
def initialize(conn, opts={})
|
23
27
|
@connection, @options = conn, opts
|
24
28
|
end
|
25
29
|
|
26
|
-
def send_request(method=
|
30
|
+
def send_request(method='GET', path='', params={}, headers={})
|
27
31
|
headers = DEFAULT_HEADER_ATTRS.merge(headers)
|
28
32
|
params.merge!(headers)
|
29
33
|
method_name = method.to_s.downcase
|
30
34
|
self.connection[path].__send__(method_name, params)
|
35
|
+
rescue RestClient::Exception => e
|
36
|
+
raise(BugherdClient::Errors::HttpRequestError.new(e.message, e.http_code))
|
31
37
|
end
|
32
38
|
|
33
39
|
[:get, :post, :put, :patch, :delete].each do |method_name|
|
@@ -36,16 +42,29 @@ module BugherdClient
|
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
45
|
+
def converter(body)
|
46
|
+
case body
|
47
|
+
when Hash
|
48
|
+
::Hashie::Mash.new(body)
|
49
|
+
when Array
|
50
|
+
body.map { |item| item.is_a?(Hash) ? converter(item) : item }
|
51
|
+
else
|
52
|
+
body
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
39
56
|
def parse_response(response, root_element=nil)
|
40
|
-
if root_element
|
41
|
-
JSON.parse(response)
|
57
|
+
parsed = if root_element
|
58
|
+
p = JSON.parse(response)
|
59
|
+
p.key?(root_element.to_s) ? p[root_element.to_s] : p
|
42
60
|
else
|
43
61
|
JSON.parse(response)
|
44
62
|
end
|
63
|
+
converter(parsed)
|
45
64
|
end
|
46
65
|
|
47
66
|
end
|
48
67
|
|
49
68
|
end
|
50
69
|
end
|
51
|
-
end
|
70
|
+
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module BugherdClient
|
2
2
|
module Resources
|
3
3
|
module V2
|
4
|
-
|
4
|
+
|
5
5
|
class Organization < Base
|
6
6
|
|
7
7
|
#
|
8
8
|
# Get more detail of your account.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
def get
|
11
11
|
raw_response = self.connection['organization'].get
|
12
12
|
parse_response(raw_response, :organization)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
16
|
+
end # V2
|
17
|
+
end # Resources
|
18
|
+
end # BugherdClient
|
@@ -6,7 +6,7 @@ module BugherdClient
|
|
6
6
|
|
7
7
|
#
|
8
8
|
# Get more detail of your account.
|
9
|
-
#
|
9
|
+
#
|
10
10
|
def all
|
11
11
|
raw_response = get_request('projects')
|
12
12
|
parse_response(raw_response, :projects)
|
@@ -14,18 +14,27 @@ module BugherdClient
|
|
14
14
|
|
15
15
|
#
|
16
16
|
# Show details for a specific project
|
17
|
-
#
|
17
|
+
#
|
18
18
|
def find(project_id)
|
19
19
|
raw_response = get_request("projects/#{project_id}")
|
20
20
|
parse_response(raw_response, :project)
|
21
21
|
end
|
22
22
|
|
23
|
+
# CREATE
|
24
|
+
#
|
25
|
+
# Create a new project. The project will initially have no members.
|
26
|
+
# POST /api_v2/projects.json
|
27
|
+
#
|
28
|
+
# PARAMS:
|
29
|
+
# {
|
30
|
+
# "name": "My Website",
|
31
|
+
# "devurl": "http://www.example.com",
|
32
|
+
# "is_active": true,
|
33
|
+
# "is_public": false
|
34
|
+
# }
|
23
35
|
#
|
24
|
-
# Create a Project, will initially have no members
|
25
|
-
# attributes: name, devurl, is_public, is_active
|
26
|
-
#
|
27
36
|
def create(attributes={})
|
28
|
-
raw_response = post_request(
|
37
|
+
raw_response = post_request('projects', project: attributes)
|
29
38
|
parse_response(raw_response, :project)
|
30
39
|
end
|
31
40
|
|
@@ -37,7 +46,7 @@ module BugherdClient
|
|
37
46
|
parse_response(raw_response, :project)
|
38
47
|
end
|
39
48
|
|
40
|
-
#
|
49
|
+
#
|
41
50
|
# Delete a project and all associated data. Use with care, deleted projects cannot be recovered.
|
42
51
|
# API: 1,2
|
43
52
|
def delete(project_id)
|
@@ -45,7 +54,7 @@ module BugherdClient
|
|
45
54
|
parse_response(raw_response)
|
46
55
|
end
|
47
56
|
|
48
|
-
#
|
57
|
+
#
|
49
58
|
# Add an existing guest to a project, or invite someone by email address.
|
50
59
|
# required: project_id
|
51
60
|
# attributes: user_id, email
|
@@ -55,11 +64,11 @@ module BugherdClient
|
|
55
64
|
parse_response(raw_response)
|
56
65
|
end
|
57
66
|
|
58
|
-
#
|
67
|
+
#
|
59
68
|
# Add an existing guest to a project, or invite someone by email address.
|
60
69
|
# required: project_id
|
61
70
|
# attributes: user_id
|
62
|
-
#
|
71
|
+
#
|
63
72
|
def add_member(project_id, attributes={})
|
64
73
|
raw_response = post_request("projects/#{project_id}/add_member", attributes)
|
65
74
|
parse_response(raw_response)
|
@@ -68,13 +77,13 @@ module BugherdClient
|
|
68
77
|
|
69
78
|
#
|
70
79
|
# Get all active projects
|
71
|
-
#
|
80
|
+
#
|
72
81
|
def active
|
73
82
|
raw_response = get_request('projects/active')
|
74
83
|
parse_response(raw_response, :projects)
|
75
84
|
end
|
76
85
|
end
|
77
|
-
|
86
|
+
|
78
87
|
end
|
79
88
|
end
|
80
|
-
end
|
89
|
+
end
|
@@ -5,20 +5,31 @@ module BugherdClient
|
|
5
5
|
class Task < Base
|
6
6
|
|
7
7
|
PRIORITIES = ['not set', 'critical', 'important', 'normal','minor']
|
8
|
-
PRIORITIES.each
|
9
|
-
|
8
|
+
PRIORITIES.each { |p| Task.const_set("PRIORITY_#{p.gsub(' ', '').upcase}", p) }
|
9
|
+
def priorities
|
10
|
+
self.class::PRIORITIES
|
10
11
|
end
|
11
12
|
|
12
|
-
STATUSES
|
13
|
-
STATUSES.each
|
14
|
-
|
13
|
+
STATUSES = ['backlog','todo','doing','done','closed']
|
14
|
+
STATUSES.each { |s| Task.const_set("STATUS_#{s.upcase}", s) }
|
15
|
+
def statuses
|
16
|
+
self.class::STATUSES
|
15
17
|
end
|
16
18
|
|
19
|
+
VALID_QUERY_KEYS = [:page, :updated_since, :created_since, :status, :priority, :assigned_to_id, :external_id]
|
20
|
+
|
17
21
|
#
|
18
22
|
# Get a full list of tasks for a project, including archived tasks.
|
19
|
-
# filters: updated_since, created_since, status, priority, tag
|
23
|
+
# filters: updated_since, created_since, status, priority, tag,
|
24
|
+
# assigned_to_id, and external_id.
|
25
|
+
#
|
26
|
+
# example:
|
27
|
+
#
|
28
|
+
# client.tasks.all(45, { status: 'backlog' })
|
29
|
+
#
|
20
30
|
def all(project_id, filter_attributes={})
|
21
31
|
params = filter_attributes.empty? ? {} : { params: filter_attributes }
|
32
|
+
validate_filter_attributes!(filter_attributes) unless filter_attributes.empty?
|
22
33
|
raw_response = get_request("projects/#{project_id}/tasks", params)
|
23
34
|
parse_response(raw_response, :tasks)
|
24
35
|
end
|
@@ -28,20 +39,20 @@ module BugherdClient
|
|
28
39
|
#
|
29
40
|
def find(project_id, task_id)
|
30
41
|
raw_response = get_request("projects/#{project_id}/tasks/#{task_id}")
|
31
|
-
parse_response(raw_response)
|
42
|
+
parse_response(raw_response, :task)
|
32
43
|
end
|
33
44
|
|
34
45
|
#
|
35
46
|
# Create a new Task
|
36
|
-
# attributes:
|
37
|
-
# description, priority, status, tag_names(Array),
|
38
|
-
# requester_id or requester_email,
|
47
|
+
# attributes:
|
48
|
+
# description, priority, status, tag_names(Array),
|
49
|
+
# requester_id or requester_email,
|
39
50
|
# assigned_to_id or assigned_to_email
|
40
51
|
# external_id
|
41
52
|
# if status is null the Task is automatically put in the Feedback panel
|
42
|
-
#
|
43
|
-
# Values for
|
44
|
-
# Values for
|
53
|
+
# 'requester_email' can be any email address while 'assigned_to_email' needs to be of a current project member.
|
54
|
+
# Values for 'priority' are not set, critical, important, normal, and minor.
|
55
|
+
# Values for 'status' are backlog, todo, doing, done, and closed. Omit this field or set as 'null' to send tasks to the Feedback panel.
|
45
56
|
# External ID is an API-only field. It cannot be set from the BugHerd application, only using the API. An external ID can be used to track originating IDs from other systems in BugHerd bugs.
|
46
57
|
def create(project_id, attributes={})
|
47
58
|
raw_response = post_request("projects/#{project_id}/tasks", task: attributes)
|
@@ -53,8 +64,17 @@ module BugherdClient
|
|
53
64
|
parse_response(raw_response)
|
54
65
|
end
|
55
66
|
|
67
|
+
private
|
68
|
+
def validate_filter_attributes!(input_filters = {})
|
69
|
+
input_filters.keys.compact.each do |k|
|
70
|
+
unless VALID_QUERY_KEYS.include?(k.to_sym)
|
71
|
+
raise(BugherdClient::Errors::InvalidQueryKey.new(k, VALID_QUERY_KEYS))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
56
76
|
end
|
57
77
|
|
58
78
|
end
|
59
79
|
end
|
60
|
-
end
|
80
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module BugherdClient
|
2
|
+
module Resources
|
3
|
+
module V2
|
4
|
+
class Webhook < Base
|
5
|
+
|
6
|
+
EVENTS = ['task_create', 'task_update', 'task_destroy', 'comment']
|
7
|
+
def events
|
8
|
+
self.class::EVENTS
|
9
|
+
end
|
10
|
+
|
11
|
+
# LIST
|
12
|
+
#
|
13
|
+
# Get a list of currently installed webhooks.
|
14
|
+
#
|
15
|
+
# GET /api_v2/webhooks.json
|
16
|
+
def all
|
17
|
+
raw_response = get_request('webhooks')
|
18
|
+
parse_response(raw_response, :webhooks)
|
19
|
+
end
|
20
|
+
|
21
|
+
# CREATE
|
22
|
+
#
|
23
|
+
# When installing a webhook, specify an event you wish to hook into.
|
24
|
+
# Choose from: 'task_create', 'task_update', 'comment' or 'task_destroy'.
|
25
|
+
# To get activity for all 3 events, create an entry for each event.
|
26
|
+
#
|
27
|
+
# 'project_id' is optional; it only needs to be specified if you'd only like
|
28
|
+
# events on a specific project. Omitting 'project_id' results in notifications
|
29
|
+
# of activity on all your projects.
|
30
|
+
#
|
31
|
+
# PARAMS
|
32
|
+
# {
|
33
|
+
# 'project_id':1,
|
34
|
+
# 'target_url':'https://app.example.com/api/bugherd_sync/project/1/task_create',
|
35
|
+
# 'event':'task_create'
|
36
|
+
# }
|
37
|
+
#
|
38
|
+
def create(payload = {})
|
39
|
+
raw_response = post_request('webhooks', payload)
|
40
|
+
parse_response(raw_response, :webhook)
|
41
|
+
end
|
42
|
+
|
43
|
+
# DELETE
|
44
|
+
#
|
45
|
+
# DELETE /api_v2/webhooks/#{id}.json
|
46
|
+
def delete(webhook_id)
|
47
|
+
raw_response = delete_request("webhooks/#{webhook_id}")
|
48
|
+
parse_response(raw_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end # V2
|
53
|
+
end # Resources
|
54
|
+
end # BugherdClient
|