jira_command 0.1.3
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +113 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +88 -0
- data/LICENSE.txt +21 -0
- data/README.md +140 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/jira_command +5 -0
- data/jira_command.gemspec +31 -0
- data/lib/jira_command.rb +7 -0
- data/lib/jira_command/cli.rb +21 -0
- data/lib/jira_command/command/assign.rb +48 -0
- data/lib/jira_command/command/config.rb +72 -0
- data/lib/jira_command/command/issue.rb +80 -0
- data/lib/jira_command/command/list.rb +70 -0
- data/lib/jira_command/command/status.rb +21 -0
- data/lib/jira_command/command/transition.rb +68 -0
- data/lib/jira_command/command/user.rb +22 -0
- data/lib/jira_command/config.rb +38 -0
- data/lib/jira_command/jira/assign.rb +32 -0
- data/lib/jira_command/jira/base.rb +26 -0
- data/lib/jira_command/jira/issue.rb +40 -0
- data/lib/jira_command/jira/issuetype.rb +19 -0
- data/lib/jira_command/jira/list.rb +23 -0
- data/lib/jira_command/jira/project.rb +19 -0
- data/lib/jira_command/jira/status.rb +30 -0
- data/lib/jira_command/jira/transition.rb +29 -0
- data/lib/jira_command/jira/user.rb +31 -0
- data/lib/jira_command/version.rb +3 -0
- metadata +95 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'jira_command'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/jira_command
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'lib/jira_command/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'jira_command'
|
5
|
+
spec.version = JiraCommand::VERSION
|
6
|
+
spec.authors = ['shengbo.xu']
|
7
|
+
spec.email = ['shengbo.xu@xincere.jp']
|
8
|
+
|
9
|
+
spec.summary = 'jira cli'
|
10
|
+
spec.description = 'jira cli tool'
|
11
|
+
spec.homepage = 'https://github.com/xincere-inc/jira_command'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
14
|
+
|
15
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/xincere-inc/jira_command'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/xincere-inc/jira_command'
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = 'exe'
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
|
30
|
+
spec.add_dependency 'thor'
|
31
|
+
end
|
data/lib/jira_command.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'jira_command'
|
2
|
+
require 'thor'
|
3
|
+
require_relative 'command/list'
|
4
|
+
require_relative 'command/config'
|
5
|
+
require_relative 'command/user'
|
6
|
+
require_relative 'command/assign'
|
7
|
+
require_relative 'command/status'
|
8
|
+
require_relative 'command/transition'
|
9
|
+
require_relative 'command/issue'
|
10
|
+
|
11
|
+
module JiraCommand
|
12
|
+
class CLI < Thor
|
13
|
+
register(JiraCommand::Command::List, 'list', 'list', 'list up issues')
|
14
|
+
register(JiraCommand::Command::Config, 'config', 'config', 'create or clear configuration')
|
15
|
+
register(JiraCommand::Command::User, 'user', 'user', 'list all users')
|
16
|
+
register(JiraCommand::Command::Assign, 'assign', 'assign', 'set or unset assign in issue')
|
17
|
+
register(JiraCommand::Command::Status, 'status', 'status', 'show all status in project')
|
18
|
+
register(JiraCommand::Command::Transition, 'transition', 'transition', 'transition issues')
|
19
|
+
register(JiraCommand::Command::Issue, 'issue', 'issue', 'create a issue')
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'optparse'
|
3
|
+
require 'tty-prompt'
|
4
|
+
require_relative '../config'
|
5
|
+
require_relative '../jira/assign'
|
6
|
+
|
7
|
+
module JiraCommand
|
8
|
+
module Command
|
9
|
+
class Assign < Thor
|
10
|
+
desc 'exec', 'assign to user'
|
11
|
+
option 'issue', aliases: 'i', required: true
|
12
|
+
option 'refresh-user', aliases: 'ru', required: false
|
13
|
+
def exec
|
14
|
+
config = JiraCommand::Config.new.read
|
15
|
+
|
16
|
+
user_api = JiraCommand::Jira::User.new(config)
|
17
|
+
user_list = user_api.all_list(project: options['issue'].split('-').first)
|
18
|
+
|
19
|
+
user_list = if options['refresh-user'].nil?
|
20
|
+
config['users']
|
21
|
+
else
|
22
|
+
user_api = JiraCommand::Jira::User.new(config)
|
23
|
+
user_api.all_list(project: project[:key])
|
24
|
+
end
|
25
|
+
|
26
|
+
prompt = TTY::Prompt.new
|
27
|
+
|
28
|
+
assignee = prompt.select('Who do you want to assign?') do |menu|
|
29
|
+
user_list.each do |user|
|
30
|
+
menu.choice name: user[:name], value: user[:account_id]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
assign = JiraCommand::Jira::Assign.new(config)
|
35
|
+
user_list = assign.execute(issue_key: options['issue'], assignee: assignee)
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'clear', 'set to unassigned'
|
39
|
+
option 'issue', aliases: 'i', required: false
|
40
|
+
def clear
|
41
|
+
config = JiraCommand::Config.new.read
|
42
|
+
|
43
|
+
assign = JiraCommand::Jira::Assign.new(config)
|
44
|
+
assign.unassigne(issue_key: options['issue'])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'jira_command'
|
2
|
+
require 'thor'
|
3
|
+
require 'optparse'
|
4
|
+
require 'tty-prompt'
|
5
|
+
require_relative '../config'
|
6
|
+
require_relative '../jira/issuetype'
|
7
|
+
require_relative '../jira/project'
|
8
|
+
require_relative '../jira/user'
|
9
|
+
require 'base64'
|
10
|
+
|
11
|
+
module JiraCommand
|
12
|
+
module Command
|
13
|
+
class Config < Thor
|
14
|
+
desc 'create', 'create config file'
|
15
|
+
def create
|
16
|
+
if JiraCommand::Config.check_exist
|
17
|
+
puts 'config file has been already existed. if you want to renew it, please execute `jira_command config clear` first'
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
prompt = TTY::Prompt.new
|
22
|
+
|
23
|
+
jira_url = prompt.ask('Please input your site url:')
|
24
|
+
email = prompt.ask('Please input your registered email address:')
|
25
|
+
token = prompt.mask('Please input your token:')
|
26
|
+
|
27
|
+
jira_url += '/' unless jira_url.end_with?('/')
|
28
|
+
config = { jira_url: jira_url, header_token: Base64.strict_encode64("#{email}:#{token}") }
|
29
|
+
|
30
|
+
JiraCommand::Config.new.write(config)
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'update_projects', 'update default projects in config file'
|
34
|
+
def update_projects
|
35
|
+
config = JiraCommand::Config.new.read
|
36
|
+
|
37
|
+
jira_project = JiraCommand::Jira::Project.new(config)
|
38
|
+
config.merge!({
|
39
|
+
projects: jira_project.list
|
40
|
+
})
|
41
|
+
JiraCommand::Config.new.write(config)
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'update_users', 'update default users in config file'
|
45
|
+
option 'project', aliases: 'p', required: true
|
46
|
+
def update_users
|
47
|
+
config = JiraCommand::Config.new.read
|
48
|
+
user_api = JiraCommand::Jira::User.new(config)
|
49
|
+
config.merge!({
|
50
|
+
users: user_api.all_list(project: options[:project])
|
51
|
+
})
|
52
|
+
JiraCommand::Config.new.write(config)
|
53
|
+
end
|
54
|
+
|
55
|
+
desc 'update_it', 'update default issue_type in config file'
|
56
|
+
def update_it
|
57
|
+
config = JiraCommand::Config.new.read
|
58
|
+
jira_issue_type = JiraCommand::Jira::IssueType.new(config)
|
59
|
+
config.merge!({
|
60
|
+
issue_types: jira_issue_type.list
|
61
|
+
})
|
62
|
+
JiraCommand::Config.new.write(config)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc 'clear', 'clear config file'
|
66
|
+
def clear
|
67
|
+
prompt = TTY::Prompt.new
|
68
|
+
JiraCommand::Config.new.clear if prompt.yes?('Are you sure to clear?')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'jira_command'
|
2
|
+
require_relative '../config'
|
3
|
+
require_relative '../jira/issuetype'
|
4
|
+
require_relative '../jira/project'
|
5
|
+
require_relative '../jira/issue'
|
6
|
+
|
7
|
+
module JiraCommand
|
8
|
+
module Command
|
9
|
+
class Issue < Thor
|
10
|
+
desc 'create', 'create new issue'
|
11
|
+
option 'refresh-project', aliases: 'rp', required: false
|
12
|
+
option 'refresh-issue-type', aliases: 'rit', required: false
|
13
|
+
option 'refresh-user', aliases: 'ru', required: false
|
14
|
+
def create
|
15
|
+
config = JiraCommand::Config.new.read
|
16
|
+
|
17
|
+
issue_types = if options['refresh-issue-type'].nil?
|
18
|
+
config['issue_types']
|
19
|
+
else
|
20
|
+
jira_issue_type = JiraCommand::Jira::IssueType.new(config)
|
21
|
+
jira_issue_type.list
|
22
|
+
end
|
23
|
+
|
24
|
+
prompt = TTY::Prompt.new
|
25
|
+
|
26
|
+
issue_type = prompt.select('Which issue type do you want to create?') do |menu|
|
27
|
+
issue_types.each do |item|
|
28
|
+
menu.choice name: item['name'], value: item['id']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
projects = if options['refresh-project'].nil?
|
33
|
+
config['projects']
|
34
|
+
else
|
35
|
+
jira_project = JiraCommand::Jira::Project.new(config)
|
36
|
+
jira_project.list
|
37
|
+
end
|
38
|
+
|
39
|
+
project = prompt.select('Which project does the issue belong to?') do |menu|
|
40
|
+
projects.each do |item|
|
41
|
+
menu.choice name: item['name'], value: { id: item['id'], key: item['key'] }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
user_list = if options['refresh-user'].nil?
|
46
|
+
config['users']
|
47
|
+
else
|
48
|
+
user_api = JiraCommand::Jira::User.new(config)
|
49
|
+
user_api.all_list(project: project[:key])
|
50
|
+
end
|
51
|
+
|
52
|
+
assignee = prompt.select('Who do you want to assign?') do |menu|
|
53
|
+
user_list.each do |user|
|
54
|
+
menu.choice name: user['name'], value: user['account_id']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
reporter = prompt.select('Who are you?') do |menu|
|
59
|
+
user_list.each do |user|
|
60
|
+
menu.choice name: user['name'], value: user['account_id']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
summary = prompt.ask('Please input issue summary: ')
|
65
|
+
description = prompt.ask('Please input issue description: ')
|
66
|
+
|
67
|
+
jira_issue = JiraCommand::Jira::Issue.new(config)
|
68
|
+
|
69
|
+
puts 'the created issue url: ' + jira_issue.create(
|
70
|
+
summary: summary,
|
71
|
+
description: description,
|
72
|
+
assignee: assignee,
|
73
|
+
reporter: reporter,
|
74
|
+
project_id: project[:id],
|
75
|
+
issuetype_id: issue_type
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'jira_command'
|
2
|
+
require 'thor'
|
3
|
+
require 'optparse'
|
4
|
+
require 'pry'
|
5
|
+
require_relative '../config'
|
6
|
+
require_relative '../jira/list'
|
7
|
+
require 'tty-prompt'
|
8
|
+
require 'base64'
|
9
|
+
require 'terminal-table'
|
10
|
+
|
11
|
+
module JiraCommand
|
12
|
+
module Command
|
13
|
+
class List < Thor
|
14
|
+
default_command :unresolved
|
15
|
+
|
16
|
+
desc 'all', 'list issues'
|
17
|
+
def all
|
18
|
+
config = JiraCommand::Config.new.read
|
19
|
+
list = JiraCommand::Jira::List.new(config)
|
20
|
+
issues_list = list.list({ fields: 'id,key,status,issuetype,assignee,summary' })
|
21
|
+
show_in_console(config['jira_url'], issues_list['issues'])
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'unresolved', 'list issues'
|
25
|
+
def unresolved
|
26
|
+
config = JiraCommand::Config.new.read
|
27
|
+
list = JiraCommand::Jira::List.new(config)
|
28
|
+
issues_list = list.list({ fields: 'id,key,status,issuetype,assignee,summary',
|
29
|
+
jql: 'status not in (resolved)' })
|
30
|
+
|
31
|
+
show_in_console(config['jira_url'], issues_list['issues'])
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'my', 'list your issues'
|
35
|
+
option 'current', aliases: 'c', required: false
|
36
|
+
option 'unresolved', aliases: 'u', required: false
|
37
|
+
def my
|
38
|
+
jql = ['assignee=currentUser()']
|
39
|
+
jql << 'sprint in openSprints()' unless options['current'].nil?
|
40
|
+
jql << 'status not in (resolved)' unless options['unresolved'].nil?
|
41
|
+
|
42
|
+
config = JiraCommand::Config.new.read
|
43
|
+
list = JiraCommand::Jira::List.new(config)
|
44
|
+
issues_list = list.list({ fields: 'id,key,status,issuetype,assignee,summary',
|
45
|
+
jql: jql.join('&') })
|
46
|
+
|
47
|
+
show_in_console(config['jira_url'], issues_list['issues'])
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def show_in_console(jira_url, issues)
|
53
|
+
issue_list = issues.map do |issue|
|
54
|
+
{ key: issue['key'],
|
55
|
+
summary: issue['fields']['summary'],
|
56
|
+
assignee: issue['fields']['assignee'].nil? ? 'not assinged' : issue['fields']['assignee']['displayName'],
|
57
|
+
type: issue['fields']['issuetype']['name'],
|
58
|
+
status: issue['fields']['status']['name'],
|
59
|
+
link: jira_url + 'browse/' + issue['key'] }
|
60
|
+
end
|
61
|
+
|
62
|
+
table = Terminal::Table.new
|
63
|
+
table.headings = issue_list.first.keys
|
64
|
+
table.rows = issue_list.sort_by { |data| "#{data['status']}-#{data['key']}-#{data['type']}" }.map(&:values)
|
65
|
+
|
66
|
+
puts table
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'optparse'
|
3
|
+
require_relative '../config'
|
4
|
+
require_relative '../jira/status'
|
5
|
+
|
6
|
+
module JiraCommand
|
7
|
+
module Command
|
8
|
+
class Status < Thor
|
9
|
+
desc 'project', 'list status in specified project'
|
10
|
+
option 'project', aliases: 'p', required: true
|
11
|
+
def project
|
12
|
+
config = JiraCommand::Config.new.read
|
13
|
+
|
14
|
+
jira = JiraCommand::Jira::Status.new(config)
|
15
|
+
res = jira.list(project: options['project'])
|
16
|
+
|
17
|
+
puts res.map(:name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'optparse'
|
3
|
+
require 'tty-prompt'
|
4
|
+
require_relative '../config'
|
5
|
+
require_relative '../jira/transition'
|
6
|
+
|
7
|
+
module JiraCommand
|
8
|
+
module Command
|
9
|
+
class Transition < Thor
|
10
|
+
default_command :exec
|
11
|
+
|
12
|
+
desc 'exec', 'transit issue status'
|
13
|
+
option 'issue', aliases: 'i', required: true
|
14
|
+
def exec
|
15
|
+
config = JiraCommand::Config.new.read
|
16
|
+
|
17
|
+
jira = JiraCommand::Jira::Transition.new(config)
|
18
|
+
res = jira.list(issue_key: options['issue'])
|
19
|
+
|
20
|
+
prompt = TTY::Prompt.new
|
21
|
+
|
22
|
+
target_transition_id = prompt.select('Which status do you want to transite?') do |menu|
|
23
|
+
res.each do |transition|
|
24
|
+
menu.choice name: transition[:name], value: transition[:id]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
jira.transite(issue_key: options['issue'], target_transition_id: target_transition_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'issue', 'transite issue status'
|
32
|
+
option 'current', aliases: 'c', required: false
|
33
|
+
option 'mine', aliases: 'm', required: false
|
34
|
+
def issue
|
35
|
+
jql = []
|
36
|
+
jql << 'sprint in openSprints()' unless options['current'].nil?
|
37
|
+
jql << 'assignee=currentUser()' unless options['mine'].nil?
|
38
|
+
|
39
|
+
config = JiraCommand::Config.new.read
|
40
|
+
|
41
|
+
list = JiraCommand::Jira::List.new(config)
|
42
|
+
issues_list = list.list({ fields: 'key,status,assignee,summary',
|
43
|
+
jql: jql.join('&') })
|
44
|
+
|
45
|
+
prompt = TTY::Prompt.new
|
46
|
+
|
47
|
+
issue_key = prompt.select('Which issue do you want to transite?') do |menu|
|
48
|
+
issues_list['issues'].map do |i|
|
49
|
+
assignee = i['fields']['assignee']
|
50
|
+
menu.choice(name: "#{assignee.nil? ? 'not assigned' : assignee['displayName']}: #{i['fields']['summary']}(#{i['fields']['status']['name']})",
|
51
|
+
value: i['key'])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
jira = JiraCommand::Jira::Transition.new(config)
|
56
|
+
res = jira.list(issue_key: issue_key)
|
57
|
+
|
58
|
+
target_transition_id = prompt.select('Which status do you want to transite?') do |menu|
|
59
|
+
res.each do |transition|
|
60
|
+
menu.choice name: transition[:name], value: transition[:id]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
jira.transite(issue_key: issue_key, target_transition_id: target_transition_id)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|