bl 0.6.3 → 0.7.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 +5 -5
- data/.travis.yml +5 -2
- data/README.md +32 -32
- data/Rakefile +4 -10
- data/bl.gemspec +5 -5
- data/etc/help.md +32 -31
- data/lib/bl.rb +16 -16
- data/lib/bl/cli.rb +25 -113
- data/lib/bl/command.rb +0 -1
- data/lib/bl/commands/category.rb +46 -0
- data/lib/bl/commands/file.rb +28 -0
- data/lib/bl/commands/gitrepo.rb +23 -0
- data/lib/bl/commands/group.rb +47 -0
- data/lib/bl/commands/issue.rb +104 -0
- data/lib/bl/commands/milestone.rb +60 -0
- data/lib/bl/commands/notification.rb +41 -0
- data/lib/bl/commands/project.rb +127 -0
- data/lib/bl/commands/pull_request.rb +23 -0
- data/lib/bl/commands/recent.rb +28 -0
- data/lib/bl/commands/space.rb +66 -0
- data/lib/bl/commands/type.rb +57 -0
- data/lib/bl/commands/user.rb +90 -0
- data/lib/bl/commands/watching.rb +67 -0
- data/lib/bl/commands/webhook.rb +52 -0
- data/lib/bl/commands/wiki.rb +79 -0
- data/lib/bl/version.rb +11 -1
- metadata +43 -43
- data/lib/bl/category.rb +0 -44
- data/lib/bl/file.rb +0 -26
- data/lib/bl/formatting.rb +0 -38
- data/lib/bl/gitrepo.rb +0 -22
- data/lib/bl/groups.rb +0 -45
- data/lib/bl/milestone.rb +0 -58
- data/lib/bl/notifications.rb +0 -38
- data/lib/bl/project.rb +0 -121
- data/lib/bl/pull_request.rb +0 -21
- data/lib/bl/recent.rb +0 -24
- data/lib/bl/space.rb +0 -61
- data/lib/bl/type.rb +0 -55
- data/lib/bl/users.rb +0 -87
- data/lib/bl/watchings.rb +0 -67
- data/lib/bl/webhooks.rb +0 -51
- data/lib/bl/wiki.rb +0 -77
data/lib/bl/command.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Category < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = "projects/#{@config[:project_key]}/categories"
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'list', 'list categories'
|
11
|
+
def list
|
12
|
+
res = request(:get, @url)
|
13
|
+
puts 'categories:'
|
14
|
+
print_response(res, :category)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'add [NAME...]', 'add categories'
|
18
|
+
def add(*names)
|
19
|
+
names.each do |name|
|
20
|
+
res = request(:post, @url, name: name)
|
21
|
+
puts 'category added'
|
22
|
+
print_response(res, :category)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'update [ID...]', 'update categories'
|
27
|
+
option :name, type: :string
|
28
|
+
def update(*ids)
|
29
|
+
ids.each do |id|
|
30
|
+
res = request(:patch, "#{@url}/#{id}", delete_class_options(options))
|
31
|
+
puts 'category updated'
|
32
|
+
print_response(res, :category)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'delete [ID...]', 'delete categories'
|
37
|
+
def delete(*ids)
|
38
|
+
ids.each do |id|
|
39
|
+
res = request(:delete, "#{@url}/#{id}")
|
40
|
+
puts 'category deleted'
|
41
|
+
print_response(res, :category)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class File < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = "projects/#{@config[:project_key]}"
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'list PATH', 'list files on PATH'
|
11
|
+
def list(path = '')
|
12
|
+
res = request(:get, "#{@url}/files/metadata/#{path}")
|
13
|
+
print_response(res, :file)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'get [ID...]', 'get files'
|
17
|
+
def get(*ids)
|
18
|
+
ids.each do |id|
|
19
|
+
res = request(:get, "#{@url}/files/#{id}")
|
20
|
+
f = ::File.new(res.body.filename, 'w')
|
21
|
+
f.write(res.body.content)
|
22
|
+
f.close
|
23
|
+
puts "file #{id} #{res.body.filename} downloaded."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class GitRepo < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = "projects/#{@config[:project_key]}/git/repositories"
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'list', 'list git repositories'
|
11
|
+
def list
|
12
|
+
res = request(:get, @url)
|
13
|
+
print_response(res, :gitrepo)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'show ID', 'show a git repository'
|
17
|
+
def show(id)
|
18
|
+
res = request(:get, "#{@url}/#{id}")
|
19
|
+
print_response(res, :gitrepo)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Group < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = 'groups'
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'list', 'list groups'
|
11
|
+
options order: :string, offset: :numeric, count: :numeric
|
12
|
+
def list
|
13
|
+
res = request(:get, @url, options.to_h)
|
14
|
+
puts formatter.render(res.body, fields: %i(id name))
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'show GROUP_ID', 'show group'
|
18
|
+
def show(id)
|
19
|
+
res = request(:get, "#{@url}/#{id}")
|
20
|
+
puts formatter.render(res.body.members, fields: USER_FIELDS)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'add GROUP_NAME', 'add group'
|
24
|
+
options members: :array
|
25
|
+
def add(name)
|
26
|
+
res = request(:post, @url, { name: name }.merge(delete_class_options(options)))
|
27
|
+
puts 'group added'
|
28
|
+
print_group_and_members(res.body)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'update GROUP_ID', 'update group'
|
32
|
+
options name: :string, members: :array
|
33
|
+
def update(id)
|
34
|
+
res = request(:patch, "#{@url}/#{id}", delete_class_options(options.to_h))
|
35
|
+
puts 'group updated'
|
36
|
+
print_group_and_members(res.body)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'delete GROUP_ID', 'delete group'
|
40
|
+
def delete(id)
|
41
|
+
res = request(:delete, "#{@url}/#{id}")
|
42
|
+
puts 'group deleted'
|
43
|
+
print_group_and_members(res.body)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Issue < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = 'issues'
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'add [SUBJECT...]', 'add issues'
|
11
|
+
options ISSUE_BASE_ATTRIBUTES
|
12
|
+
def add(*subjects)
|
13
|
+
subjects.each do |s|
|
14
|
+
issue_default_options = @config[:issue][:default]
|
15
|
+
res = request(:post,
|
16
|
+
'issues',
|
17
|
+
issue_default_options.merge({summary: s}).merge(delete_class_options(options.to_h))
|
18
|
+
)
|
19
|
+
puts '💡 issue added'
|
20
|
+
print_response(res, :issue)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'close [KEY...]', 'close issues'
|
25
|
+
def close(*keys)
|
26
|
+
keys.each do |k|
|
27
|
+
res = request(:patch, "issues/#{k}", statusId: 4)
|
28
|
+
puts '🎉 issue closed'
|
29
|
+
print_response(res, :issue)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'count', 'count issues'
|
34
|
+
options ISSUES_PARAMS
|
35
|
+
def count
|
36
|
+
puts request(:get, 'issues/count', delete_class_options(options.to_h)).body.count
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'edit KEY', "edit issues' description by $EDITOR"
|
40
|
+
def edit(key)
|
41
|
+
issue_description = request(:get, "issues/#{key}").body.description
|
42
|
+
file = Tempfile.new
|
43
|
+
file.puts(issue_description)
|
44
|
+
file.close
|
45
|
+
begin
|
46
|
+
file.open
|
47
|
+
system("$EDITOR #{file.path}")
|
48
|
+
new_content = file.read
|
49
|
+
request(:patch, "issues/#{key}", description: new_content)
|
50
|
+
puts "issue #{key} updated."
|
51
|
+
ensure
|
52
|
+
file.close
|
53
|
+
file.unlink
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc 'list', 'list issues by typical ways'
|
58
|
+
option :all
|
59
|
+
option :unassigned
|
60
|
+
option :today
|
61
|
+
option :overdue
|
62
|
+
option :priority
|
63
|
+
option :nocategory
|
64
|
+
def list
|
65
|
+
opts = {}
|
66
|
+
opts[:statusId] = [1, 2, 3] unless options[:all]
|
67
|
+
opts[:assigneeId] = [-1] if options[:unassigned]
|
68
|
+
if options[:today]
|
69
|
+
today = Date.today
|
70
|
+
opts[:dueDateSince] = today.to_s
|
71
|
+
opts[:dueDateUntil] = today.next.to_s
|
72
|
+
end
|
73
|
+
opts[:dueDateUntil] = Date.today.to_s if options[:overdue]
|
74
|
+
if options[:priority]
|
75
|
+
opts[:sort] = 'priority'
|
76
|
+
opts[:order] = 'asc'
|
77
|
+
end
|
78
|
+
opts[:categoryId] = [-1] if options[:nocategory]
|
79
|
+
opts[:count] = ISSUES_COUNT_MAX
|
80
|
+
res = request(:get, 'issues', opts)
|
81
|
+
print_response(res, :issue)
|
82
|
+
end
|
83
|
+
|
84
|
+
desc 'update [KEY...]', 'update issues'
|
85
|
+
options ISSUE_BASE_ATTRIBUTES
|
86
|
+
option :comment, type: :string
|
87
|
+
def update(*keys)
|
88
|
+
keys.each do |k|
|
89
|
+
res = request(:patch, "issues/#{k}", delete_class_options(options.to_h))
|
90
|
+
puts 'issue updated'
|
91
|
+
print_response(res, :issue)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
desc 'search', 'search issues'
|
96
|
+
options ISSUES_PARAMS
|
97
|
+
def search
|
98
|
+
res = request(:get, 'issues', delete_class_options(options.to_h))
|
99
|
+
print_response(res, :issue)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Milestone < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = "projects/#{@config[:project_key]}/versions"
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'list', 'list milestones'
|
11
|
+
option :all
|
12
|
+
def list
|
13
|
+
res = request(:get, @url)
|
14
|
+
if options[:all]
|
15
|
+
else
|
16
|
+
res.body.select! { |m| m.archived == false } unless options[:all]
|
17
|
+
end
|
18
|
+
puts 'milestones:'
|
19
|
+
print_response(res, :milestone)
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'add [NAME...]', 'add milestones'
|
23
|
+
options MILESTONE_PARAMS
|
24
|
+
def add(*names)
|
25
|
+
names.each do |name|
|
26
|
+
res = request(
|
27
|
+
:post,
|
28
|
+
@url,
|
29
|
+
name: name,
|
30
|
+
description: options[:description],
|
31
|
+
startDate: options[:startDate],
|
32
|
+
releaseDueDate: options[:releaseDueDate]
|
33
|
+
)
|
34
|
+
puts 'milestone added'
|
35
|
+
print_response(res, :milestone)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'update [ID...]', 'update milestones'
|
40
|
+
option :name, type: :string
|
41
|
+
options MILESTONE_PARAMS
|
42
|
+
def update(*ids)
|
43
|
+
ids.each do |id|
|
44
|
+
res = request(:patch, "#{@url}/#{id}", delete_class_options(options))
|
45
|
+
puts 'milestone updated'
|
46
|
+
print_response(res, milestone)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'delete [ID...]', 'delete milestones'
|
51
|
+
def delete(*ids)
|
52
|
+
ids.each do |id|
|
53
|
+
res = request(:delete, "#{@url}/#{id}")
|
54
|
+
puts 'milestone deleted'
|
55
|
+
print_response(res, :milestone)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Notification < Command
|
4
|
+
# TODO:
|
5
|
+
|
6
|
+
def initialize(*)
|
7
|
+
@config = Bl::Config.instance
|
8
|
+
@url = 'notifications'
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'list', ''
|
13
|
+
options minId: :numeric, maxId: :numeric, count: :numeric, order: :string
|
14
|
+
def list
|
15
|
+
res = request(:get, @url, options.to_h)
|
16
|
+
res.body.map { |n| puts n.pretty_inspect }
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'count', ''
|
20
|
+
options alreadyRead: :boolean, resourceAlreadyRead: :boolean
|
21
|
+
def count
|
22
|
+
# puts request(:get, "#{@url}/count").body.count
|
23
|
+
# TODO fix nil error
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'mark-as-read', ''
|
27
|
+
def mark_as_read
|
28
|
+
res = request(:post, "#{@url}/markAsRead")
|
29
|
+
puts 'notifications mark as readed'
|
30
|
+
puts res.body.count
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'read NOTIFICATIONS_ID', ''
|
34
|
+
def read(id)
|
35
|
+
res = request(:post, "#{@url}/#{id}/markAsRead")
|
36
|
+
puts "notifications #{id} readed"
|
37
|
+
puts res.pretty_inspect
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Bl
|
2
|
+
module Commands
|
3
|
+
class Project < Command
|
4
|
+
def initialize(*)
|
5
|
+
@config = Bl::Config.instance
|
6
|
+
@url = 'projects'
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
# TODO:
|
11
|
+
# desc 'activities ID', 'show project activities'
|
12
|
+
# def activities(id)
|
13
|
+
# res = request(:get, "#{@url}/#{id}/activities")
|
14
|
+
# res.body.each do |a|
|
15
|
+
# p a.pretty_inspect
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
|
19
|
+
desc 'list', 'list projects'
|
20
|
+
option :all
|
21
|
+
def list
|
22
|
+
opts = {}
|
23
|
+
opts[:archived] = false unless options[:all]
|
24
|
+
res = request(:get, @url, opts)
|
25
|
+
print_response(res, :project)
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'show', 'show project'
|
29
|
+
def show(id)
|
30
|
+
res = request(:get, "#{@url}/#{id}")
|
31
|
+
print_response(res, :project)
|
32
|
+
rescue => e
|
33
|
+
puts e.message
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'add', 'add project'
|
37
|
+
option :key, required: true, type: :string
|
38
|
+
option :chartEnabled, type: :boolean, default: false
|
39
|
+
option :projectLeaderCanEditProjectLeader, type: :boolean, default: false
|
40
|
+
option :subtaskingEnabled, type: :boolean, default: false
|
41
|
+
option :textFormattingRule, type: :string, default: 'markdown'
|
42
|
+
def add(name)
|
43
|
+
res = request(:post, @url, {name: name}.merge(delete_class_options(options.to_h)))
|
44
|
+
puts 'project added'
|
45
|
+
print_response(res, :project)
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'update', 'update project'
|
49
|
+
options PROJECT_PARAMS
|
50
|
+
def update(id)
|
51
|
+
res = request(:patch, "#{@url}/#{id}", delete_class_options(options.to_h))
|
52
|
+
puts 'project updated'
|
53
|
+
print_response(res, :project)
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'delete', 'delete project'
|
57
|
+
def delete(id)
|
58
|
+
res = request(:delete, "#{@url}/#{id}")
|
59
|
+
puts 'project deleted'
|
60
|
+
print_response(res, :project)
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'status ID', 'show project status'
|
64
|
+
def status(id)
|
65
|
+
all_issues_count = count_issues(id)
|
66
|
+
open_issues_count = count_issues(id, statusId: [1])
|
67
|
+
in_progress_issues_count = count_issues(id, statusId: [2])
|
68
|
+
resolved_issues_count = count_issues(id, statusId: [3])
|
69
|
+
closed_issues_count = count_issues(id, statusId: [4])
|
70
|
+
puts "#{closed_issues_count} / #{all_issues_count}"
|
71
|
+
puts "open: #{open_issues_count}"
|
72
|
+
puts "in progress: #{in_progress_issues_count}"
|
73
|
+
puts "resolved: #{resolved_issues_count}"
|
74
|
+
puts "closed: #{closed_issues_count}"
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'progress ID', 'show project progress'
|
78
|
+
def progress(id)
|
79
|
+
puts '--status--'
|
80
|
+
all_issues_count = count_issues(id)
|
81
|
+
closed_issues_count = count_issues(id, statusId: [4])
|
82
|
+
puts "#{closed_issues_count} / #{all_issues_count}"
|
83
|
+
puts '--milestone--'
|
84
|
+
versions = request(:get, "projects/#{@config[:project_key]}/versions").body
|
85
|
+
versions.each do |version|
|
86
|
+
all_issues_count = count_issues(id, milestoneId: [version.id])
|
87
|
+
closed_issues_count = count_issues(id, milestoneId: [version.id], statusId: [4])
|
88
|
+
puts "#{version.name}: #{closed_issues_count} / #{all_issues_count}"
|
89
|
+
end
|
90
|
+
puts '--category--'
|
91
|
+
categories = request(:get, "projects/#{@config[:project_key]}/categories").body
|
92
|
+
categories.each do |category|
|
93
|
+
all_issues_count = count_issues(id, categoryId: [category.id])
|
94
|
+
closed_issues_count = count_issues(id, categoryId: [category.id], statusId: [4])
|
95
|
+
puts "#{category.name}: #{closed_issues_count} / #{all_issues_count}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
desc 'users ID', 'show project users'
|
100
|
+
def users(id)
|
101
|
+
res = request(:get, "#{@url}/#{id}/users")
|
102
|
+
puts formatter.render(res.body, fields: USER_FIELDS)
|
103
|
+
end
|
104
|
+
|
105
|
+
desc 'image ID', 'get project image file'
|
106
|
+
def image(id)
|
107
|
+
res = request(:get, "#{@url}/#{id}/image")
|
108
|
+
::File.open(res.body.filename, 'wb') { |f| f.write(res.body.content) }
|
109
|
+
puts "#{res.body.filename} generated"
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def count_issues(project_id, args={})
|
115
|
+
args = {
|
116
|
+
projectId: [project_id],
|
117
|
+
}.merge(args)
|
118
|
+
request(
|
119
|
+
:get,
|
120
|
+
'issues/count',
|
121
|
+
args
|
122
|
+
).body.count
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|