firespring_dev_commands 2.1.7 → 2.1.10.pre.alpha.1
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/common.rb +1 -1
- data/lib/firespring_dev_commands/git.rb +29 -7
- data/lib/firespring_dev_commands/target_process/project.rb +13 -0
- data/lib/firespring_dev_commands/target_process/query.rb +70 -0
- data/lib/firespring_dev_commands/target_process/release.rb +13 -0
- data/lib/firespring_dev_commands/target_process/team.rb +13 -0
- data/lib/firespring_dev_commands/target_process/user.rb +14 -0
- data/lib/firespring_dev_commands/target_process/user_story.rb +45 -0
- data/lib/firespring_dev_commands/target_process.rb +101 -0
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5d6f684466e6dde383089a4206db4858b6aa353cf2160a26209a57406048e67
|
4
|
+
data.tar.gz: 72b604e125b342ac714ee18099af6474b96e248002ca6b6869ebe18df51e01c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 499014ee023457b5981445bfe2334b3749bffc705e27c5359c79ead81d8a794f1aabb4ce85878da108fa2bdb6d5c4b25cba6c8945c7abd1e62a8d0040f725059
|
7
|
+
data.tar.gz: a1c35a8c9015ebe42e0cd5882ffe3585cda6389af35fdedb5f711c2f2187466e85c99c5cb00f659685b28b815d97cb014d99afc457e8608c2beabcdbdca39e60
|
@@ -41,7 +41,7 @@ module Dev
|
|
41
41
|
# If the user answers 'y' then the block is executed.
|
42
42
|
# If the user answers 'n' then the block is skipped.
|
43
43
|
def with_confirmation(message, default = 'y', color_message: true)
|
44
|
-
message = "\n #{message}?
|
44
|
+
message = "\n #{message}" << '? '.light_green
|
45
45
|
message = message.light_green if color_message
|
46
46
|
print message
|
47
47
|
print '('.light_green << 'y'.light_yellow << '/'.light_green << 'n'.light_yellow << ') '.light_green
|
@@ -203,7 +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
|
-
def checkout(branch, dir: default_project_dir)
|
206
|
+
def checkout(branch, dir: default_project_dir, raise_errors: false)
|
207
207
|
raise 'branch is required' if branch.to_s.strip.empty?
|
208
208
|
return unless File.exist?(dir)
|
209
209
|
|
@@ -224,12 +224,14 @@ module Dev
|
|
224
224
|
indent g.pull('origin', actual_branch)
|
225
225
|
true
|
226
226
|
rescue ::Git::GitExecuteError => e
|
227
|
+
raise e if raise_errors
|
228
|
+
|
227
229
|
print_errors(e.message)
|
228
230
|
false
|
229
231
|
end
|
230
232
|
|
231
233
|
# Create the given branch in the given repo
|
232
|
-
def create_branch(branch, dir: default_project_dir)
|
234
|
+
def create_branch(branch, dir: default_project_dir, raise_errors: false)
|
233
235
|
raise 'branch is required' if branch.to_s.strip.empty?
|
234
236
|
raise "refusing to create protected branch '#{branch}'" if %w(master develop).any?(branch.to_s.strip)
|
235
237
|
return unless File.exist?(dir)
|
@@ -240,7 +242,7 @@ module Dev
|
|
240
242
|
g = ::Git.open(dir)
|
241
243
|
g.fetch('origin', prune: true)
|
242
244
|
|
243
|
-
puts "Fetching the latest changes for base branch #{staging_branch}"
|
245
|
+
puts "Fetching the latest changes for base branch \"#{staging_branch}\""
|
244
246
|
g.checkout(staging_branch)
|
245
247
|
g.pull('origin', staging_branch)
|
246
248
|
|
@@ -251,6 +253,19 @@ module Dev
|
|
251
253
|
g.config("branch.#{branch}.merge", "refs/heads/#{branch}")
|
252
254
|
puts
|
253
255
|
rescue ::Git::GitExecuteError => e
|
256
|
+
raise e if raise_errors
|
257
|
+
|
258
|
+
print_errors(e.message)
|
259
|
+
false
|
260
|
+
end
|
261
|
+
|
262
|
+
def add(*paths, dir: default_project_dir, raise_errors: false)
|
263
|
+
g = ::Git.open(dir)
|
264
|
+
indent g.add(paths)
|
265
|
+
true
|
266
|
+
rescue ::Git::GitExecuteError => e
|
267
|
+
raise e if raise_errors
|
268
|
+
|
254
269
|
print_errors(e.message)
|
255
270
|
false
|
256
271
|
end
|
@@ -277,7 +292,7 @@ module Dev
|
|
277
292
|
end
|
278
293
|
|
279
294
|
# Merge the given branch into the given repo
|
280
|
-
def merge(branch, dir: default_project_dir)
|
295
|
+
def merge(branch, dir: default_project_dir, raise_errors: false)
|
281
296
|
raise 'branch is required' if branch.to_s.strip.empty?
|
282
297
|
return unless File.exist?(dir)
|
283
298
|
|
@@ -296,6 +311,8 @@ module Dev
|
|
296
311
|
indent g.merge(branch)
|
297
312
|
true
|
298
313
|
rescue ::Git::GitExecuteError => e
|
314
|
+
raise e if raise_errors
|
315
|
+
|
299
316
|
print_errors(e.message)
|
300
317
|
false
|
301
318
|
end
|
@@ -320,7 +337,7 @@ module Dev
|
|
320
337
|
end
|
321
338
|
|
322
339
|
# Pull the given repo
|
323
|
-
def pull(dir: default_project_dir)
|
340
|
+
def pull(dir: default_project_dir, raise_errors: false)
|
324
341
|
return unless File.exist?(dir)
|
325
342
|
|
326
343
|
g = ::Git.open(dir)
|
@@ -331,6 +348,8 @@ module Dev
|
|
331
348
|
indent g.pull('origin', branch)
|
332
349
|
true
|
333
350
|
rescue ::Git::GitExecuteError => e
|
351
|
+
raise e if raise_errors
|
352
|
+
|
334
353
|
print_errors(e.message)
|
335
354
|
false
|
336
355
|
end
|
@@ -355,7 +374,7 @@ module Dev
|
|
355
374
|
end
|
356
375
|
|
357
376
|
# Push the given repo
|
358
|
-
def push(dir: default_project_dir)
|
377
|
+
def push(dir: default_project_dir, raise_errors: false)
|
359
378
|
return unless File.exist?(dir)
|
360
379
|
|
361
380
|
g = ::Git.open(dir)
|
@@ -366,6 +385,8 @@ module Dev
|
|
366
385
|
indent g.push('origin', branch)
|
367
386
|
true
|
368
387
|
rescue ::Git::GitExecuteError => e
|
388
|
+
raise e if raise_errors
|
389
|
+
|
369
390
|
print_errors(e.message)
|
370
391
|
false
|
371
392
|
end
|
@@ -378,7 +399,7 @@ module Dev
|
|
378
399
|
# Clones the repo_name into the dir
|
379
400
|
# Optionally specify a repo_org
|
380
401
|
# 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)
|
402
|
+
def clone_repo(dir:, repo_name:, repo_org: 'firespring', branch: nil, depth: nil)
|
382
403
|
if Dir.exist?("#{dir}/.git")
|
383
404
|
puts "#{dir} already cloned".light_green
|
384
405
|
return
|
@@ -390,6 +411,7 @@ module Dev
|
|
390
411
|
|
391
412
|
opts = {}
|
392
413
|
opts[:branch] = branch unless branch.to_s.strip.empty?
|
414
|
+
opts[:depth] = depth unless depth.to_s.strip.empty?
|
393
415
|
g = ::Git.clone(ssh_repo_url(repo_name, repo_org), dir, opts)
|
394
416
|
g.fetch('origin', prune: true)
|
395
417
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Dev
|
2
|
+
class TargetProcess
|
3
|
+
class Query
|
4
|
+
attr_accessor :where, :incl, :take
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@where = []
|
8
|
+
@incl = []
|
9
|
+
@take = 250
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(item)
|
13
|
+
where << item
|
14
|
+
end
|
15
|
+
|
16
|
+
def where=(item)
|
17
|
+
if item.is_a?(Array)
|
18
|
+
where.concat(item)
|
19
|
+
else
|
20
|
+
where << item
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def include=(item)
|
25
|
+
if item.is_a?(Array)
|
26
|
+
incl.concat(item)
|
27
|
+
else
|
28
|
+
incl << item
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate
|
33
|
+
{}.tap do |clause|
|
34
|
+
clause[:where] = where.join(' and ') unless where.nil? || where.empty?
|
35
|
+
clause[:include] = "[#{incl.join(',')}]" unless incl.nil? || incl.empty?
|
36
|
+
clause[:take] = take if take.to_i.positive?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
generate
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_by_user_story_ids(user_story_ids)
|
45
|
+
self << "(Id in ('#{user_story_ids.join("', '")}'))"
|
46
|
+
end
|
47
|
+
|
48
|
+
def filter_by_project(projects)
|
49
|
+
self << "(Project.Name in ('#{projects.join("', '")}'))"
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter_by_states(states)
|
53
|
+
self << "(EntityState.Name in ('#{states.join("', '")}'))" unless states.nil? || states.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def filter_by_final
|
57
|
+
self << "(EntityState.IsFinal eq 'true')"
|
58
|
+
end
|
59
|
+
|
60
|
+
def filter_by_end_dates(start_date, end_date)
|
61
|
+
self << "(EndDate gt '#{start_date}')" if start_date
|
62
|
+
self << "(EndDate lt '#{end_date}')" if end_date
|
63
|
+
end
|
64
|
+
|
65
|
+
def filter_by_missing_tests
|
66
|
+
self << '(LinkedTestPlan is nil)'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Dev
|
2
|
+
class TargetProcess
|
3
|
+
class UserStory
|
4
|
+
PATH = '/UserStories'.freeze
|
5
|
+
|
6
|
+
attr_accessor :type, :id, :name, :description, :start_date, :end_date, :create_date, :modify_date, :tags, :effort, :time_spent, :last_state_change_date, :project,
|
7
|
+
:owner, :creator, :release, :team, :priority, :state, :original_data
|
8
|
+
|
9
|
+
def initialize(data)
|
10
|
+
@id = data['Id']
|
11
|
+
@type = data['ResourceType']
|
12
|
+
@name = data['Name']
|
13
|
+
@description = data['Description']
|
14
|
+
@state = data['EntityState']['Name']
|
15
|
+
@project = Project.new(data['Project']) if data['Project']
|
16
|
+
@owner = User.new(data['Owner']) if data['Owner']
|
17
|
+
@creator = User.new(data['Creator']) if data['Creator']
|
18
|
+
@release = Release.new(data['Release']) if data['Release']
|
19
|
+
@team = Team.new(data['Team']) if data['Team']
|
20
|
+
@start_date = parse_time(data['StartDate'])
|
21
|
+
@end_date = parse_time(data['EndDate'])
|
22
|
+
@create_date = parse_time(data['CreateDate'])
|
23
|
+
@modify_date = parse_time(data['ModifyDate'])
|
24
|
+
@tags = data['Tags']
|
25
|
+
@effort = data['Effort']
|
26
|
+
@time_spent = data['TimeSpent']
|
27
|
+
@last_state_change_date = parse_time(data['LastStateChangeDate'])
|
28
|
+
@original_data = original_data
|
29
|
+
end
|
30
|
+
|
31
|
+
# Parse the dot net time representation into something that ruby can use
|
32
|
+
def parse_time(string)
|
33
|
+
return nil unless string && !string.empty?
|
34
|
+
|
35
|
+
Time.at(string.slice(6, 10).to_i)
|
36
|
+
end
|
37
|
+
|
38
|
+
def cycle_time
|
39
|
+
return 1.0 unless start_date && end_date
|
40
|
+
|
41
|
+
(end_date - start_date).to_f
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Dev
|
4
|
+
class TargetProcess
|
5
|
+
CONFIG_FILE = "#{Dir.home}/.env.tp".freeze
|
6
|
+
|
7
|
+
TP_USERNAME = 'TP_USERNAME'.freeze
|
8
|
+
|
9
|
+
TP_PASSWORD = 'TP_PASSWORD'.freeze
|
10
|
+
|
11
|
+
TP_URL = 'TP_URL'.freeze
|
12
|
+
|
13
|
+
Config = Struct.new(:username, :password, :url, :http_debug) do
|
14
|
+
def initialize
|
15
|
+
Dotenv.load(CONFIG_FILE) if File.exist?(CONFIG_FILE)
|
16
|
+
|
17
|
+
self.username = ENV.fetch(TP_USERNAME, nil)
|
18
|
+
self.password = ENV.fetch(TP_PASSWORD, nil)
|
19
|
+
self.url = ENV.fetch(TP_URL, nil)
|
20
|
+
self.http_debug = false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# Instantiates a new top level config object if one hasn't already been created
|
26
|
+
# Yields that config object to any given block
|
27
|
+
# Returns the resulting config object
|
28
|
+
def config
|
29
|
+
@config ||= Config.new
|
30
|
+
yield(@config) if block_given?
|
31
|
+
@config
|
32
|
+
end
|
33
|
+
|
34
|
+
# Alias the config method to configure for a slightly clearer access syntax
|
35
|
+
alias_method :configure, :config
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :username, :password, :url, :auth, :client, :headers
|
39
|
+
|
40
|
+
# Initialize a new jira client using the given inputs
|
41
|
+
def initialize(username: self.class.config.username, password: self.class.config.password, url: self.class.config.url)
|
42
|
+
@username = username
|
43
|
+
@password = password
|
44
|
+
@auth = Base64.strict_encode64("#{@username}:#{@password}")
|
45
|
+
@url = url
|
46
|
+
uri = URI.parse(@url)
|
47
|
+
@client = Net::HTTP.new(uri.host, uri.port)
|
48
|
+
@client.use_ssl = true
|
49
|
+
@client.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
50
|
+
@client.set_debug_output(LOG) if self.class.config.http_debug
|
51
|
+
@headers = {
|
52
|
+
'authorization' => "Basic #{auth}",
|
53
|
+
'content-type' => 'application/json',
|
54
|
+
'accept' => 'application/json'
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def user_stories(query, &)
|
59
|
+
[].tap do |ary|
|
60
|
+
get(UserStory::PATH, query) do |result|
|
61
|
+
ary << UserStory.new(result)
|
62
|
+
end
|
63
|
+
ary.each(&)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get(path, query, &)
|
68
|
+
query_string = query.generate
|
69
|
+
url = "/api/v1/#{path}"
|
70
|
+
url << "?#{URI.encode_www_form(query_string)}" unless query_string.empty?
|
71
|
+
|
72
|
+
response = client.request_get(url, headers)
|
73
|
+
raise "Error querying #{url} [#{query_string}]: #{response.inspect}" unless response.response.is_a?(Net::HTTPSuccess)
|
74
|
+
|
75
|
+
parsed_response = JSON.parse(response.body)
|
76
|
+
return parsed_response unless parsed_response.key?('Items')
|
77
|
+
|
78
|
+
parsed_response['Items'].each(&)
|
79
|
+
|
80
|
+
while parsed_response['Next']
|
81
|
+
response = client.request_get(parsed_response['Next'], headers)
|
82
|
+
raise "Error querying #{parsed_response['Next']} [#{query_string}]: #{response.inspect}" unless response.response.is_a?(Net::HTTPSuccess)
|
83
|
+
|
84
|
+
parsed_response = JSON.parse(response.body)
|
85
|
+
return parsed_response unless parsed_response.key?('Items')
|
86
|
+
|
87
|
+
parsed_response['Items'].each(&)
|
88
|
+
end
|
89
|
+
|
90
|
+
nil
|
91
|
+
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
|
+
end
|
101
|
+
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.10.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-
|
11
|
+
date: 2023-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 7.
|
19
|
+
version: 7.1.1
|
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: 7.
|
26
|
+
version: 7.1.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: aws-sdk-cloudformation
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -305,6 +305,13 @@ files:
|
|
305
305
|
- lib/firespring_dev_commands/tar.rb
|
306
306
|
- lib/firespring_dev_commands/tar/pax_header.rb
|
307
307
|
- lib/firespring_dev_commands/tar/type_flag.rb
|
308
|
+
- lib/firespring_dev_commands/target_process.rb
|
309
|
+
- lib/firespring_dev_commands/target_process/project.rb
|
310
|
+
- lib/firespring_dev_commands/target_process/query.rb
|
311
|
+
- lib/firespring_dev_commands/target_process/release.rb
|
312
|
+
- lib/firespring_dev_commands/target_process/team.rb
|
313
|
+
- lib/firespring_dev_commands/target_process/user.rb
|
314
|
+
- lib/firespring_dev_commands/target_process/user_story.rb
|
308
315
|
- lib/firespring_dev_commands/templates/aws.rb
|
309
316
|
- lib/firespring_dev_commands/templates/base_interface.rb
|
310
317
|
- lib/firespring_dev_commands/templates/ci.rb
|
@@ -333,9 +340,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
333
340
|
version: '3.1'
|
334
341
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
335
342
|
requirements:
|
336
|
-
- - "
|
343
|
+
- - ">"
|
337
344
|
- !ruby/object:Gem::Version
|
338
|
-
version:
|
345
|
+
version: 1.3.1
|
339
346
|
requirements: []
|
340
347
|
rubygems_version: 3.4.10
|
341
348
|
signing_key:
|