jirify 0.1.1 → 0.1.2

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
  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