firespring_dev_commands 2.1.6.pre.alpha.1 → 2.1.7.pre.alpha.1
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 +4 -4
- data/lib/firespring_dev_commands/git.rb +1 -2
- data/lib/firespring_dev_commands/jira/histories.rb +11 -0
- data/lib/firespring_dev_commands/jira/history.rb +17 -0
- data/lib/firespring_dev_commands/jira/issue.rb +64 -3
- data/lib/firespring_dev_commands/jira/user.rb +3 -1
- data/lib/firespring_dev_commands/jira.rb +5 -3
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5efd3f846669710ea2f7f839df890d6489555a18bfe62ef77d644bf884c121e
|
4
|
+
data.tar.gz: 490a60e2c04726bbbb7d0950160395c3c3fb8c70313be14794fc6181296e7e0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11e1f6e01faea39bc49278011efcce6c4f9b30a6dd283efea6e96f13938596e21ed840f961646e3b4d487db50eb4e3a0604a00e14e304eb351f09e2165e7b5b1
|
7
|
+
data.tar.gz: 48d04949c727bade11d7f405701d705fd25eb9a67cd25516a83c799159f32738bd4133028f3271fcf2cddb17a728c422bbed8781bc21f58bfc7d5689543ba555
|
@@ -378,7 +378,7 @@ module Dev
|
|
378
378
|
# Clones the repo_name into the dir
|
379
379
|
# Optionally specify a repo_org
|
380
380
|
# Optionally specify a branch to check out (defaults to the repository default branch)
|
381
|
-
def clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil
|
381
|
+
def clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil)
|
382
382
|
if Dir.exist?("#{dir}/.git")
|
383
383
|
puts "#{dir} already cloned".light_green
|
384
384
|
return
|
@@ -390,7 +390,6 @@ module Dev
|
|
390
390
|
|
391
391
|
opts = {}
|
392
392
|
opts[:branch] = branch unless branch.to_s.strip.empty?
|
393
|
-
opts[:depth] = depth unless depth.to_s.strip.empty?
|
394
393
|
g = ::Git.clone(ssh_repo_url(repo_name, repo_org), dir, opts)
|
395
394
|
g.fetch('origin', prune: true)
|
396
395
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Dev
|
4
|
+
class Jira
|
5
|
+
class History
|
6
|
+
attr_accessor :date, :id, :author, :created, :items
|
7
|
+
|
8
|
+
def initialize(data)
|
9
|
+
@data = data
|
10
|
+
@id = data['id']
|
11
|
+
@author = data['author']
|
12
|
+
@items = data['items']
|
13
|
+
@created = Time.parse(data['created'])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,9 +3,9 @@ module Dev
|
|
3
3
|
# Contains information and methods representing a Jira issue
|
4
4
|
class Issue
|
5
5
|
# Issue subtypes which do not map to a story type
|
6
|
-
NON_STORY_TYPES = ['review', 'sub-task', 'code review sub-task', 'pre-deploy sub-task', 'deploy sub-task', 'devops sub-task'].freeze
|
6
|
+
NON_STORY_TYPES = ['epic', 'review', 'sub-task', 'code review sub-task', 'pre-deploy sub-task', 'deploy sub-task', 'devops sub-task'].freeze
|
7
7
|
|
8
|
-
attr_accessor :data, :project, :id, :title, :points, :assignee, :resolved_date
|
8
|
+
attr_accessor :data, :project, :id, :title, :points, :assignee, :resolved_date, :histories, :last_in_progress_history, :first_in_review_history, :last_closed_history
|
9
9
|
|
10
10
|
def initialize(data)
|
11
11
|
@data = data
|
@@ -15,10 +15,71 @@ module Dev
|
|
15
15
|
@points = calculate_points(data)
|
16
16
|
@assignee = Jira::User.lookup(data.assignee&.accountId)
|
17
17
|
@resolved_date = data.resolutiondate
|
18
|
+
@histories = Jira::Histories.populate(data)
|
19
|
+
@last_in_progress_history = nil
|
20
|
+
@first_in_review_history = nil
|
21
|
+
@last_closed_history = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def cycle_time
|
25
|
+
# Calculate the difference and convert to days
|
26
|
+
((last_closed_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
|
27
|
+
end
|
28
|
+
|
29
|
+
def in_progress_cycle_time
|
30
|
+
# Calculate the difference and convert to days
|
31
|
+
((first_in_review_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
|
32
|
+
end
|
33
|
+
|
34
|
+
def in_review_cycle_time
|
35
|
+
# Calculate the difference and convert to days
|
36
|
+
((last_closed_history.created - first_in_review_history.created) / 60 / 60 / 24).round(2)
|
37
|
+
end
|
38
|
+
|
39
|
+
private def last_in_progress_history
|
40
|
+
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
41
|
+
|
42
|
+
# Find the first instance in the histoy where the status moved to "In Progress"
|
43
|
+
@last_in_progress_history ||= histories.select do |history|
|
44
|
+
history.items.find do |item|
|
45
|
+
item['fieldId'] == 'status' && item['fromString'] == 'Open' && item['toString'] == 'In Progress'
|
46
|
+
end
|
47
|
+
end.max_by(&:created)
|
48
|
+
raise 'unable to find "In Progress" history entry needed to calculate cycle time' unless @last_in_progress_history
|
49
|
+
|
50
|
+
@last_in_progress_history
|
51
|
+
end
|
52
|
+
|
53
|
+
private def first_in_review_history
|
54
|
+
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
55
|
+
|
56
|
+
# Find the first instance in the histoy where the status moved to "In Review"
|
57
|
+
@first_in_review_history ||= histories.select do |history|
|
58
|
+
history.items.find do |item|
|
59
|
+
item['fieldId'] == 'status' && item['toString'] == 'In Review'
|
60
|
+
end
|
61
|
+
end.min_by(&:created)
|
62
|
+
raise 'unable to find "In Review" history entry needed to calculate cycle time' unless @first_in_review_history
|
63
|
+
|
64
|
+
@first_in_review_history
|
65
|
+
end
|
66
|
+
|
67
|
+
private def last_closed_history
|
68
|
+
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
69
|
+
|
70
|
+
# Find the last instance in the histoy where the status moved to "Closed"
|
71
|
+
@last_closed_history ||= histories.select do |history|
|
72
|
+
history.items.find do |item|
|
73
|
+
item['fieldId'] == 'status' && item['toString'] == 'Closed'
|
74
|
+
end
|
75
|
+
end.max_by(&:created)
|
76
|
+
raise 'unable to find "Closed" history entry needed to calculate cycle time' unless @last_closed_history
|
77
|
+
|
78
|
+
@last_closed_history
|
18
79
|
end
|
19
80
|
|
20
81
|
# Returns the value of the jira points field or 0 if the field is not found
|
21
|
-
def calculate_points(data)
|
82
|
+
private def calculate_points(data)
|
22
83
|
return data.send(Dev::Jira.config.points_field_name).to_i if Dev::Jira.config.points_field_name && data.respond_to?(Dev::Jira.config.points_field_name)
|
23
84
|
|
24
85
|
0
|
@@ -22,8 +22,10 @@ module Dev
|
|
22
22
|
# Returns the Jira user object which maps to the give user id
|
23
23
|
# If none is found, it returns a Jira user object with only the id set
|
24
24
|
def self.lookup(id)
|
25
|
+
id = id.to_s.strip
|
26
|
+
id = 'notfound' if id.empty?
|
25
27
|
user = Dev::Jira.config.user_lookup_list&.find { |it| it.id == id }
|
26
|
-
user ||= new(name: '', email: '', id:)
|
28
|
+
user ||= new(name: 'Not Found', email: 'notfound@notfound.com', id:)
|
27
29
|
user
|
28
30
|
end
|
29
31
|
end
|
@@ -9,12 +9,13 @@ module Dev
|
|
9
9
|
# "user_lookup_list" should be an array of Jira::User objects representing the usernames, ids, etc for all jira users
|
10
10
|
# This is a bit clumsy but currently the jira api only returns the user id with issues
|
11
11
|
# and there is no way to query this information from Jira directly.
|
12
|
-
Config = Struct.new(:username, :token, :url, :points_field_name, :user_lookup_list, :read_timeout, :http_debug) do
|
12
|
+
Config = Struct.new(:username, :token, :url, :points_field_name, :expand, :user_lookup_list, :read_timeout, :http_debug) do
|
13
13
|
def initialize
|
14
14
|
self.username = nil
|
15
15
|
self.token = nil
|
16
16
|
self.url = nil
|
17
17
|
self.points_field_name = nil
|
18
|
+
self.expand = []
|
18
19
|
self.user_lookup_list = []
|
19
20
|
self.read_timeout = 120
|
20
21
|
self.http_debug = false
|
@@ -62,15 +63,16 @@ module Dev
|
|
62
63
|
def issues(jql, &)
|
63
64
|
start_at = 0
|
64
65
|
max_results = 100
|
66
|
+
expand = self.class.config.expand
|
65
67
|
|
66
68
|
# Query Jira and yield all issues it returns
|
67
|
-
issues = @client.Issue.jql(jql, start_at:, max_results:)
|
69
|
+
issues = @client.Issue.jql(jql, start_at:, max_results:, expand:)
|
68
70
|
issues.map { |data| Issue.new(data) }.each(&)
|
69
71
|
|
70
72
|
# If we returned the max_results then there may be more - add the max results to where we start at and query again
|
71
73
|
while issues.length >= max_results
|
72
74
|
start_at += max_results
|
73
|
-
issues = @client.Issue.jql(jql, start_at:, max_results:)
|
75
|
+
issues = @client.Issue.jql(jql, start_at:, max_results:, expand:)
|
74
76
|
issues.map { |data| Issue.new(data) }.each(&)
|
75
77
|
end
|
76
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: firespring_dev_commands
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.7.pre.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Firespring
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -284,6 +284,8 @@ files:
|
|
284
284
|
- lib/firespring_dev_commands/git.rb
|
285
285
|
- lib/firespring_dev_commands/git/info.rb
|
286
286
|
- lib/firespring_dev_commands/jira.rb
|
287
|
+
- lib/firespring_dev_commands/jira/histories.rb
|
288
|
+
- lib/firespring_dev_commands/jira/history.rb
|
287
289
|
- lib/firespring_dev_commands/jira/issue.rb
|
288
290
|
- lib/firespring_dev_commands/jira/project.rb
|
289
291
|
- lib/firespring_dev_commands/jira/user.rb
|