firespring_dev_commands 2.1.10.pre.alpha.1 → 2.1.10.pre.alpha.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/firespring_dev_commands/git.rb +12 -0
- data/lib/firespring_dev_commands/jira/histories.rb +2 -0
- data/lib/firespring_dev_commands/jira/history.rb +1 -0
- data/lib/firespring_dev_commands/jira/issue.rb +6 -0
- data/lib/firespring_dev_commands/platform.rb +6 -2
- data/lib/firespring_dev_commands/target_process/project.rb +1 -0
- data/lib/firespring_dev_commands/target_process/query.rb +12 -0
- data/lib/firespring_dev_commands/target_process/release.rb +1 -0
- data/lib/firespring_dev_commands/target_process/team.rb +1 -0
- data/lib/firespring_dev_commands/target_process/user.rb +1 -0
- data/lib/firespring_dev_commands/target_process/user_story.rb +4 -1
- data/lib/firespring_dev_commands/target_process.rb +13 -9
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eebfafcc2e64ee029e9ec478bf7d3ab53167f024eafdd581458cda045927587
|
4
|
+
data.tar.gz: 71c135fe88993700199eede29e0ac56fb66735cd4511536d289bb686c5dbbb56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fb3b21aee7a97d1c39dcb0a7837f5494d154d5be63f3851cdfd5a3751a36c165d4e617cc1771f53d45c5a7e0bdc9ee92f3c7ea6a29087c40959b71990c3616d
|
7
|
+
data.tar.gz: 537f2e499353e108a7ebaa8b97f40b69dc883978625ff779a2769e71e1a640ffa300ebe926a2d383e8749834cdc42b15c4434b073085c0309fdc6158f0842c3c
|
@@ -203,6 +203,7 @@ module Dev
|
|
203
203
|
|
204
204
|
# Checks out the given branch in the given repo
|
205
205
|
# Defaults to the current directory
|
206
|
+
# optionally raise errors
|
206
207
|
def checkout(branch, dir: default_project_dir, raise_errors: false)
|
207
208
|
raise 'branch is required' if branch.to_s.strip.empty?
|
208
209
|
return unless File.exist?(dir)
|
@@ -231,6 +232,8 @@ module Dev
|
|
231
232
|
end
|
232
233
|
|
233
234
|
# Create the given branch in the given repo
|
235
|
+
# Defaults to the current directory
|
236
|
+
# optionally raise errors
|
234
237
|
def create_branch(branch, dir: default_project_dir, raise_errors: false)
|
235
238
|
raise 'branch is required' if branch.to_s.strip.empty?
|
236
239
|
raise "refusing to create protected branch '#{branch}'" if %w(master develop).any?(branch.to_s.strip)
|
@@ -259,6 +262,9 @@ module Dev
|
|
259
262
|
false
|
260
263
|
end
|
261
264
|
|
265
|
+
# Add the given paths to git
|
266
|
+
# Defaults to the current directory
|
267
|
+
# optionally raise errors
|
262
268
|
def add(*paths, dir: default_project_dir, raise_errors: false)
|
263
269
|
g = ::Git.open(dir)
|
264
270
|
indent g.add(paths)
|
@@ -292,6 +298,8 @@ module Dev
|
|
292
298
|
end
|
293
299
|
|
294
300
|
# Merge the given branch into the given repo
|
301
|
+
# Defaults to the current directory
|
302
|
+
# optionally raise errors
|
295
303
|
def merge(branch, dir: default_project_dir, raise_errors: false)
|
296
304
|
raise 'branch is required' if branch.to_s.strip.empty?
|
297
305
|
return unless File.exist?(dir)
|
@@ -337,6 +345,8 @@ module Dev
|
|
337
345
|
end
|
338
346
|
|
339
347
|
# Pull the given repo
|
348
|
+
# Defaults to the current directory
|
349
|
+
# optionally raise errors
|
340
350
|
def pull(dir: default_project_dir, raise_errors: false)
|
341
351
|
return unless File.exist?(dir)
|
342
352
|
|
@@ -374,6 +384,8 @@ module Dev
|
|
374
384
|
end
|
375
385
|
|
376
386
|
# Push the given repo
|
387
|
+
# Defaults to the current directory
|
388
|
+
# optionally raise errors
|
377
389
|
def push(dir: default_project_dir, raise_errors: false)
|
378
390
|
return unless File.exist?(dir)
|
379
391
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Dev
|
2
2
|
class Jira
|
3
|
+
# Class which provides a helper method for converting the changelog data to history objects
|
3
4
|
class Histories
|
5
|
+
# If changelog is present in the given data, return an array of history objects for each changelog entry
|
4
6
|
def self.populate(data)
|
5
7
|
return nil unless data.attrs.key?('changelog')
|
6
8
|
|
@@ -21,21 +21,25 @@ module Dev
|
|
21
21
|
@last_closed_history = nil
|
22
22
|
end
|
23
23
|
|
24
|
+
# Returns the cycle time of the issue (time between in progress and closed states)
|
24
25
|
def cycle_time
|
25
26
|
# Calculate the difference and convert to days
|
26
27
|
((last_closed_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
|
27
28
|
end
|
28
29
|
|
30
|
+
# Returns the time the issue was in progress (time between in progress and in review states)
|
29
31
|
def in_progress_cycle_time
|
30
32
|
# Calculate the difference and convert to days
|
31
33
|
((first_in_review_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
|
32
34
|
end
|
33
35
|
|
36
|
+
# Returns the time the issue was in review (time between in review and closed states)
|
34
37
|
def in_review_cycle_time
|
35
38
|
# Calculate the difference and convert to days
|
36
39
|
((last_closed_history.created - first_in_review_history.created) / 60 / 60 / 24).round(2)
|
37
40
|
end
|
38
41
|
|
42
|
+
# Loop through the issue history and find the most recent state change from Open to In Progress
|
39
43
|
private def last_in_progress_history
|
40
44
|
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
41
45
|
|
@@ -50,6 +54,7 @@ module Dev
|
|
50
54
|
@last_in_progress_history
|
51
55
|
end
|
52
56
|
|
57
|
+
# Loop through the issue history and find the oldest state change to In Review
|
53
58
|
private def first_in_review_history
|
54
59
|
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
55
60
|
|
@@ -64,6 +69,7 @@ module Dev
|
|
64
69
|
@first_in_review_history
|
65
70
|
end
|
66
71
|
|
72
|
+
# Loop through the issue history and find the most recent state change to closed
|
67
73
|
private def last_closed_history
|
68
74
|
raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
|
69
75
|
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module Dev
|
2
2
|
class Common
|
3
|
+
# Class which returns information about the current platform
|
3
4
|
class Platform
|
5
|
+
# Constant containing all supported architectures
|
4
6
|
ALLOWED_ARCHITECTURES = %w(arm64 amd64).freeze
|
5
7
|
|
8
|
+
# Normalize the ruby platform to return a docker platform architecture format
|
6
9
|
def determine_compute_architecture
|
7
10
|
case RUBY_PLATFORM
|
8
11
|
when /x86_64|amd64/
|
@@ -14,6 +17,9 @@ module Dev
|
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
20
|
+
# Determine the platform architecture
|
21
|
+
# If one was specified in the DOCKER_ARCHITECTURE variable, use it
|
22
|
+
# Otherwise, use the RUBY_PLATFORM built-in to auto-detect and architecture
|
17
23
|
def architecture
|
18
24
|
docker_architecture = ENV['DOCKER_ARCHITECTURE'].to_s.strip.downcase
|
19
25
|
if docker_architecture.empty?
|
@@ -22,13 +28,11 @@ module Dev
|
|
22
28
|
raise "Missing 'linux/' prefix in DOCKER_ARCHITECTURE: #{docker_architecture}" unless docker_architecture.start_with?('linux/')
|
23
29
|
|
24
30
|
architecture_name = docker_architecture.split('/')[1]
|
25
|
-
|
26
31
|
unless ALLOWED_ARCHITECTURES.include?(architecture_name)
|
27
32
|
raise "Invalid DOCKER_ARCHITECTURE: #{architecture_name}. Allowed architectures are #{ALLOWED_ARCHITECTURES.join(', ')}"
|
28
33
|
end
|
29
34
|
|
30
35
|
docker_architecture
|
31
|
-
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Dev
|
2
2
|
class TargetProcess
|
3
|
+
# Class for writing target process query statements
|
3
4
|
class Query
|
4
5
|
attr_accessor :where, :incl, :take
|
5
6
|
|
@@ -9,10 +10,12 @@ module Dev
|
|
9
10
|
@take = 250
|
10
11
|
end
|
11
12
|
|
13
|
+
# Add a new query clause
|
12
14
|
def <<(item)
|
13
15
|
where << item
|
14
16
|
end
|
15
17
|
|
18
|
+
# Add the item to the where clause
|
16
19
|
def where=(item)
|
17
20
|
if item.is_a?(Array)
|
18
21
|
where.concat(item)
|
@@ -21,6 +24,7 @@ module Dev
|
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
27
|
+
# Add the item to the include clause
|
24
28
|
def include=(item)
|
25
29
|
if item.is_a?(Array)
|
26
30
|
incl.concat(item)
|
@@ -29,6 +33,7 @@ module Dev
|
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
36
|
+
# Generate the string representation for this query
|
32
37
|
def generate
|
33
38
|
{}.tap do |clause|
|
34
39
|
clause[:where] = where.join(' and ') unless where.nil? || where.empty?
|
@@ -37,31 +42,38 @@ module Dev
|
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
45
|
+
# Generate the string representation for this query
|
40
46
|
def to_s
|
41
47
|
generate
|
42
48
|
end
|
43
49
|
|
50
|
+
# Add a filter that looks for stories whose id is contained in the list of ids given
|
44
51
|
def filter_by_user_story_ids(user_story_ids)
|
45
52
|
self << "(Id in ('#{user_story_ids.join("', '")}'))"
|
46
53
|
end
|
47
54
|
|
55
|
+
# Add a filter that looks for stories whose project id is contained in the list of ids given
|
48
56
|
def filter_by_project(projects)
|
49
57
|
self << "(Project.Name in ('#{projects.join("', '")}'))"
|
50
58
|
end
|
51
59
|
|
60
|
+
# Add a filter that looks for stories whose state is contained in the list of states given
|
52
61
|
def filter_by_states(states)
|
53
62
|
self << "(EntityState.Name in ('#{states.join("', '")}'))" unless states.nil? || states.empty?
|
54
63
|
end
|
55
64
|
|
65
|
+
# Add a filter that looks for stories whose state is set to final
|
56
66
|
def filter_by_final
|
57
67
|
self << "(EntityState.IsFinal eq 'true')"
|
58
68
|
end
|
59
69
|
|
70
|
+
# Add a filter that looks for stories whose end date is between the given dates
|
60
71
|
def filter_by_end_dates(start_date, end_date)
|
61
72
|
self << "(EndDate gt '#{start_date}')" if start_date
|
62
73
|
self << "(EndDate lt '#{end_date}')" if end_date
|
63
74
|
end
|
64
75
|
|
76
|
+
# Add a filter that looks for stories which do not have a linked test plan
|
65
77
|
def filter_by_missing_tests
|
66
78
|
self << '(LinkedTestPlan is nil)'
|
67
79
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Dev
|
2
2
|
class TargetProcess
|
3
|
+
# Class containing user story information
|
3
4
|
class UserStory
|
5
|
+
# The api path for user story requests
|
4
6
|
PATH = '/UserStories'.freeze
|
5
7
|
|
6
8
|
attr_accessor :type, :id, :name, :description, :start_date, :end_date, :create_date, :modify_date, :tags, :effort, :time_spent, :last_state_change_date, :project,
|
@@ -35,10 +37,11 @@ module Dev
|
|
35
37
|
Time.at(string.slice(6, 10).to_i)
|
36
38
|
end
|
37
39
|
|
40
|
+
# Calculate the cycle time as the amount of time the story was open
|
38
41
|
def cycle_time
|
39
42
|
return 1.0 unless start_date && end_date
|
40
43
|
|
41
|
-
(end_date - start_date).to_f
|
44
|
+
(end_date - start_date).to_f / (60 * 60 * 24)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
@@ -1,15 +1,21 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
3
|
module Dev
|
4
|
+
# Class for querying target process data from their api
|
4
5
|
class TargetProcess
|
6
|
+
# The config file to try to load credentials from
|
5
7
|
CONFIG_FILE = "#{Dir.home}/.env.tp".freeze
|
6
8
|
|
9
|
+
# The text of the username variable key
|
7
10
|
TP_USERNAME = 'TP_USERNAME'.freeze
|
8
11
|
|
12
|
+
# The text of the password variable key
|
9
13
|
TP_PASSWORD = 'TP_PASSWORD'.freeze
|
10
14
|
|
15
|
+
# The text of the url variable key
|
11
16
|
TP_URL = 'TP_URL'.freeze
|
12
17
|
|
18
|
+
# Config object for setting top level jira config options
|
13
19
|
Config = Struct.new(:username, :password, :url, :http_debug) do
|
14
20
|
def initialize
|
15
21
|
Dotenv.load(CONFIG_FILE) if File.exist?(CONFIG_FILE)
|
@@ -37,7 +43,7 @@ module Dev
|
|
37
43
|
|
38
44
|
attr_accessor :username, :password, :url, :auth, :client, :headers
|
39
45
|
|
40
|
-
# Initialize a new
|
46
|
+
# Initialize a new target process client using the given inputs
|
41
47
|
def initialize(username: self.class.config.username, password: self.class.config.password, url: self.class.config.url)
|
42
48
|
@username = username
|
43
49
|
@password = password
|
@@ -55,6 +61,9 @@ module Dev
|
|
55
61
|
}
|
56
62
|
end
|
57
63
|
|
64
|
+
# Perform a query to the user story api path
|
65
|
+
# Call the given block (if present) with each user story
|
66
|
+
# Return all user stories
|
58
67
|
def user_stories(query, &)
|
59
68
|
[].tap do |ary|
|
60
69
|
get(UserStory::PATH, query) do |result|
|
@@ -64,6 +73,9 @@ module Dev
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
76
|
+
# Perform a get request to the given path using the given query
|
77
|
+
# Call the given block (if present) with each piece of data
|
78
|
+
# Return all pieces of data
|
67
79
|
def get(path, query, &)
|
68
80
|
query_string = query.generate
|
69
81
|
url = "/api/v1/#{path}"
|
@@ -89,13 +101,5 @@ module Dev
|
|
89
101
|
|
90
102
|
nil
|
91
103
|
end
|
92
|
-
|
93
|
-
def self.parse_dot_net_time(string)
|
94
|
-
Time.at(string.slice(6, 10).to_i)
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.parse_dot_net_date(string)
|
98
|
-
parse_dot_net_time(string).to_date
|
99
|
-
end
|
100
104
|
end
|
101
105
|
end
|