jira-cli 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -28
- data/bin/jira +3 -1
- data/lib/jira.rb +12 -6
- data/lib/jira/api.rb +10 -5
- data/lib/jira/auth_api.rb +11 -0
- data/lib/jira/command.rb +21 -1
- data/lib/jira/commands/all.rb +2 -2
- data/lib/jira/commands/assign.rb +2 -2
- data/lib/jira/commands/comment.rb +8 -98
- data/lib/jira/commands/comment/add.rb +46 -0
- data/lib/jira/commands/comment/delete.rb +80 -0
- data/lib/jira/commands/comment/list.rb +69 -0
- data/lib/jira/commands/comment/update.rb +88 -0
- data/lib/jira/commands/delete.rb +0 -2
- data/lib/jira/commands/describe.rb +0 -2
- data/lib/jira/commands/install.rb +39 -17
- data/lib/jira/commands/link.rb +4 -3
- data/lib/jira/commands/log.rb +7 -72
- data/lib/jira/commands/log/add.rb +50 -0
- data/lib/jira/commands/log/delete.rb +80 -0
- data/lib/jira/commands/log/list.rb +69 -0
- data/lib/jira/commands/log/update.rb +89 -0
- data/lib/jira/commands/new.rb +4 -6
- data/lib/jira/commands/rename.rb +0 -2
- data/lib/jira/commands/sprint.rb +3 -3
- data/lib/jira/commands/tickets.rb +0 -2
- data/lib/jira/commands/transition.rb +0 -2
- data/lib/jira/commands/vote.rb +5 -107
- data/lib/jira/commands/vote/add.rb +43 -0
- data/lib/jira/commands/vote/delete.rb +46 -0
- data/lib/jira/commands/vote/list.rb +59 -0
- data/lib/jira/commands/watch.rb +5 -108
- data/lib/jira/commands/watch/add.rb +43 -0
- data/lib/jira/commands/watch/delete.rb +46 -0
- data/lib/jira/commands/watch/list.rb +59 -0
- data/lib/jira/constants.rb +1 -1
- data/lib/jira/core.rb +9 -1
- data/lib/jira/sprint_api.rb +2 -18
- metadata +17 -5
- data/lib/jira/commands/commit.rb +0 -14
- data/lib/jira/legacy_api.rb +0 -102
- data/lib/jira/mixins.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90eee20531277d150c8a465d36bd465f87aadc09
|
4
|
+
data.tar.gz: 40144b5a1cb60ff669124475a6a651fa45b6691a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74fad1cbbdc11727a57c82fa39e3184eb7d80a5b199aac67eabbc9fe14acc510412f3b30a83ad805abd89ea30dc19eddd3517195a43829bfd400ff10d04f01f4
|
7
|
+
data.tar.gz: fb6e29c2710f0b74bb3000cb767799aff6f0bc82c5bb9199ed9cad29a91acb7646f0ab7eb1c59f543bc2dcfe7da546853f103dd47a49d9d40dd3abb18528df71
|
data/README.md
CHANGED
@@ -10,34 +10,24 @@ Ruby gem CLI tool used to manage JIRA workflows leveraging git
|
|
10
10
|
|
11
11
|
### Available Commands
|
12
12
|
|
13
|
-
jira all
|
14
|
-
jira assign
|
15
|
-
jira attachments
|
16
|
-
jira comment
|
17
|
-
jira
|
18
|
-
jira
|
19
|
-
jira
|
20
|
-
jira
|
21
|
-
jira
|
22
|
-
jira
|
23
|
-
jira
|
24
|
-
jira
|
25
|
-
jira
|
26
|
-
jira
|
27
|
-
jira
|
28
|
-
jira
|
29
|
-
jira
|
30
|
-
jira
|
31
|
-
jira tickets # List the tickets of the input username
|
32
|
-
jira transition # Transitions the input ticket to the next state
|
33
|
-
jira unvote # Unvote against the input ticket
|
34
|
-
jira unwatch # Unwatch against the input ticket
|
35
|
-
jira version # Displays the version
|
36
|
-
jira vote # Vote against the input ticket
|
37
|
-
jira votes # List the votes of the input ticket
|
38
|
-
jira watch # Watch against the input ticket
|
39
|
-
jira watchers # List the watchers of the input ticket
|
40
|
-
jira help [COMMAND] # Describe available commands or one specific command
|
13
|
+
jira all # Describes all local branches that match JIRA ticketing syntax
|
14
|
+
jira assign # Assign a ticket to a user
|
15
|
+
jira attachments # View ticket attachments
|
16
|
+
jira comment <command> # Commands for comment operations in JIRA
|
17
|
+
jira delete # Deletes a ticket in JIRA and the git branch
|
18
|
+
jira describe # Describes the input ticket
|
19
|
+
jira help [COMMAND] # Describe available commands or one specific command
|
20
|
+
jira install # Guides the user through JIRA CLI installation
|
21
|
+
jira link # Creates a link between two tickets in JIRA
|
22
|
+
jira log <command> # Commands for logging operations in JIRA
|
23
|
+
jira new # Creates a new ticket in JIRA and checks out the git branch
|
24
|
+
jira rename # Updates the summary of the input ticket
|
25
|
+
jira sprint # Lists sprint info
|
26
|
+
jira tickets # List the tickets of the input username
|
27
|
+
jira transition # Transitions the input ticket to the next state
|
28
|
+
jira version # Displays the version
|
29
|
+
jira vote <command> # Commands for voting operations in JIRA
|
30
|
+
jira watch <command> # Commands for watching tickets in JIRA
|
41
31
|
|
42
32
|
### Gem Installation
|
43
33
|
|
data/bin/jira
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
require 'jira'
|
4
4
|
begin
|
5
5
|
Jira::CLI.start
|
6
|
+
rescue Faraday::Error
|
7
|
+
puts "JIRA failed connect, you may need to rerun 'jira install'"
|
6
8
|
rescue GitException
|
7
9
|
puts "JIRA commands can only be run within a git repository."
|
8
10
|
rescue InstallationException
|
9
11
|
puts "Please run #{Jira::Format.summary('jira install')} before "\
|
10
|
-
|
12
|
+
"running this command."
|
11
13
|
rescue Interrupt
|
12
14
|
end
|
data/lib/jira.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
# dependencies
|
1
|
+
# external dependencies
|
2
2
|
require 'thor'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
require 'tty-table'
|
4
|
+
require 'inifile'
|
5
|
+
require 'tty-prompt'
|
6
|
+
require 'json'
|
7
|
+
require 'faraday'
|
8
|
+
require 'faraday_middleware'
|
9
|
+
# internal dependencies
|
10
|
+
require 'jira/exceptions'
|
11
|
+
require 'jira/constants'
|
12
|
+
require 'jira/command'
|
13
|
+
require 'jira/format'
|
8
14
|
|
9
15
|
module Jira
|
10
16
|
class CLI < Thor
|
data/lib/jira/api.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'faraday_middleware'
|
3
|
-
|
4
1
|
module Jira
|
5
2
|
class API
|
6
3
|
|
@@ -24,7 +21,7 @@ module Jira
|
|
24
21
|
process(response, options)
|
25
22
|
end
|
26
23
|
|
27
|
-
|
24
|
+
protected
|
28
25
|
|
29
26
|
def process(response, options)
|
30
27
|
json = response.body || {}
|
@@ -62,7 +59,15 @@ module Jira
|
|
62
59
|
end
|
63
60
|
|
64
61
|
def headers
|
65
|
-
{ 'Content-Type' => 'application/json' }
|
62
|
+
{ 'Content-Type' => 'application/json' }.merge(cookies)
|
63
|
+
end
|
64
|
+
|
65
|
+
def cookies
|
66
|
+
cookie = Jira::Core.cookie
|
67
|
+
unless cookie.empty?
|
68
|
+
return { 'cookie' => "#{cookie[:name]}=#{cookie[:value]}" }
|
69
|
+
end
|
70
|
+
{}
|
66
71
|
end
|
67
72
|
|
68
73
|
end
|
data/lib/jira/command.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
# internal dependencies
|
2
|
+
require 'jira/api'
|
3
|
+
require 'jira/sprint_api'
|
4
|
+
require 'jira/auth_api'
|
5
|
+
require 'jira/core'
|
2
6
|
|
3
7
|
module Jira
|
4
8
|
module Command
|
@@ -14,6 +18,18 @@ module Jira
|
|
14
18
|
@api ||= Jira::API.new
|
15
19
|
end
|
16
20
|
|
21
|
+
def auth_api
|
22
|
+
@auth_api ||= Jira::AuthAPI.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def body
|
26
|
+
@body ||= (
|
27
|
+
comment = io.ask("Leave a comment for ticket #{ticket}:").strip
|
28
|
+
comment = comment.gsub(/\@[a-zA-Z]+/,'[~\0]') || comment
|
29
|
+
comment.gsub('[~@','[~') || comment
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
17
33
|
def sprint_api
|
18
34
|
@sprint_api ||= Jira::SprintAPI.new
|
19
35
|
end
|
@@ -34,3 +50,7 @@ module Jira
|
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|
53
|
+
|
54
|
+
# load commands
|
55
|
+
commands_directory = File.join(File.dirname(__FILE__), 'commands', '*.rb')
|
56
|
+
Dir[commands_directory].each { |file| require file }
|
data/lib/jira/commands/all.rb
CHANGED
@@ -28,8 +28,8 @@ module Jira
|
|
28
28
|
json['issues'].map do |issue|
|
29
29
|
[
|
30
30
|
issue['key'],
|
31
|
-
issue['fields']['assignee']['name'],
|
32
|
-
issue['fields']['status']['name'],
|
31
|
+
issue['fields']['assignee']['name'] || 'Unassigned',
|
32
|
+
issue['fields']['status']['name'] || 'Unknown',
|
33
33
|
truncate(issue['fields']['summary'], 45)
|
34
34
|
]
|
35
35
|
end
|
data/lib/jira/commands/assign.rb
CHANGED
@@ -1,104 +1,14 @@
|
|
1
|
+
require 'jira/commands/comment/add'
|
2
|
+
require 'jira/commands/comment/delete'
|
3
|
+
require 'jira/commands/comment/list'
|
4
|
+
require 'jira/commands/comment/update'
|
5
|
+
|
1
6
|
module Jira
|
2
7
|
class CLI < Thor
|
3
8
|
|
4
|
-
desc
|
5
|
-
|
6
|
-
comment = self.get_comment_body(ticket)
|
7
|
-
puts "No comment posted." and return if comment.empty?
|
8
|
-
|
9
|
-
self.api.post("issue/#{ticket}/comment", { body: comment }) do |json|
|
10
|
-
puts "Successfully posted your comment."
|
11
|
-
return
|
12
|
-
end
|
13
|
-
puts "No comment posted."
|
14
|
-
end
|
15
|
-
|
16
|
-
desc "commentd", "Delete a comment to the input ticket"
|
17
|
-
def commentd(ticket=Jira::Core.ticket)
|
18
|
-
self.comment_delete(ticket)
|
19
|
-
end
|
20
|
-
|
21
|
-
desc "comments", "Lists the comments of the input ticket"
|
22
|
-
def comments(ticket=Jira::Core.ticket)
|
23
|
-
self.api.get("issue/#{ticket}") do |json|
|
24
|
-
comments = json['fields']['comment']['comments']
|
25
|
-
if comments.count > 0
|
26
|
-
comments.each do |comment|
|
27
|
-
author = comment['author']['displayName']
|
28
|
-
time = Time.parse(comment['updated'])
|
29
|
-
body = comment['body']
|
30
|
-
|
31
|
-
printf "[%2d]", comments.index(comment)
|
32
|
-
puts " #{Jira::Format.user(author)} @ "\
|
33
|
-
"#{Jira::Format.time(time)}:\n"\
|
34
|
-
"#{Jira::Format.comment(body)}"
|
35
|
-
end
|
36
|
-
else
|
37
|
-
puts "There are no comments on ticket #{ticket}."
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
desc "commentu", "Update a comment to the input ticket"
|
43
|
-
def commentu(ticket=Jira::Core.ticket)
|
44
|
-
self.comment_update(ticket)
|
45
|
-
end
|
46
|
-
|
47
|
-
protected
|
48
|
-
|
49
|
-
def comment_delete(ticket)
|
50
|
-
comments(ticket) if self.io.yes?("List comments for ticket #{ticket}?")
|
51
|
-
|
52
|
-
index = self.get_type_of_index("comment", "delete")
|
53
|
-
puts "No comment deleted." and return if index < 0
|
54
|
-
|
55
|
-
self.api.get("issue/#{ticket}") do |json|
|
56
|
-
comments = json['fields']['comment']['comments']
|
57
|
-
if index < comments.count
|
58
|
-
id = comments[index]['id']
|
59
|
-
self.api.delete("issue/#{ticket}/comment/#{id}") do |json|
|
60
|
-
puts "Successfully deleted your comment."
|
61
|
-
return
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
puts "No comment deleted."
|
66
|
-
end
|
67
|
-
|
68
|
-
def comment_update(ticket)
|
69
|
-
comments(ticket) if self.io.yes?("List comments for ticket #{ticket}?")
|
70
|
-
|
71
|
-
index = self.get_type_of_index("comment", "update")
|
72
|
-
puts "No comment updated." and return if index < 0
|
73
|
-
|
74
|
-
comment = self.get_comment_body(ticket)
|
75
|
-
puts "No comment updated." and return if comment.empty?
|
76
|
-
|
77
|
-
self.api.get("issue/#{ticket}") do |json|
|
78
|
-
comments = json['fields']['comment']['comments']
|
79
|
-
id = comments[index]['id']
|
80
|
-
self.api.put("issue/#{ticket}/comment/#{id}", { body: comment }) do |json|
|
81
|
-
puts "Successfully updated your comment."
|
82
|
-
return
|
83
|
-
end
|
84
|
-
end
|
85
|
-
puts "No comment updated."
|
86
|
-
end
|
87
|
-
|
88
|
-
#
|
89
|
-
# Prompts the user for a comment body, strips it, then
|
90
|
-
# returns a substituted version of it
|
91
|
-
#
|
92
|
-
# @return comment [String] asked comment body
|
93
|
-
#
|
94
|
-
def get_comment_body(ticket)
|
95
|
-
comment = self.io.ask("Leave a comment for ticket #{ticket}:").strip
|
96
|
-
temp = comment.gsub(/\@[a-zA-Z]+/,'[~\0]')
|
97
|
-
temp = comment if temp.nil?
|
98
|
-
temp = temp.gsub('[~@','[~')
|
99
|
-
comment = temp if !temp.nil?
|
100
|
-
comment
|
101
|
-
end
|
9
|
+
desc 'comment <command>', 'Commands for comment operations in JIRA'
|
10
|
+
subcommand 'comment', Comment
|
102
11
|
|
103
12
|
end
|
13
|
+
|
104
14
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Jira
|
2
|
+
class Comment < Thor
|
3
|
+
|
4
|
+
desc 'add', 'Add a comment to the input ticket'
|
5
|
+
def add(ticket=Jira::Core.ticket)
|
6
|
+
Command::Comment::Add.new(ticket).run
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module Command
|
12
|
+
module Comment
|
13
|
+
class Add < Base
|
14
|
+
|
15
|
+
attr_accessor :ticket
|
16
|
+
|
17
|
+
def initialize(ticket)
|
18
|
+
self.ticket = ticket
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
return if body.empty?
|
23
|
+
api.post "issue/#{ticket}/comment",
|
24
|
+
params: params,
|
25
|
+
success: on_success,
|
26
|
+
failure: on_failure
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def params
|
32
|
+
{ body: body }
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_success
|
36
|
+
->{ puts "Successfully posted your comment." }
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_failure
|
40
|
+
->{ puts "No comment posted." }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Jira
|
2
|
+
class Comment < Thor
|
3
|
+
|
4
|
+
desc 'delete', 'Delete a comment to the input ticket'
|
5
|
+
def delete(ticket=Jira::Core.ticket)
|
6
|
+
Command::Comment::Delete.new(ticket).run
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module Command
|
12
|
+
module Comment
|
13
|
+
class Delete < Base
|
14
|
+
|
15
|
+
attr_accessor :ticket
|
16
|
+
|
17
|
+
def initialize(ticket)
|
18
|
+
self.ticket = ticket
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
return unless comments?
|
23
|
+
api.delete endpoint,
|
24
|
+
success: on_success,
|
25
|
+
failure: on_failure
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def comments?
|
31
|
+
if json.empty?
|
32
|
+
puts "Ticket #{ticket} has no comments."
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def endpoint
|
39
|
+
"issue/#{ticket}/comment/#{to_delete['id']}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_success
|
43
|
+
->{ puts "Successfully deleted comment from #{to_delete['updateAuthor']['displayName']}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_failure
|
47
|
+
->{ puts "No comment deleted." }
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_delete
|
51
|
+
@to_delete ||= comments[
|
52
|
+
io.select("Select a comment to delete:", comments.keys)
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
def comments
|
57
|
+
@comments ||= (
|
58
|
+
comments = {}
|
59
|
+
json.each do |comment|
|
60
|
+
comments[description_for(comment)] = comment
|
61
|
+
end
|
62
|
+
comments
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def description_for(comment)
|
67
|
+
author = comment['updateAuthor']['displayName']
|
68
|
+
updated_at = Jira::Format.time(Time.parse(comment['updated']))
|
69
|
+
body = comment['body'].gsub("\r\n|\r|\n", ";")
|
70
|
+
truncate("#{author} @ #{updated_at}: #{body}", 160)
|
71
|
+
end
|
72
|
+
|
73
|
+
def json
|
74
|
+
@json ||= api.get("issue/#{ticket}/comment")['comments']
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|