terjira 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1daef227221455846fa59674d6cfeb9735d1e33d
4
- data.tar.gz: 5dd7bbe7f90499eaf61ff4300ae5518f1a3336b3
3
+ metadata.gz: 77476a02726804785494a7f8fb656fd3693414aa
4
+ data.tar.gz: b82d22e41c646033ce9123784055ce330adadfce
5
5
  SHA512:
6
- metadata.gz: 6124824ac122ea72b0e7077956371b6803cd848a8a454bbb03c4e25de2a8e99902e64a5fd01763925b1cecfa9ac7e04457749c7b56ddd2c530d178bbdfd025f8
7
- data.tar.gz: 4ecc886b8ab99b2bc3ddfb9f9694f6baba32f5b63484f9468ac9dd6368e5428108e4cedfb74e291024f1ce8e9a0326e6a237d79284c912f4828441836358f8b2
6
+ metadata.gz: 57c3cc8b7df5b492832613b0e78ff8e6c9b4fac73ec57005487e2bb33f8a59920aec75b65edf3cd2a457075c19a6e1db1fafd649a5865697350a005b6e440215
7
+ data.tar.gz: 48b8f7be412ffca233e1eeefec4c125c363fc15bfef404ede54815801760ad419b43398d84ec324b150fd35a398beeb93dd32c10007b85b632e1485cfe0b005c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- terjira (0.1.1)
4
+ terjira (0.2.0)
5
5
  activesupport (= 4.0.13)
6
6
  jira-ruby (~> 1.1)
7
7
  pastel (~> 0.6.1)
data/README.md CHANGED
@@ -5,12 +5,14 @@
5
5
 
6
6
  # Terjira
7
7
 
8
- Terjira is interactive and easy to use command line interface (or Application) for Jira. You do not need to remember reosurce key or id. Terjira suggests with interactive prompt.
8
+ Terjira is an interactive and easy to use command line interface (or Application) for Jira. You do not need to remember resource key or id. Terjira suggests it with interactive prompt.
9
9
 
10
10
  Your Jira must support Rest API 2.0 and Agile Rest API 1.0
11
11
 
12
+ ## Domo
13
+ [Watch Demo](https://www.youtube.com/watch?v=T0hbhaXtH-Y)
12
14
 
13
- **I'm working now..**
15
+ [![Sample](./sample.png)](https://www.youtube.com/watch?v=T0hbhaXtH-Y)
14
16
 
15
17
  ## Installation
16
18
 
@@ -28,8 +30,50 @@ If you have permission problem,
28
30
  # You need to export your gem path
29
31
 
30
32
  ## Usage
31
-
32
-
33
+ ```
34
+ Authentication:
35
+ jira login # Login your Jira
36
+ jira logout # Logout your Jira
37
+
38
+ Project:
39
+ jira project help [COMMAND] # Describe one specific subcommand
40
+ jira project ( ls | list ) # List of all projects
41
+ jira project [PROJECT_KEY] # Show detail of the project
42
+
43
+ Board:
44
+ jira board help [COMMAND] # Describe one specific subcommand
45
+ jira board ( ls | list) # List of all boards
46
+ jira board backlog # Backlog from the board
47
+
48
+
49
+ Sprint:
50
+ jira sprint help [COMMAND] # Describe one specific subcommand
51
+ jira sprint ( ls | list ) # List of all sprint from the board
52
+ jira sprint [SPRINT_ID] # Show the sprint
53
+ jira sprint active # Show active sprints and issues
54
+
55
+ Issue:
56
+ jira issue help [COMMAND] # Describe one specific subcommand
57
+ jira issue ( ls | list ) # List of issues
58
+ jira issue [ISSUE_KEY] # Show detail of the issue
59
+ jira issue assign [ISSUE_KEY] ([ASSIGNEE]) # Assign the issue to user
60
+ jira issue comment # Write comment on the issue
61
+ jira issue delete # Delete the issue
62
+ jira issue edit # Edit the issue
63
+ jira issue new # Create an issue
64
+ jira issue open [ISSUE_KEY] # Open browser
65
+ jira issue take [ISSUE_KEY] # Assign the issue to self
66
+ jira issue trans [ISSUE_KEY] ([STATUS]) # Do transition
67
+
68
+ ```
69
+
70
+ ## Todo
71
+ **Contributions are welcome!**
72
+ - [ ] Manage worklog and estimate of issues
73
+ - [ ] Manage component and version of issues
74
+ - [ ] Track history of transitions
75
+ - [ ] More friendly help
76
+ - [ ] Improve test coverage
33
77
 
34
78
  ## Development
35
79
 
data/bin/jira CHANGED
@@ -14,8 +14,8 @@ rescue JIRA::HTTPError => e
14
14
  pastel = Pastel.new
15
15
  if message['errorMessages'].present?
16
16
  puts pastel.red(message['errorMessages'].join("\n"))
17
- else
18
- puts pastel.red(e.message.to_s + "\n" + e.response.body)
17
+ elsif message['errors'].present?
18
+ puts pastel.red(message['errors'].map { |k, v| "#{k}: #{v}" }.join(", "))
19
19
  end
20
20
  rescue => e
21
21
  puts Pastel.new.dim(e.message)
data/bin/terjira CHANGED
@@ -14,8 +14,8 @@ rescue JIRA::HTTPError => e
14
14
  pastel = Pastel.new
15
15
  if message['errorMessages'].present?
16
16
  puts pastel.red(message['errorMessages'].join("\n"))
17
- else
18
- puts pastel.red(e.message.to_s + "\n" + e.response.body)
17
+ elsif message['errors'].present?
18
+ puts pastel.red(message['errors'].map { |k, v| "#{k}: #{v}" }.join(", "))
19
19
  end
20
20
  rescue => e
21
21
  puts Pastel.new.dim(e.message)
@@ -33,6 +33,18 @@ module Terjira
33
33
  def current_username
34
34
  @current_username ||= Client::Base.username
35
35
  end
36
+
37
+ def open_url(url)
38
+ ostype = `echo $OSTYPE`
39
+ open_cmd = case ostype
40
+ when /darwin/ then 'open'
41
+ when /cygwin/ then 'cygstart'
42
+ when /linux/ then 'xdg-open'
43
+ when /msys/ then 'start ""'
44
+ else puts "Platform $OSTYPE not supported"
45
+ end
46
+ `#{open_cmd} #{url}`
47
+ end
36
48
  end
37
49
  end
38
50
  end
@@ -8,7 +8,7 @@ module Terjira
8
8
  end
9
9
  end
10
10
 
11
- desc "( ls | list)", "list all boards"
11
+ desc "( ls | list)", "List all boards"
12
12
  map ls: :list
13
13
  def list
14
14
  boards = client_class.all
@@ -23,6 +23,11 @@ module Terjira
23
23
  client.send(class_name) if client.respond_to?(class_name)
24
24
  end
25
25
 
26
+ def site_url
27
+ auth_options = build_auth_options
28
+ "#{auth_options[:site]}/#{auth_options[:context_path]}"
29
+ end
30
+
26
31
  def username
27
32
  client.options[:username]
28
33
  end
@@ -10,6 +10,10 @@ module Terjira
10
10
  end
11
11
  end
12
12
 
13
+ def find_by_key(key)
14
+ all.find { |field| field.key == key }
15
+ end
16
+
13
17
  def epic_name
14
18
  all.find { |field| field.name == 'Epic Name' }
15
19
  end
@@ -22,6 +22,10 @@ module Terjira
22
22
  build(resp)
23
23
  end
24
24
 
25
+ def delete(issue)
26
+ api_delete("issue/#{issue.key_value}")
27
+ end
28
+
25
29
  def assign(issue, assignee)
26
30
  body = { name: assignee.key_value }.to_json
27
31
  api_put("issue/#{issue.key_value}/assignee", body)
@@ -34,17 +38,14 @@ module Terjira
34
38
 
35
39
  def create(options = {})
36
40
  params = extract_to_fields_params(options)
37
- if transition_param = extract_to_transition_param(options)
38
- params.merge!(transition_param)
39
- end
40
-
41
41
  resp = api_post 'issue', params.to_json
42
42
  find(resp['id'])
43
43
  end
44
44
 
45
45
  def update(issue, options = {})
46
- params = extract_to_fields_params(options)
47
- api_put "issue/#{issue.key_value}", params.to_json
46
+ params = extract_to_update_params(options)
47
+ params.merge!(extract_to_fields_params(options))
48
+ resp = api_put "issue/#{issue.key_value}", params.to_json
48
49
  find(issue)
49
50
  end
50
51
 
@@ -78,21 +79,19 @@ module Terjira
78
79
  params = {}
79
80
 
80
81
  custom_fields = options.keys.select { |k| k.to_s =~ /^customfield/ }
82
+
81
83
  (custom_fields + [:summary, :description]).each do |k, _v|
82
84
  params[k] = opts.delete(k) if opts.key?(k)
83
85
  end
84
86
 
85
- if opts.key?(:project)
86
- params[:project] = { key: opts.delete(:project).key_value }
87
+ [:project, :parent].each do |resource|
88
+ if opts.key?(resource)
89
+ params[resource] = { key: opts.delete(resource).key_value }
90
+ end
87
91
  end
88
92
 
89
- if opts.key?(:parent)
90
- params[:parent] = { key: opts.delete(:parent).key_value }
91
- end
93
+ opts.each { |k, v| params[k] = convert_param_key_value_hash(v) }
92
94
 
93
- opts.each do |k, v|
94
- params[k] = convert_param_key_value_hash(v)
95
- end
96
95
  { fields: params }
97
96
  end
98
97
 
@@ -13,9 +13,9 @@ module Terjira
13
13
  default_task :show
14
14
 
15
15
  desc '[ISSUE_KEY]', 'Show detail of the issue'
16
- def show(issue_key = nil)
17
- return invoke(:help) unless issue_key
18
- issue = client_class.find(issue_key)
16
+ def show(issue = nil)
17
+ return invoke(:help) unless issue
18
+ issue = client_class.find(issue)
19
19
  if issue.issuetype.name.casecmp('epic').zero?
20
20
  epic_issues = client_class.all_epic_issues(issue)
21
21
  render_issue_detail(issue, epic_issues)
@@ -24,6 +24,11 @@ module Terjira
24
24
  end
25
25
  end
26
26
 
27
+ desc 'open [ISSUE_KEY]', 'Open browser'
28
+ def open(issue)
29
+ open_url(client_class.site_url + "/browse/#{issue}")
30
+ end
31
+
27
32
  desc '( ls | list )', 'List of issues'
28
33
  jira_options :assignee, :status, :project, :issuetype, :priority
29
34
  map ls: :list
@@ -37,29 +42,7 @@ module Terjira
37
42
  render_issues(issues)
38
43
  end
39
44
 
40
- desc 'trans [ISSUE_KEY] ([STATUS])', 'Do Transition'
41
- jira_options :comment, :assignee, :resolution
42
- def trans(*args)
43
- issue = args.shift
44
- raise 'must pass issue key or id' unless issue
45
- status = args.join(' ') if args.present?
46
- issue = client_class.find(issue, expand: 'transitions.fields')
47
-
48
- transitions = issue.transitions
49
- transition = transitions.find { |t| t.name.casecmp(status.to_s).zero? }
50
-
51
- resources = if transition
52
- { status: transition, issue: issue }
53
- else
54
- { statuses: transitions, issue: issue }
55
- end
56
-
57
- opts = suggest_options(required: [:status], resources: resources)
58
- issue = client_class.trans(issue, opts)
59
- render_issue_detail(issue)
60
- end
61
-
62
- desc 'new', 'Create issue'
45
+ desc 'new', 'Create an issue'
63
46
  jira_options :summary, :description, :project, :issuetype,
64
47
  :priority, :assignee, :parent, :epiclink
65
48
  def new
@@ -71,7 +54,7 @@ module Terjira
71
54
  render_issue_detail(issue)
72
55
  end
73
56
 
74
- desc 'edit', 'Edit issue'
57
+ desc 'edit', 'Edit the issue'
75
58
  jira_options :summary, :description, :project, :issuetype,
76
59
  :priority, :assignee, :epiclink
77
60
  def edit(issue)
@@ -84,6 +67,12 @@ module Terjira
84
67
  render_issue_detail(issue)
85
68
  end
86
69
 
70
+ desc 'delete', 'Delete the issue'
71
+ def delete(issue)
72
+ client_class.delete(issue)
73
+ render("Deleted")
74
+ end
75
+
87
76
  desc 'comment', 'Write comment on the issue'
88
77
  jira_options :comment
89
78
  def comment(issue)
@@ -92,12 +81,12 @@ module Terjira
92
81
  render_issue_detail(issue)
93
82
  end
94
83
 
95
- desc 'take [ISSUE_KEY]', 'Assign issue to self'
84
+ desc 'take [ISSUE_KEY]', 'Assign the issue to self'
96
85
  def take(issue)
97
86
  assign(issue, current_username)
98
87
  end
99
88
 
100
- desc 'assign [ISSUE_KEY] ([ASSIGNEE])', 'Assing issue to user'
89
+ desc 'assign [ISSUE_KEY] ([ASSIGNEE])', 'Assign the issue to user'
101
90
  def assign(*keys)
102
91
  issue = keys[0]
103
92
  assignee = keys[1]
@@ -110,5 +99,27 @@ module Terjira
110
99
  client_class.assign(issue, assignee)
111
100
  show(issue.key_value)
112
101
  end
102
+
103
+ desc 'trans [ISSUE_KEY] ([STATUS])', 'Do transition'
104
+ jira_options :comment, :assignee, :resolution
105
+ def trans(*args)
106
+ issue = args.shift
107
+ raise 'must pass issue key or id' unless issue
108
+ status = args.join(' ') if args.present?
109
+ issue = client_class.find(issue, expand: 'transitions.fields')
110
+
111
+ transitions = issue.transitions
112
+ transition = transitions.find { |t| t.name.casecmp(status.to_s).zero? }
113
+
114
+ resources = if transition
115
+ { status: transition, issue: issue }
116
+ else
117
+ { statuses: transitions, issue: issue }
118
+ end
119
+
120
+ opts = suggest_options(required: [:status], resources: resources)
121
+ issue = client_class.trans(issue, opts)
122
+ render_issue_detail(issue)
123
+ end
113
124
  end
114
125
  end
@@ -30,13 +30,11 @@ module Terjira
30
30
  Time.parse(date_str).strftime(date_format)
31
31
  end
32
32
 
33
- def username_with_email(user)
33
+ def username(user)
34
34
  if user.nil?
35
35
  dim_none
36
36
  else
37
- title = "#{user.name}, #{user.displayName}"
38
- title += " <#{user.emailAddress}>" if user.respond_to?(:emailAddress)
39
- title
37
+ "#{user.name}, #{user.displayName}"
40
38
  end
41
39
  end
42
40
 
@@ -40,7 +40,7 @@ module Terjira
40
40
  def render_issue_detail(issue, epic_issues = [])
41
41
  result = ERB.new(issue_detail_template, nil, '-').result(binding)
42
42
  result += ERB.new(comments_template, nil, '-').result(binding)
43
- rows = insert_new_line(result, screen_width - 10)
43
+ rows = insert_new_line(result, screen_width - 15)
44
44
  table = TTY::Table.new nil, rows.split("\n").map { |r| [r] }
45
45
  render table.render(:unicode, padding: [0, 1, 0, 1], multiline: true)
46
46
  end
@@ -60,7 +60,7 @@ module Terjira
60
60
  end
61
61
 
62
62
  def issue_detail_template
63
- """<%= bold(issue.key) + ' in ' + issue.project.name %>
63
+ %{<%= bold(issue.key) + ' in ' + issue.project.name %>
64
64
 
65
65
  <%= pastel.underline.bold(issue.summary) %>
66
66
 
@@ -75,8 +75,8 @@ module Terjira
75
75
  <%= bold('Sprint') %>: <%= colorize_sprint_state(issue.try(:sprint).try(:state)) %> <%= issue.try(:sprint).try(:id) %>. <%= issue.try(:sprint).try(:name) %>
76
76
  <% end -%>
77
77
 
78
- <%= bold('Assignee') %>: <%= username_with_email(issue.assignee) %>
79
- <%= bold('Reporter') %>: <%= username_with_email(issue.reporter) %>
78
+ <%= bold('Assignee') %>: <%= username(issue.assignee) %>
79
+ <%= bold('Reporter') %>: <%= username(issue.reporter) %>
80
80
 
81
81
  <%= bold('Description') %>
82
82
  <%= issue.description || dim_none %>
@@ -94,6 +94,11 @@ module Terjira
94
94
  <%= bold('Environment') %>
95
95
  <%= issue.environment %>
96
96
  <% end -%>
97
+ <% if issue.try(:attachment).present? -%>
98
+
99
+ <%= bold('Attachment') %>
100
+ <%= issue.attachment.map { |item| item['filename'] }.join(", ") %>
101
+ <% end -%>
97
102
  <% if issue.subtasks.size > 0 -%>
98
103
 
99
104
  <%= bold('SubTasks') %>
@@ -102,12 +107,13 @@ module Terjira
102
107
  <% end -%>
103
108
  <% end -%>
104
109
  <% if epic_issues.present? -%>
110
+
105
111
  <%= bold('Issues in Epic') %>
106
112
  <% epic_issues.each do |epic_issue| -%>
107
- * <%= bold(epic_issue.key) %> <%= colorize_issue_stastus(epic_issue.status) %> <%= epic_issue.summary %> <%= issue.assignee.try(:name) %>
113
+ * <%= bold(epic_issue.key) %> <%= colorize_issue_stastus(epic_issue.status) %> <%= epic_issue.summary %>
108
114
  <% end -%>
109
115
  <% end -%>
110
- """
116
+ }
111
117
  end
112
118
 
113
119
  def comments_template
@@ -121,9 +127,8 @@ module Terjira
121
127
  <%= pastel.dim('- ' + remain_comments.size.to_s + ' previous comments exist -') %>
122
128
  <% end -%>
123
129
  <% visiable_comments.each do |comment| -%>
124
- <%= pastel.bold(comment.author['displayName']) %> <%= formatted_date(comment.created) %>
125
130
  <%= comment.body %>
126
-
131
+ - <%= comment.author['displayName'] %> <%= formatted_date(comment.created) %>
127
132
  <% end -%>
128
133
  """
129
134
  end
@@ -43,7 +43,7 @@ module Terjira
43
43
  rows << ''
44
44
 
45
45
  rows << pastel.bold('Lead')
46
- rows << username_with_email(project.lead)
46
+ rows << username(project.lead)
47
47
  rows << ''
48
48
  rows << render_components_and_versions(project)
49
49
 
@@ -4,7 +4,7 @@ module Terjira
4
4
  class ProjectCLI < BaseCLI
5
5
  default_task :show
6
6
 
7
- desc '[PROJECT_KEY]', 'Show detail of project'
7
+ desc '[PROJECT_KEY]', 'Show detail of the project'
8
8
  def show(project_key = nil)
9
9
  if project_key.nil?
10
10
  project = select_project
@@ -15,7 +15,7 @@ module Terjira
15
15
  redner_project_detail(project)
16
16
  end
17
17
 
18
- desc '( ls | list )', 'list of projects'
18
+ desc '( ls | list )', 'List of all projects'
19
19
  map ls: :list
20
20
  def list
21
21
  projects = Client::Project.all
@@ -11,7 +11,7 @@ module Terjira
11
11
 
12
12
  default_task :show
13
13
 
14
- desc '[SPRINT_ID]', 'Default, show sprint'
14
+ desc '[SPRINT_ID]', 'Show the sprint'
15
15
  jira_option(:assignee)
16
16
  def show(sprint = nil)
17
17
  opts = suggest_options(required: [:sprint], resources: { sprint: sprint })
@@ -38,7 +38,7 @@ module Terjira
38
38
  end
39
39
  end
40
40
 
41
- desc '( ls | list )', 'list all sprint from the board'
41
+ desc '( ls | list )', 'List of all sprint from the board'
42
42
  jira_options :board, :state
43
43
  map ls: :list
44
44
  def list
@@ -1,3 +1,3 @@
1
1
  module Terjira
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
data/sample.png ADDED
Binary file
data/terjira.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Jaehyun Shin"]
11
11
  spec.email = ["keepcosmos@gmail.com"]
12
12
 
13
- spec.summary = "Terjira is interactive command line app for Jira"
13
+ spec.summary = "Terjira is interactive command line application for Jira"
14
14
  spec.description = "Terjira is interactive and easy to use command line interface (or Application) for Jira.\nYou do not need to remember reosurce key or id. Terjira suggests with interactive prompt."
15
15
  spec.homepage = "https://github.com/keepcosmos/terjira"
16
16
  spec.license = "MIT"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terjira
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaehyun Shin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-16 00:00:00.000000000 Z
11
+ date: 2016-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -253,6 +253,7 @@ files:
253
253
  - lib/terjira/sprint_cli.rb
254
254
  - lib/terjira/utils/file_cache.rb
255
255
  - lib/terjira/version.rb
256
+ - sample.png
256
257
  - terjira.gemspec
257
258
  homepage: https://github.com/keepcosmos/terjira
258
259
  licenses:
@@ -277,6 +278,6 @@ rubyforge_project:
277
278
  rubygems_version: 2.6.4
278
279
  signing_key:
279
280
  specification_version: 4
280
- summary: Terjira is interactive command line app for Jira
281
+ summary: Terjira is interactive command line application for Jira
281
282
  test_files: []
282
283
  has_rdoc: