clubhouse2 0.0.1 → 0.0.2
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/README.md +61 -0
- data/VERSION +1 -1
- data/lib/clubhouse2/client.rb +0 -2
- data/lib/clubhouse2/clubhouse_resource.rb +5 -1
- data/lib/clubhouse2/workflow.rb +1 -1
- metadata +2 -2
- data/lib/clubhouse2/ops-migration.rb +0 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 569d926370ed4d73fef21487292e1c20764ec833
|
4
|
+
data.tar.gz: 8d1563ec86cd3a03d1191b65586598dc2389e43c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1dc4c5513c835f155e22f77c9bbfa8d84f37aba8422d5ebd0dcadbcdf52c243e0a10911003d7827c1be0aeb7b57f56fa68eff1d6696479dc12fbe4d30354e1e
|
7
|
+
data.tar.gz: 796c45550edc55e53b76d3c74337f45d34c610b6a3ca2f26b2b1adb87bc4364b516b858df575f610b06de3d74466c9e5eef87dc1a4a92a3b31acc4cc3ac489b7
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Clubhouse API v2 Ruby Gem
|
2
|
+
|
3
|
+
This is a resource-oriented ruby library for interacting with the Clubhouse v2 API.
|
4
|
+
|
5
|
+
## How to use
|
6
|
+
|
7
|
+
### Initializing the client
|
8
|
+
require 'clubhouse2'
|
9
|
+
client = Clubhouse::Client.new(api_key: 'your_api_key')
|
10
|
+
|
11
|
+
### Querying
|
12
|
+
|
13
|
+
#### Quick-start
|
14
|
+
Get all stories being followed by a user called 'James'.
|
15
|
+
client.stories(follower_ids: client.member(name: 'James'))
|
16
|
+
|
17
|
+
Get all stories in the 'Testing' project in the 'Completed' state.
|
18
|
+
client.project(name: 'Testing').stories(workflow_state_id: client.workflow.state(name: 'Completed').id)
|
19
|
+
|
20
|
+
Get the names of all stories in the 'Testing' project
|
21
|
+
client.project(name: 'Testing').stories.collect(&:name)
|
22
|
+
|
23
|
+
Get all non-archived stories with the label 'Out Of Hours'
|
24
|
+
client.stories(archived: false, labels: client.label(name: 'Out Of Hours'))
|
25
|
+
|
26
|
+
Get all stories last updated more than 30 days ago
|
27
|
+
client.stories.select { |story| story.updated_at < Date.today - 30 }
|
28
|
+
|
29
|
+
#### Methods returning arrays of resources
|
30
|
+
client.projects # list all projects
|
31
|
+
client.milestones # list all milestones
|
32
|
+
client.members # list all members (users)
|
33
|
+
client.epics # list all epics
|
34
|
+
client.stories # list all stories, comments and tasks [WARNING: slow!]
|
35
|
+
client.categories # list all categories
|
36
|
+
client.workflows # list all workflows and states
|
37
|
+
client.labels # list all labels
|
38
|
+
client.teams # list all teams
|
39
|
+
|
40
|
+
#### Methods returning single resources
|
41
|
+
client.project # list the first matching project
|
42
|
+
client.milestone # list the first matching milestone
|
43
|
+
client.member # list the first matching member (user)
|
44
|
+
client.epic # list the first matching epic
|
45
|
+
client.story # list the first matching story [WARNING: slow!]
|
46
|
+
client.category # list the first matching category
|
47
|
+
client.workflow # list the first matching workflow (usually Default)
|
48
|
+
client.label # list the first matching label
|
49
|
+
client.team # list the first matching team
|
50
|
+
|
51
|
+
#### Filtering
|
52
|
+
It's possible to filter by any resource property provided by the API. Multiple property filters can be specified.
|
53
|
+
|
54
|
+
client.project(id: 123) # get a specific project
|
55
|
+
client.project(name: 'blah') # get a project by name
|
56
|
+
client.projects(archived: true) # get all archived projects
|
57
|
+
client.project(id: 123).stories # get stories belonging to a project
|
58
|
+
client.story(archived: false) # get all non-archived stories
|
59
|
+
|
60
|
+
### Notes
|
61
|
+
Note that querying for stories is quicker when performed on a Project, rather than using the `client.projects` method. This is because stories are only available as children of a project, so building the global story array requires making an API call to every project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/clubhouse2/client.rb
CHANGED
@@ -15,7 +15,6 @@ module Clubhouse
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def api_request(method, *params)
|
18
|
-
puts [method, *params].join(', ')
|
19
18
|
response = HTTP.headers(content_type: 'application/json').send(method, *params)
|
20
19
|
case response.code
|
21
20
|
when 429
|
@@ -120,6 +119,5 @@ module Clubhouse
|
|
120
119
|
def create_workflow(**args); create_object(:workflow, args); end
|
121
120
|
def workflows(**args); get_objects(:workflow, args); end
|
122
121
|
def workflow(**args); get_object(:workflow, args); end
|
123
|
-
|
124
122
|
end
|
125
123
|
end
|
@@ -46,10 +46,14 @@ module Clubhouse
|
|
46
46
|
|
47
47
|
def set_properties(object)
|
48
48
|
object.each_pair do |k, v|
|
49
|
-
instance_variable_set('@' + k.to_s, v)
|
49
|
+
instance_variable_set('@' + k.to_s, value_format(k, v))
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
def value_format(key, value)
|
54
|
+
Date.iso8601(value) rescue value
|
55
|
+
end
|
56
|
+
|
53
57
|
# Empties resource cache
|
54
58
|
def flush
|
55
59
|
@client.flush(self.class)
|
data/lib/clubhouse2/workflow.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Clubhouse
|
2
2
|
class Workflow < ClubhouseResource
|
3
3
|
def self.properties
|
4
|
-
[ :created_at, :default_state_id, :description, :entity_type, :id, :name, :
|
4
|
+
[ :created_at, :default_state_id, :description, :entity_type, :id, :name, :team_id, :updated_at ]
|
5
5
|
end
|
6
6
|
|
7
7
|
def initialize(client:, object:)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clubhouse2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Denness
|
@@ -60,6 +60,7 @@ extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
62
|
- ".gitignore"
|
63
|
+
- README.md
|
63
64
|
- VERSION
|
64
65
|
- clubhouse2.gemspec
|
65
66
|
- lib/clubhouse2.rb
|
@@ -74,7 +75,6 @@ files:
|
|
74
75
|
- lib/clubhouse2/linked_file.rb
|
75
76
|
- lib/clubhouse2/member.rb
|
76
77
|
- lib/clubhouse2/milestone.rb
|
77
|
-
- lib/clubhouse2/ops-migration.rb
|
78
78
|
- lib/clubhouse2/profile.rb
|
79
79
|
- lib/clubhouse2/project.rb
|
80
80
|
- lib/clubhouse2/repository.rb
|
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'clubhouse2'
|
2
|
-
|
3
|
-
source_account = Clubhouse::Client.new(api_key: 'source_account_api_key')
|
4
|
-
target_account = Clubhouse::Client.new(api_key: 'target_account_api_key')
|
5
|
-
|
6
|
-
resolve_map = {}
|
7
|
-
|
8
|
-
# Map of workflows which don't directly relate to workflows in the other account
|
9
|
-
resolve_map[:workflow] = {
|
10
|
-
'Unscheduled' => 'Backlog',
|
11
|
-
'Ready for Deployment' => 'Awaiting UAT Deployment',
|
12
|
-
'Waiting for other team' => 'Blocked',
|
13
|
-
'Completed' => 'Done',
|
14
|
-
'Rejected' => 'Icebox'
|
15
|
-
}
|
16
|
-
|
17
|
-
# Map of members which aren't named the same in both accounts
|
18
|
-
resolve_map[:member] = {
|
19
|
-
'James' => 'James Denness',
|
20
|
-
}
|
21
|
-
|
22
|
-
# This method looks up the corresponding ID of a resource in the other account, by matching its name.
|
23
|
-
def resolve(source_client, target_client, resolve_map, type, id)
|
24
|
-
item = source_client.send(type, id: id)
|
25
|
-
if resolve_map[type]
|
26
|
-
counterpart = resolve_map[type][item.name] || item.name
|
27
|
-
else
|
28
|
-
counterpart = item.name
|
29
|
-
end
|
30
|
-
target_client.send(type, name: counterpart)&.id
|
31
|
-
end
|
32
|
-
|
33
|
-
# We need to create the empty projects before we can create epics
|
34
|
-
source_account.projects.each do |this_project|
|
35
|
-
target_account.create_project(
|
36
|
-
this_project.to_h.merge({
|
37
|
-
follower_ids: this_project.follower_ids.collect { |f| resolve(source_account, target_account, resolve_map, :member, f) }
|
38
|
-
})
|
39
|
-
) unless resolve(source_account, target_account, resolve_map, :project, this_project.id)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Create labels
|
43
|
-
source_account.labels.each do |this_label|
|
44
|
-
target_account.create_label(this_label.to_h) unless resolve(source_account, target_account, resolve_map, :label, this_label.id)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Create categories
|
48
|
-
source_account.categories.each do |this_category|
|
49
|
-
target_account.create_category(this_category.to_h) unless resolve(source_account, target_account, resolve_map, :category, this_category.id)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Create milestones
|
53
|
-
source_account.milestones.each do |this_milestone|
|
54
|
-
new_milestone = target_account.create_milestone(
|
55
|
-
this_milestone.to_h.merge({
|
56
|
-
labels: this_milestone.categories.collect { |c| resolve(source_account, target_account, resolve_map, :category, c ) }
|
57
|
-
})
|
58
|
-
) unless target_account.milestone(name: this_milestone.name)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Create epics
|
62
|
-
source_account.epics.each do |this_epic|
|
63
|
-
new_epic = target_account.create_epic(
|
64
|
-
this_epic.to_h.merge({
|
65
|
-
follower_ids: this_epic.follower_ids.collect { |f| resolve(source_account, target_account, resolve_map, :member, f) },
|
66
|
-
owner_ids: this_epic.owner_ids.collect { |o| resolve(source_account, target_account, resolve_map, :member, o) },
|
67
|
-
labels: this_epic.labels.collect { |l| resolve(source_account, target_account, resolve_map, :label, l ) },
|
68
|
-
started_at_override: this_epic.started_at,
|
69
|
-
completed_at_override: this_epic.completed_at,
|
70
|
-
milestone_id: resolve(source_account, target_account, resolve_map, :milestone, this_epic.milestone_id)
|
71
|
-
})
|
72
|
-
) unless target_account.epic(name: this_epic.name)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Fill the projects with stories
|
76
|
-
source_account.projects.each do |this_project|
|
77
|
-
target_account_project = target_account.project(id: resolve(source_account, target_account, resolve_map, :project, this_project.id))
|
78
|
-
this_project.stories.each do |this_story|
|
79
|
-
new_story = target_account.create_story(
|
80
|
-
this_story.to_h.merge({
|
81
|
-
project_id: target_account_project.id,
|
82
|
-
epic_id: (resolve(source_account, target_account, resolve_map, :epic, this_story.epic_id) if this_story.epic_id),
|
83
|
-
follower_ids: this_story.follower_ids.collect { |f| resolve(source_account, target_account, resolve_map, :member, f) },
|
84
|
-
owner_ids: this_story.owner_ids.collect { |o| resolve(source_account, target_account, resolve_map, :member, o) },
|
85
|
-
requested_by_id: resolve(source_account, target_account, resolve_map, :member, this_story.requested_by_id),
|
86
|
-
})
|
87
|
-
) unless target_account_project.story(name: this_story.name)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# Restore story links
|
92
|
-
source_account.story_links.each do |this_link|
|
93
|
-
begin
|
94
|
-
target_account.create_story_link(
|
95
|
-
this_link.to_h.merge({
|
96
|
-
object_id: resolve(source_account, target_account, resolve_map, :story, this_link.object_id),
|
97
|
-
subject_id: resolve(source_account, target_account, resolve_map, :story, this_link.subject_id)
|
98
|
-
})
|
99
|
-
) unless target_account.story_link(object_id: resolve(source_account, target_account, resolve_map, :story, this_link.object_id), subject_id: resolve(source_account, target_account, resolve_map, :story, this_link.subject_id))
|
100
|
-
rescue Clubhouse::ClubhouseAPIError => e
|
101
|
-
if e.message[/duplicated/]
|
102
|
-
next
|
103
|
-
else
|
104
|
-
raise e
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
|