jirify 0.1.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffc744ba29ebc793a458fc12b583b97b4fd7107713c90de2614a65de044419fa
4
- data.tar.gz: 48387acd76cb182e3e2581b069e3f8c7f61996db39b71ce7bd9463426582f080
3
+ metadata.gz: 5528c8d48b61117388daf001e8035ea61d6e3ed7f91efb1083d1e2d04d94db7b
4
+ data.tar.gz: fbe37f94e037385cc423df5bf27c9696ae807d0cb6263b070272fecc093e3ede
5
5
  SHA512:
6
- metadata.gz: 1d2c2ba015b016166011a248afc5c8c31323bb924d3f1ee010250affc5dbe72e015134fe4e482ab772b5ecb9903f6d6e7fb52433b164bde5f963f32625599d02
7
- data.tar.gz: 5e5c53f469ca2d01a91b3665f895fbf756abe1fb965ad09add3f9cd8e2db091edd50a2d9d01f337f0337366001ea93f058295f888db3b272af6b83ef931c9b94
6
+ metadata.gz: 5c145893008fe97f50f744d010463ec9fd64cbd48d5f861160674789797de01eb3052beb8ef5f18b410d8df352e587f9031dbe71ee0e8f2d0611b8ee7662556d
7
+ data.tar.gz: fbfdfb7d636c451a7e25d6f9fe52c19412bfc4e855c788a3dd744437522b2d66722df50cc1bc0563c82822fa4ebdeb5d15c4eb12c97a7fcf28b282f41b4b0f2a
@@ -1,25 +1,210 @@
1
1
  module Jirify
2
- class CLI < Thor
3
- desc "mine", "List all of the issues assigned to you in the current sprint"
4
- method_option :in_progress, type: :boolean, aliases: '-i', desc: "Show only issues in progress"
5
- method_option :in_review, type: :boolean, aliases: '-r', desc: "Show only issues in review"
6
- method_option :closed, type: :boolean, aliases: '-c', desc: "Show only closed issues"
7
- method_option :todo, type: :boolean, aliases: '-t', desc: "Show only issues in todo"
8
- method_option :all, type: :boolean, aliases: '-a', desc: "Show all assigned issues in Project - not limited to sprint"
9
- method_option :status, banner: "<status>", type: :string, aliases: '-s', desc: "Show only issues with the specified status"
10
- method_option :statuses, banner: "<statuses>", type: :array, desc: "Show only issues with the specified statuses"
11
- def mine
12
- if options[:status]
13
- statuses = [options[:status]]
14
- else
15
- statuses = []
16
- statuses << "To Do" if options[:todo]
17
- statuses << "In Progress" if options[:in_progress]
18
- statuses << "In Review" if options[:in_review]
19
- statuses << "Closed" if options[:closed]
20
- end
21
-
22
- Jirify::Issues.mine(options[:verbose], statuses, options[:all])
2
+ module Subcommands
3
+ class Issues < Thor
4
+ default_task :mine
5
+
6
+ desc 'mine', 'List all of the issues assigned to you in the current sprint'
7
+ method_option :in_progress, type: :boolean, aliases: '-i', desc: 'Show only issues in progress'
8
+ method_option :in_review, type: :boolean, aliases: '-r', desc: 'Show only issues in review'
9
+ method_option :closed, type: :boolean, aliases: '-c', desc: 'Show only closed issues'
10
+ method_option :todo, type: :boolean, aliases: '-t', desc: 'Show only issues in todo'
11
+ method_option :blocked, type: :boolean, aliases: '-b', desc: 'Show only blocked issues'
12
+ method_option :all,
13
+ type: :boolean,
14
+ aliases: '-a',
15
+ desc: 'Show all assigned issues in Project - not limited to sprint'
16
+ method_option :status,
17
+ banner: '<status>',
18
+ type: :string,
19
+ aliases: '-s',
20
+ desc: 'Show only issues with the specified status'
21
+ method_option :statuses,
22
+ banner: '<statuses>',
23
+ type: :array,
24
+ desc: 'Show only issues with the specified statuses'
25
+ def mine
26
+ statuses = build_issue_statuses(options)
27
+ issues = Jirify::Issue.list_mine(statuses, options[:all])
28
+ issues.each { |issue| issue.print Config.always_verbose || options[:verbose] }
29
+ end
30
+
31
+ desc 'assignee [ISSUE]', 'Displays issue assignee'
32
+ def assignee(issue_id)
33
+ issue = get_issue_or_exit issue_id
34
+
35
+ if issue.assignee.nil?
36
+ puts 'Unassigned'.yellow
37
+ else
38
+ puts issue.assignee.name
39
+ end
40
+ end
41
+
42
+ desc 'unassign [ISSUE]', 'Unassign an issue'
43
+ def unassign(issue_id)
44
+ issue = get_issue_or_exit issue_id
45
+
46
+ if issue.assignee.nil?
47
+ puts 'Issue already unassigned'.yellow
48
+ exit(0)
49
+ end
50
+
51
+ puts "Previous assignee: #{issue.assignee.name}. Unassigning..."
52
+ issue.unassign!
53
+ end
54
+
55
+ desc 'take [ISSUE]', 'Assigns an issue to you'
56
+ def take(issue_id)
57
+ issue = get_issue_or_exit issue_id
58
+
59
+ puts "Assigning #{issue.key} to #{Config.username}..."
60
+ issue.assign_to_me!
61
+ end
62
+
63
+ desc 'status [ISSUE]', 'Displays issue status'
64
+ def status(issue_id)
65
+ issue = get_issue_or_exit issue_id
66
+
67
+ puts issue.status.name
68
+ end
69
+
70
+ desc 'transitions [ISSUE]', 'Displays available transitions'
71
+ def transitions(issue_id)
72
+ issue = get_issue_or_exit issue_id
73
+
74
+ puts 'Available transitions:'
75
+ puts issue.transitions.names
76
+ end
77
+
78
+ desc 'transition [ISSUE] [TRANSITION]', 'Manually perform a transition'
79
+ def transition(issue_id, transition_name)
80
+ issue = get_issue_or_exit issue_id
81
+ transition = issue.transitions.list.find { |t| t.name == transition_name }
82
+
83
+ if transition.nil?
84
+ puts "ERROR: Issue can't transition to #{transition_name}".red
85
+ exit(0)
86
+ end
87
+
88
+ puts "Transitioning #{issue.key} with #{transition_name}...".green
89
+ issue.transition! transition
90
+ end
91
+
92
+ desc 'block [ISSUE]', "Moves an issue to #{Config.statuses['blocked']}"
93
+ def block(issue_id)
94
+ issue = get_issue_or_exit issue_id
95
+ check_assigned_to_self issue
96
+
97
+ issue.reopen! if issue.done?
98
+ issue.stop_review! if issue.in_review?
99
+ issue.block!
100
+ end
101
+
102
+ desc 'unblock [ISSUE]', 'Unblocks an issue'
103
+ def unblock(issue_id)
104
+ issue = get_issue_or_exit issue_id
105
+ check_assigned_to_self issue
106
+
107
+ if issue.blocked?
108
+ puts 'Unblocking issue...'
109
+ issue.unblock!
110
+ else
111
+ puts 'Issue wasn\'t blocked anyway :)'.green
112
+ end
113
+ end
114
+
115
+ desc 'todo [ISSUE]', "Moves an issue to #{Config.statuses['todo']}"
116
+ def todo(issue_id)
117
+ issue = get_issue_or_exit issue_id
118
+ check_assigned_to_self issue
119
+
120
+ if issue.blocked?
121
+ issue.unblock!
122
+ elsif issue.in_progress?
123
+ issue.stop!
124
+ elsif issue.in_review?
125
+ issue.stop_review!
126
+ issue.stop!
127
+ elsif issue.done?
128
+ issue.reopen!
129
+ end
130
+ end
131
+
132
+ desc 'start [ISSUE]', "Moves an issue to #{Config.statuses['in_progress']}"
133
+ def start(issue_id)
134
+ issue = get_issue_or_exit issue_id
135
+ check_assigned_to_self issue
136
+
137
+ issue.unblock! if issue.blocked?
138
+ issue.reopen! if issue.done?
139
+
140
+ if issue.in_review?
141
+ issue.stop_review!
142
+ else
143
+ issue.start!
144
+ end
145
+ end
146
+
147
+ desc 'review [ISSUE]', "Moves an issue to #{Config.statuses['in_review']}"
148
+ def review(issue_id)
149
+ issue = get_issue_or_exit issue_id
150
+ check_assigned_to_self issue
151
+
152
+ if issue.blocked?
153
+ issue.unblock!
154
+ issue.start!
155
+ elsif issue.todo?
156
+ issue.start!
157
+ elsif issue.done?
158
+ issue.reopen!
159
+ issue.start!
160
+ end
161
+
162
+ issue.start_review!
163
+ end
164
+
165
+ desc 'close [ISSUE]', "Moves an issue to #{Config.statuses['done']}"
166
+ def close(issue_id)
167
+ issue = get_issue_or_exit issue_id
168
+ check_assigned_to_self issue
169
+
170
+ issue.unblock! if issue.blocked?
171
+ issue.close!
172
+ end
173
+
174
+ protected
175
+
176
+ def get_issue_or_exit(issue_id)
177
+ issue = Jirify::Issue.find_by_id(issue_id)
178
+
179
+ if issue.nil?
180
+ puts 'ERROR: Issue not found'.red
181
+ exit(0)
182
+ else
183
+ issue
184
+ end
185
+ end
186
+
187
+ def check_assigned_to_self(issue)
188
+ unless issue.mine?
189
+ exit(0) unless yes? 'WARNING! This issue is not assigned to you!'\
190
+ ' Are you sure you want to continue? [Y/n]:'.yellow
191
+ end
192
+ end
193
+
194
+ def build_issue_statuses(options)
195
+ if options[:status]
196
+ statuses = [options[:status]]
197
+ else
198
+ statuses = []
199
+ statuses << Config.statuses['blocked'] if options[:blocked]
200
+ statuses << Config.statuses['todo'] if options[:todo]
201
+ statuses << Config.statuses['in_progress'] if options[:in_progress]
202
+ statuses << Config.statuses['in_review'] if options[:in_review]
203
+ statuses << Config.statuses['done'] if options[:closed]
204
+ end
205
+
206
+ statuses
207
+ end
23
208
  end
24
209
  end
25
210
  end
@@ -0,0 +1,12 @@
1
+ module Jirify
2
+ module Subcommands
3
+ class Projects < Thor
4
+ desc 'list', 'List all projects'
5
+ def list
6
+ puts Jirify::Project.all.map(&:name)
7
+ end
8
+
9
+ default_task :list
10
+ end
11
+ end
12
+ end
@@ -1,37 +1,44 @@
1
1
  module Jirify
2
- class CLI < Thor
3
- desc "setup", "A guided setup for jirify"
4
- def setup
5
- say "Welcome! This will guide you through the configuration of the jirify CLI tool."
6
-
7
- if Config.initialized?
8
- puts
9
- reconfigure = yes? "You seem to have already configured jirify.\n" \
10
- "Do you want to continue and overwrite the current configuration? [Y/N]"
11
- exit(0) unless reconfigure
12
- end
2
+ module Subcommands
3
+ class Setup < Thor
4
+ default_task :init
5
+
6
+ desc 'init', 'A guided setup for jirify'
7
+ def init
8
+ say 'Welcome! This will guide you through the configuration of the jirify CLI tool.'
13
9
 
14
- username = ask "Enter username:"
15
- token = ask "Enter token (generate from https://id.atlassian.com):"
16
- site = ask "Enter JIRA url:"
17
- project = ask "Enter JIRA Project key:"
18
- filter_labels = ask "Enter a comma-separated list of labels to filter by every time (optional):"
10
+ if Config.initialized?
11
+ exit(0) unless yes? 'You seem to have already configured jirify. ' \
12
+ 'Do you want to continue and overwrite the current configuration? [Y/n]:'.yellow
13
+ end
19
14
 
20
- labels = filter_labels.split ', ' if filter_labels
15
+ username = ask 'Enter username:'
16
+ token = ask 'Enter token (generate from https://id.atlassian.com):'
17
+ site = ask 'Enter JIRA url:'
18
+ project = ask 'Enter JIRA Project key:'
19
+ filter_labels = ask 'Enter a comma-separated list of labels to filter by every time (optional):'
21
20
 
22
- options = {
23
- 'options' => {
24
- 'username' => username,
25
- 'token' => token,
26
- 'site' => site,
27
- 'project' => project,
21
+ labels = filter_labels.split ', ' if filter_labels
22
+
23
+ options = {
24
+ 'options' => {
25
+ 'username' => username,
26
+ 'token' => token,
27
+ 'site' => site,
28
+ 'project' => project
29
+ }
28
30
  }
29
- }
30
31
 
31
- options['options']['filter_by_labels'] = labels unless labels.empty?
32
+ options['options']['filter_by_labels'] = labels unless labels.empty?
32
33
 
33
- Config.write(options)
34
+ Config.write(options)
35
+ end
36
+
37
+ desc 'verbose', 'Set always verbose to true or false'
38
+ method_option :enable, type: :boolean, aliases: '-e', default: false, desc: 'Enable or disable'
39
+ def verbose
40
+ Config.verbose(options[:enable])
41
+ end
34
42
  end
35
43
  end
36
44
  end
37
-
@@ -1,10 +1,12 @@
1
1
  module Jirify
2
2
  class CLI < Thor
3
- desc "sprint", "Show the current sprint table"
4
- method_option :mine, type: :boolean, aliases: '-m', desc: "Show only issues assigned to me"
5
- method_option :all_columns, type: :boolean, aliases: '-a', desc: "Show all columns"
3
+ desc 'sprint', 'Show the current sprint table'
4
+ method_option :mine, type: :boolean, aliases: '-m', desc: 'Show only issues assigned to me'
5
+ method_option :all_columns, type: :boolean, aliases: '-a', desc: 'Show all columns'
6
6
  def sprint
7
- Jirify::Sprint.current(options[:verbose], options[:columns], options[:mine])
7
+ Jirify::Sprint.current(Config.always_verbose || options[:verbose],
8
+ options[:all_columns],
9
+ options[:mine])
8
10
  end
9
11
  end
10
12
  end
data/lib/jirify/config.rb CHANGED
@@ -4,40 +4,86 @@ module Jirify
4
4
  class Config
5
5
  class << self
6
6
  def initialized?
7
- File.exists? config_file
7
+ File.exist? config_file
8
8
  end
9
9
 
10
10
  def write(config)
11
- puts "Writing config:"
11
+ puts 'Writing config:'
12
12
  puts config.to_yaml
13
13
 
14
14
  File.write(config_file, config.to_yaml)
15
15
  end
16
16
 
17
+ def verbose(value)
18
+ unless initialized?
19
+ puts 'ERROR: You must initialize Jirify first!'.red
20
+ exit(0)
21
+ end
22
+
23
+ config = YAML.load_file(config_file)
24
+ config['options']['verbose'] = value
25
+ write(config)
26
+ end
27
+
17
28
  def config_file
18
29
  @config_file ||= "#{Dir.home}/.jirify"
19
30
  end
20
31
 
21
32
  def options
22
- raise StandardError unless initialized?
33
+ unless initialized?
34
+ puts 'ERROR: You must initialize Jirify first!'.red
35
+ exit(0)
36
+ end
37
+
23
38
  @options ||= YAML.load_file(config_file)['options']
24
39
  end
25
40
 
41
+ def always_verbose
42
+ options['verbose']
43
+ end
44
+
26
45
  def atlassian_url
27
46
  options['site']
28
47
  end
29
48
 
49
+ def username
50
+ options['username']
51
+ end
52
+
30
53
  def issue_browse_url
31
54
  "#{atlassian_url}/browse/"
32
55
  end
33
56
 
57
+ def statuses
58
+ options['statuses'] || {
59
+ 'blocked' => 'Blocked',
60
+ 'todo' => 'To Do',
61
+ 'in_progress' => 'In Progress',
62
+ 'in_review' => 'In Review',
63
+ 'done' => 'Closed'
64
+ }
65
+ end
66
+
67
+ def transitions
68
+ options['transitions'] || {
69
+ 'block' => 'Blocked',
70
+ 'unblock' => 'Unblock',
71
+ 'start' => 'Start Progress',
72
+ 'stop' => 'Stop Progress',
73
+ 'start_review' => 'Code Review',
74
+ 'stop_review' => 'Back to In Progress',
75
+ 'close' => 'Close',
76
+ 'reopen' => 'Reopen'
77
+ }
78
+ end
79
+
34
80
  def client_options
35
81
  {
36
- :username => options['username'],
37
- :password => options['token'],
38
- :site => atlassian_url,
39
- :context_path => '',
40
- :auth_type => :basic,
82
+ username: options['username'],
83
+ password: options['token'],
84
+ site: atlassian_url,
85
+ context_path: '',
86
+ auth_type: :basic
41
87
  }
42
88
  end
43
89
  end
@@ -1,5 +1,21 @@
1
1
  module Jirify
2
2
  class Base
3
+ def initialize(entity)
4
+ @entity = entity
5
+ end
6
+
7
+ def method_missing(method, *args, &_block)
8
+ if @entity.respond_to? method
9
+ @entity.send method, *args
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def respond_to_missing?(method, *)
16
+ @entity.respond_to? method
17
+ end
18
+
3
19
  class << self
4
20
  def client
5
21
  @client ||= JIRA::Client.new(Config.client_options)
@@ -0,0 +1,106 @@
1
+ module JIRA
2
+ module Resource
3
+ class Issue
4
+ def transition!(transition)
5
+ attrs = { transition: transition.id }.to_json
6
+ client.send(:post, "#{url}/transitions", attrs)
7
+ end
8
+
9
+ def assign_to!(username)
10
+ client.send(:put, "#{url}/assignee", { name: username }.to_json)
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ module Jirify
17
+ class Issue < Base
18
+ class InvalidTransitionError < StandardError; end
19
+
20
+ def mine?
21
+ !assignee.nil? && assignee.emailAddress == Config.username
22
+ end
23
+
24
+ def assign_to_me!
25
+ @entity.assign_to!(Config.username.split('@')[0])
26
+ end
27
+
28
+ def unassign!
29
+ @entity.assign_to!(nil)
30
+ end
31
+
32
+ def status
33
+ @status ||= Jirify::Status.new @entity.status
34
+ end
35
+
36
+ def status?(status_name)
37
+ status_name = status_name.to_s if status_name.is_a? Symbol
38
+ status.name == status_name
39
+ end
40
+
41
+ Config.statuses.keys.each do |status_key|
42
+ define_method "#{status_key.to_sym}?" do
43
+ status.name == Config.statuses[status_key]
44
+ end
45
+ end
46
+
47
+ def transitions(reload = false)
48
+ if reload
49
+ @transitions = Jirify::TransitionList.all @entity
50
+ else
51
+ @transitions ||= Jirify::TransitionList.all @entity
52
+ end
53
+ end
54
+
55
+ Config.transitions.keys.each do |transition_name|
56
+ define_method "#{transition_name}!".to_sym do
57
+ transition = transitions(true).send(transition_name.to_sym)
58
+
59
+ if transition.nil?
60
+ puts "ERROR: Issue can't be transitioned with \"#{transition_name}\"".red
61
+ exit(0)
62
+ end
63
+
64
+ puts "Transitioning #{key} with \"#{transition_name}\"...".green
65
+ @entity.transition! transition
66
+ end
67
+ end
68
+
69
+ def print(verbose)
70
+ url = "#{Config.issue_browse_url}#{key}".blue
71
+
72
+ if verbose
73
+ puts "#{status.pretty_name} #{key.ljust(7)}: #{summary} (#{url})"
74
+ else
75
+ puts "#{key.ljust(7)}: (#{url})"
76
+ end
77
+ end
78
+
79
+ class << self
80
+ def list_mine(statuses = [], all = false)
81
+ my_issues = find_mine(all).sort_by { |issue| issue.status.name }
82
+
83
+ my_issues.select do |issue|
84
+ statuses.empty? || statuses.any? { |status| issue.status? status }
85
+ end
86
+ end
87
+
88
+ def find_mine(all)
89
+ client.Issue.jql(my_issues_jql(all)).map { |issue| Issue.new issue }
90
+ end
91
+
92
+ def find_by_id(issue_id)
93
+ Issue.new client.Issue.find(issue_id)
94
+ rescue StandardError
95
+ nil
96
+ end
97
+
98
+ protected
99
+
100
+ def my_issues_jql(all_issues)
101
+ all_clause = 'AND sprint in openSprints()' unless all_issues
102
+ "project='#{project}' #{all_clause} AND assignee='#{Config.username}'"
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,9 @@
1
+ module Jirify
2
+ class Project < Base
3
+ class << self
4
+ def all
5
+ client.Project.all.map { |project| Project.new project }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,4 +1,3 @@
1
- require 'colorize'
2
1
  require 'terminal-table'
3
2
  require 'json'
4
3
 
@@ -6,41 +5,49 @@ module Jirify
6
5
  class Sprint < Base
7
6
  class << self
8
7
  def current(verbose = false, all_columns = false, only_mine = false)
8
+ issues = client.Issue.jql current_sprint_jql(only_mine), max_results: 200
9
+
10
+ grouped_issues = issues.group_by do |issue|
11
+ all_columns ? issue.status.name : issue.status.statusCategory['name']
12
+ end
13
+
14
+ print_grouped_issues_as_table(grouped_issues, verbose)
15
+ end
16
+
17
+ protected
18
+
19
+ def current_sprint_jql(only_mine)
9
20
  labels = Config.options['filter_by_labels']
10
- labels = labels.join(", ") if labels
21
+ labels = labels.join(', ') if labels
11
22
 
12
23
  labels_clause = "AND labels in (#{labels})" if labels
13
- mine_clause = "AND assignee='#{Config.options["username"]}'" if only_mine
24
+ mine_clause = "AND assignee='#{Config.username}'" if only_mine
25
+ sprint_clause = 'AND sprint in openSprints()'
14
26
 
15
- issues = client.Issue.jql("project='#{project}' AND sprint in openSprints() #{labels_clause} #{mine_clause}", { max_results: 200 })
16
-
17
- if all_columns
18
- grouped_issues = issues.group_by { |issue| issue.status.name }
19
- else
20
- grouped_issues = issues.group_by { |issue| issue.status.statusCategory['name'] }
21
- end
27
+ "project='#{project}' #{sprint_clause} #{labels_clause} #{mine_clause}"
28
+ end
22
29
 
30
+ def print_grouped_issues_as_table(grouped_issues, verbose)
23
31
  all_groups = grouped_issues.values
24
32
 
25
33
  l = all_groups.map(&:length).max
26
- transposed = all_groups.map{ |e| e.values_at(0...l) }.transpose
34
+ transposed = all_groups.map { |e| e.values_at(0...l) }.transpose
27
35
 
28
36
  transposed = transposed.map do |row|
29
37
  row.map do |issue|
30
38
  if issue
31
- key = issue.key.ljust(7)
32
- url = "(#{Config.issue_browse_url}/#{issue.key})".blue
39
+ key = issue.key.ljust(7)
40
+ url = "(#{Config.issue_browse_url}/#{issue.key})".blue
33
41
  summary = "#{issue.summary[0, 35]}...\n" if verbose
42
+
34
43
  "#{key}: #{summary}#{url}"
35
44
  else
36
- ""
45
+ ''
37
46
  end
38
47
  end
39
48
  end
40
49
 
41
- table = Terminal::Table.new headings: grouped_issues.keys, rows: transposed
42
-
43
- puts table unless transposed.empty?
50
+ puts Terminal::Table.new headings: grouped_issues.keys, rows: transposed unless transposed.empty?
44
51
  end
45
52
  end
46
53
  end
@@ -0,0 +1,49 @@
1
+ module Jirify
2
+ class Status < Base
3
+ def pretty_name
4
+ justified = "(#{name})".rjust(longest_status_name + 2)
5
+ case name
6
+ when Config.statuses['blocked'] then justified.red
7
+ when Config.statuses['done'] then justified.green
8
+ when Config.statuses['in_progress'] then justified.blue
9
+ when Config.statuses['in_review'] then justified.yellow
10
+ when Config.statuses['todo'] then justified.black
11
+ else justified
12
+ end
13
+ end
14
+
15
+ protected
16
+
17
+ def longest_status_name
18
+ Config.statuses.values.map(&:length).max
19
+ end
20
+
21
+ class << self
22
+ def all
23
+ @all ||= client.Status.all
24
+ end
25
+
26
+ def to_do
27
+ @to_do ||= find_by_name Config.statuses['todo']
28
+ end
29
+
30
+ def in_progress
31
+ @in_progress ||= find_by_name Config.statuses['in_progress']
32
+ end
33
+
34
+ def in_review
35
+ @in_review ||= find_by_name Config.statuses['in_review']
36
+ end
37
+
38
+ def closed
39
+ @closed ||= find_by_name Config.statuses['done']
40
+ end
41
+
42
+ protected
43
+
44
+ def find_by_name(status_name)
45
+ all.select { |status| status.name == status_name }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ module Jirify
2
+ class TransitionList < Base
3
+ attr_accessor :list
4
+
5
+ def initialize(list)
6
+ @list = list
7
+ end
8
+
9
+ def names
10
+ @list.map(&:name)
11
+ end
12
+
13
+ Config.transitions.keys.each do |transition_name|
14
+ define_method(transition_name.to_sym) { find_by_name transition_name }
15
+ end
16
+
17
+ protected
18
+
19
+ def find_by_name(name)
20
+ @list.find { |transition| transition.name == Config.transitions[name] }
21
+ end
22
+
23
+ class << self
24
+ def all(issue)
25
+ TransitionList.new client.Transition.all(issue: issue)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Jirify
2
- VERSION = "0.1.1"
2
+ VERSION = '0.1.2'.freeze
3
3
  end
data/lib/jirify.rb CHANGED
@@ -1,16 +1,33 @@
1
1
  require 'thor'
2
2
  require 'jira-ruby'
3
+ require 'colorize'
3
4
 
4
5
  require 'jirify/config'
6
+ require 'jirify/models/base'
7
+ require 'jirify/models/status'
8
+ require 'jirify/models/transition_list'
9
+ require 'jirify/models/issue'
10
+ require 'jirify/models/sprint'
11
+ require 'jirify/models/project'
5
12
  require 'jirify/cli/setup'
6
13
  require 'jirify/cli/sprint'
7
14
  require 'jirify/cli/issue'
8
- require 'jirify/models/base'
9
- require 'jirify/models/issues'
10
- require 'jirify/models/sprint'
15
+ require 'jirify/cli/project'
11
16
 
12
17
  module Jirify
13
18
  class CLI < Thor
14
- class_option :verbose, type: :boolean, aliases: '-v', desc: "Show more verbose information"
19
+ class_option :verbose, type: :boolean, aliases: '-v', desc: 'Show more verbose information'
20
+
21
+ desc 'setup SUBCOMMAND', 'Jirify setup tools'
22
+ subcommand 'setup', Subcommands::Setup
23
+
24
+ desc 'issues SUBCOMMAND', 'Work with JIRA Issues'
25
+ subcommand 'issues', Subcommands::Issues
26
+
27
+ desc 'i SUBCOMMAND', 'Work with JIRA Issues'
28
+ subcommand 'i', Subcommands::Issues
29
+
30
+ desc 'projects SUBCOMMAND', 'Work with JIRA Projects'
31
+ subcommand 'projects', Subcommands::Projects
15
32
  end
16
33
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jirify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georgi Gardev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-06 00:00:00.000000000 Z
11
+ date: 2018-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: jira-ruby
14
+ name: colorize
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.5'
19
+ version: '0.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.5'
26
+ version: '0.8'
27
27
  - !ruby/object:Gem::Dependency
28
- name: colorize
28
+ name: jira-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.8'
33
+ version: '1.5'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.8'
40
+ version: '1.5'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: terminal-table
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -77,12 +77,16 @@ files:
77
77
  - bin/jira
78
78
  - lib/jirify.rb
79
79
  - lib/jirify/cli/issue.rb
80
+ - lib/jirify/cli/project.rb
80
81
  - lib/jirify/cli/setup.rb
81
82
  - lib/jirify/cli/sprint.rb
82
83
  - lib/jirify/config.rb
83
84
  - lib/jirify/models/base.rb
84
- - lib/jirify/models/issues.rb
85
+ - lib/jirify/models/issue.rb
86
+ - lib/jirify/models/project.rb
85
87
  - lib/jirify/models/sprint.rb
88
+ - lib/jirify/models/status.rb
89
+ - lib/jirify/models/transition_list.rb
86
90
  - lib/jirify/version.rb
87
91
  homepage: https://github.com/GeorgeSG/jirify
88
92
  licenses:
@@ -1,34 +0,0 @@
1
- require 'colorize'
2
-
3
- module Jirify
4
- class Issues < Base
5
- class << self
6
- def mine(verbose, statuses = [], all = false)
7
- all_clause = "AND sprint in openSprints() " unless all
8
- my_issues = client.Issue.jql("project='#{project}' #{all_clause}AND assignee='#{Config.options["username"]}'")
9
-
10
- my_issues.sort_by! { |issue| issue.status.name }
11
- my_issues.each do |issue|
12
- status = issue.status.name
13
-
14
- next if statuses.any? && !statuses.include?(status)
15
-
16
- status_justified = "(#{status})".rjust(14)
17
- status_colorized = case status
18
- when "Done" then status_justified.green
19
- when "In Progress" then status_justified.blue
20
- when "In Review" then status_justified.yellow
21
- when "Closed" then status_justified.black
22
- else status_justified
23
- end
24
-
25
- if verbose
26
- print "#{status_colorized} #{issue.key.ljust(7)}: #{issue.summary} (#{Config.issue_browse_url}#{issue.key})\n"
27
- else
28
- print "#{issue.key.ljust(7)}: (#{Config.issue_browse_url}#{issue.key})\n"
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end