abide_dev_utils 0.16.1 → 0.17.0
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/Gemfile.lock +7 -4
- data/abide_dev_utils.gemspec +2 -2
- data/lib/abide_dev_utils/cem/generate/reference.rb +13 -3
- data/lib/abide_dev_utils/cli/jira.rb +38 -31
- data/lib/abide_dev_utils/jira/client.rb +65 -0
- data/lib/abide_dev_utils/jira/client_builder.rb +107 -0
- data/lib/abide_dev_utils/jira/dry_run.rb +133 -0
- data/lib/abide_dev_utils/jira/finder.rb +62 -0
- data/lib/abide_dev_utils/jira/helper.rb +41 -0
- data/lib/abide_dev_utils/jira/issue_builder.rb +110 -0
- data/lib/abide_dev_utils/jira.rb +37 -162
- data/lib/abide_dev_utils/version.rb +1 -1
- metadata +15 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0216511efe504da6597b81a7b494975377b8afe013697e37f9985467a6a4fa14
|
4
|
+
data.tar.gz: '08265323331b31cb17e875b951ce89dfcb83bbb9649c0df97513cff26355f713'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cbd439058affe3311587d81d4dfe75191abe9f9fb1a1f8c964c2a8187f02cf9057943e4bacd5aaeb1676c936cccdd5e196b9d4a0822ed0c725d06fe0c46f0d3
|
7
|
+
data.tar.gz: f01c66b8079d9d257de1158f4a1f9f529b2e9e31c8eb04a19fa21fee63f34b2fa018b8e3bba8eefce2bf90d20f23249e27a83126f54057232aef6bd7658cbe0a
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
abide_dev_utils (0.
|
4
|
+
abide_dev_utils (0.17.0)
|
5
5
|
cmdparse (~> 3.0)
|
6
6
|
facterdb (>= 1.21)
|
7
7
|
google-cloud-storage (~> 1.34)
|
8
8
|
hashdiff (~> 1.0)
|
9
9
|
jira-ruby (~> 2.2)
|
10
10
|
nokogiri (~> 1.13)
|
11
|
-
puppet (>=
|
11
|
+
puppet (>= 7.0.0)
|
12
12
|
puppet-strings (>= 2.7)
|
13
13
|
ruby-progressbar (~> 1.11)
|
14
14
|
selenium-webdriver (~> 4.0.0.beta4)
|
@@ -69,7 +69,7 @@ GEM
|
|
69
69
|
faraday-http-cache (2.3.0)
|
70
70
|
faraday (>= 0.8)
|
71
71
|
faraday-net_http (2.0.3)
|
72
|
-
fast_gettext (
|
72
|
+
fast_gettext (2.3.0)
|
73
73
|
fiber-local (1.0.0)
|
74
74
|
gem-release (2.2.2)
|
75
75
|
github_changelog_generator (1.16.4)
|
@@ -137,6 +137,8 @@ GEM
|
|
137
137
|
multi_json (1.15.0)
|
138
138
|
multipart-post (2.3.0)
|
139
139
|
nio4r (2.5.8)
|
140
|
+
nokogiri (1.15.2-arm64-darwin)
|
141
|
+
racc (~> 1.4)
|
140
142
|
nokogiri (1.15.2-x86_64-darwin)
|
141
143
|
racc (~> 1.4)
|
142
144
|
nokogiri (1.15.2-x86_64-linux)
|
@@ -265,6 +267,7 @@ GEM
|
|
265
267
|
yard (0.9.34)
|
266
268
|
|
267
269
|
PLATFORMS
|
270
|
+
arm64-darwin-22
|
268
271
|
x86_64-darwin-19
|
269
272
|
x86_64-darwin-20
|
270
273
|
x86_64-linux
|
@@ -273,7 +276,7 @@ DEPENDENCIES
|
|
273
276
|
abide_dev_utils!
|
274
277
|
bundler
|
275
278
|
console
|
276
|
-
fast_gettext (
|
279
|
+
fast_gettext (>= 2.0)
|
277
280
|
gem-release
|
278
281
|
github_changelog_generator
|
279
282
|
pry
|
data/abide_dev_utils.gemspec
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
# Prod dependencies
|
35
35
|
spec.add_dependency 'nokogiri', '~> 1.13'
|
36
36
|
spec.add_dependency 'cmdparse', '~> 3.0'
|
37
|
-
spec.add_dependency 'puppet', '>=
|
37
|
+
spec.add_dependency 'puppet', '>= 7.0.0'
|
38
38
|
spec.add_dependency 'puppet-strings', '>= 2.7'
|
39
39
|
spec.add_dependency 'jira-ruby', '~> 2.2'
|
40
40
|
spec.add_dependency 'ruby-progressbar', '~> 1.11'
|
@@ -56,7 +56,7 @@ Gem::Specification.new do |spec|
|
|
56
56
|
spec.add_development_dependency 'rubocop-ast', '~> 1.4'
|
57
57
|
spec.add_development_dependency 'rubocop-performance', '~> 1.9'
|
58
58
|
spec.add_development_dependency 'rubocop-i18n', '~> 3.0'
|
59
|
-
spec.add_development_dependency 'fast_gettext', '
|
59
|
+
spec.add_development_dependency 'fast_gettext', '>= 2.0'
|
60
60
|
|
61
61
|
# For more information and examples about making a new gem, checkout our
|
62
62
|
# guide at: https://bundler.io/guides/creating_gem.html
|
@@ -382,7 +382,12 @@ module AbideDevUtils
|
|
382
382
|
# @valid_level is populated in verify_profile_and_level_selections from the fact that we've given
|
383
383
|
# the generator a list of levels we want to use. If we didn't give it a list of levels, then we
|
384
384
|
# want to use all of the levels that the control supports from @control.
|
385
|
-
@
|
385
|
+
if @framework == 'stig'
|
386
|
+
@md.add_ul('Supported MAC Levels:')
|
387
|
+
else
|
388
|
+
@md.add_ul('Supported Levels:')
|
389
|
+
end
|
390
|
+
|
386
391
|
if @valid_level.empty?
|
387
392
|
@control.levels.each do |l|
|
388
393
|
@md.add_ul(@md.code(l), indent: 1)
|
@@ -400,7 +405,12 @@ module AbideDevUtils
|
|
400
405
|
# @valid_profile is populated in verify_profile_and_level_selections from the fact that we've given
|
401
406
|
# the generator a list of profiles we want to use. If we didn't give it a list of profiles, then we
|
402
407
|
# want to use all of the profiles that the control supports from @control.
|
403
|
-
@
|
408
|
+
if @framework == 'stig'
|
409
|
+
@md.add_ul('Supported Confidentiality:')
|
410
|
+
else
|
411
|
+
@md.add_ul('Supported Profiles:')
|
412
|
+
end
|
413
|
+
|
404
414
|
if @valid_profile.empty?
|
405
415
|
@control.profiles.each do |l|
|
406
416
|
@md.add_ul(@md.code(l), indent: 1)
|
@@ -413,7 +423,7 @@ module AbideDevUtils
|
|
413
423
|
end
|
414
424
|
|
415
425
|
def control_alternate_ids_builder
|
416
|
-
return if @framework == 'stig'
|
426
|
+
# return if @framework == 'stig'
|
417
427
|
|
418
428
|
@md.add_ul('Alternate Config IDs:')
|
419
429
|
@control.alternate_ids.each do |l|
|
@@ -6,9 +6,6 @@ require 'abide_dev_utils/jira'
|
|
6
6
|
|
7
7
|
module Abide
|
8
8
|
module CLI
|
9
|
-
CONFIG = AbideDevUtils::Config
|
10
|
-
JIRA = AbideDevUtils::Jira
|
11
|
-
|
12
9
|
class JiraCommand < CmdParse::Command
|
13
10
|
CMD_NAME = 'jira'
|
14
11
|
CMD_SHORT = 'Commands related to Jira tickets'
|
@@ -38,11 +35,9 @@ module Abide
|
|
38
35
|
end
|
39
36
|
|
40
37
|
def execute
|
41
|
-
|
42
|
-
myself = JIRA.myself(client)
|
43
|
-
return if myself.attrs['displayName'].empty?
|
38
|
+
return if AbideDevUtils::Jira.client.myself.attrs['displayName'].empty?
|
44
39
|
|
45
|
-
Abide::CLI::OUTPUT.simple("Successfully authenticated user #{myself.attrs['
|
40
|
+
Abide::CLI::OUTPUT.simple("Successfully authenticated user #{AbideDevUtils::Jira.client.myself.attrs['displayName']}!")
|
46
41
|
end
|
47
42
|
end
|
48
43
|
|
@@ -59,8 +54,7 @@ module Abide
|
|
59
54
|
end
|
60
55
|
|
61
56
|
def execute(issue)
|
62
|
-
|
63
|
-
issue = client.Issue.find(issue)
|
57
|
+
issue = AbideDevUtils::Jira.client.find(:issue, issue)
|
64
58
|
console = @data[:file].nil?
|
65
59
|
out_json = issue.attrs.select { |_, v| !v.nil? || !v.empty? }
|
66
60
|
Abide::CLI::OUTPUT.json(out_json, console: console, file: @data[:file])
|
@@ -83,13 +77,15 @@ module Abide
|
|
83
77
|
end
|
84
78
|
|
85
79
|
def execute(project, summary, *subtasks)
|
86
|
-
|
87
|
-
issue = JIRA.new_issue(client, project, summary)
|
80
|
+
issue = AbideDevUtils::Jira.client.create(:issue, project: project, summary: summary)
|
88
81
|
Abide::CLI::OUTPUT.simple("Successfully created #{issue.attrs['key']}")
|
89
82
|
return if subtasks.nil? || subtasks.empty?
|
90
83
|
|
91
84
|
Abide::CLI::OUTPUT.simple('Creatings subtasks...')
|
92
|
-
|
85
|
+
subtasks.each do |sum|
|
86
|
+
subtask = AbideDevUtils::Jira.client.create(:subtask, parent: issue, summary: sum)
|
87
|
+
Abide::CLI::OUTPUT.simple("Successfully created #{subtask.attrs['key']}")
|
88
|
+
end
|
93
89
|
end
|
94
90
|
end
|
95
91
|
|
@@ -107,11 +103,8 @@ module Abide
|
|
107
103
|
|
108
104
|
def execute(report, project)
|
109
105
|
Abide::CLI::VALIDATE.file(report)
|
110
|
-
@data[:dry_run] = false if @data[:dry_run].nil?
|
111
|
-
client = JIRA.client(options: {})
|
112
|
-
proj = JIRA.project(client, project)
|
113
106
|
File.open(report) do |f|
|
114
|
-
|
107
|
+
AbideDevUtils::Jira.new_issues_from_coverage(project, JSON.parse(f.read), dry_run: @data[:dry_run])
|
115
108
|
end
|
116
109
|
end
|
117
110
|
end
|
@@ -127,14 +120,30 @@ module Abide
|
|
127
120
|
argument_desc(PATH: 'An XCCDF file', PROJECT: 'A Jira project')
|
128
121
|
options.on('-d', '--dry-run', 'Print to console instead of saving objects') { |_| @data[:dry_run] = true }
|
129
122
|
options.on('-e [EPIC]', '--epic [EPIC]', 'If given, tasks will be created and assigned to this epic. Takes form <PROJECT>-<NUM>') { |e| @data[:epic] = e }
|
123
|
+
options.on('-l [LEVEL]', '--level [LEVEL]', 'Only create tasks for rules belonging to the matching level. Takes a string that is treated as RegExp') do |x|
|
124
|
+
@data[:level] = x
|
125
|
+
end
|
126
|
+
options.on('-p [PROFILE]', '--profile [PROFILE]', 'Only create tasks for rules belonging to the matching profile. Takes a string that is treated as RegExp') do |x|
|
127
|
+
@data[:profile] = x
|
128
|
+
end
|
130
129
|
end
|
131
130
|
|
132
131
|
def execute(path, project)
|
133
132
|
Abide::CLI::VALIDATE.file(path)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
# Each control gets assigned labels based on the levels and profiles it supports.
|
134
|
+
# Those labels all take the form "level_<level>_<profile>". This allows us to
|
135
|
+
# filter the controls we want to create tasks for by level and profile.
|
136
|
+
@data[:label_include] = nil
|
137
|
+
@data[:label_include] = "level_#{@data[:level]}_" if @data[:level]
|
138
|
+
@data[:label_include] = "#{@data[:label_include]}#{@data[:profile]}" if @data[:profile]
|
139
|
+
Abide::CLI::Output.simple "Label include: #{@data[:label_include]}"
|
140
|
+
AbideDevUtils::Jira.new_issues_from_xccdf(
|
141
|
+
project,
|
142
|
+
path,
|
143
|
+
epic: @data[:epic],
|
144
|
+
dry_run: @data[:dry_run],
|
145
|
+
label_include: @data[:label_include],
|
146
|
+
)
|
138
147
|
end
|
139
148
|
end
|
140
149
|
|
@@ -167,17 +176,15 @@ module Abide
|
|
167
176
|
def execute(path1, path2, project)
|
168
177
|
Abide::CLI::VALIDATE.file(path1)
|
169
178
|
Abide::CLI::VALIDATE.file(path2)
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
auto_approve: @data[:auto_approve],
|
180
|
-
diff_opts: @data[:diff_opts])
|
179
|
+
AbideDevUtils::Jira.new_issues_from_xccdf_diff(
|
180
|
+
project,
|
181
|
+
path1,
|
182
|
+
path2,
|
183
|
+
epic: @data[:epic],
|
184
|
+
dry_run: @data[:dry_run],
|
185
|
+
auto_approve: @data[:auto_approve],
|
186
|
+
diff_opts: @data[:diff_opts],
|
187
|
+
)
|
181
188
|
end
|
182
189
|
end
|
183
190
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'client_builder'
|
4
|
+
require_relative 'dry_run'
|
5
|
+
require_relative 'finder'
|
6
|
+
require_relative 'helper'
|
7
|
+
require_relative 'issue_builder'
|
8
|
+
require_relative '../config'
|
9
|
+
require_relative '../errors/jira'
|
10
|
+
|
11
|
+
module AbideDevUtils
|
12
|
+
module Jira
|
13
|
+
class Client
|
14
|
+
extend DryRun
|
15
|
+
|
16
|
+
dry_run :create, :find, :myself
|
17
|
+
|
18
|
+
attr_accessor :default_project
|
19
|
+
attr_reader :config
|
20
|
+
|
21
|
+
def initialize(dry_run: false, **options)
|
22
|
+
@dry_run = dry_run
|
23
|
+
@options = options
|
24
|
+
@config = AbideDevUtils::Config.config_section('jira')
|
25
|
+
@default_project = @config[:default_project]
|
26
|
+
@client = nil
|
27
|
+
@finder = nil
|
28
|
+
@issue_builder = nil
|
29
|
+
@helper = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def myself
|
33
|
+
@myself ||= finder.myself
|
34
|
+
end
|
35
|
+
|
36
|
+
def find(type, id)
|
37
|
+
raise ArgumentError, "Invalid type #{type}" unless finder.respond_to?(type.to_sym)
|
38
|
+
|
39
|
+
finder.send(type.to_sym, id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def create(type, **fields)
|
43
|
+
issue_builder.create(type, **fields)
|
44
|
+
end
|
45
|
+
|
46
|
+
def helper
|
47
|
+
@helper ||= Helper.new(self, dry_run: @dry_run)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def client
|
53
|
+
@client ||= ClientBuilder.new(@config, **@options).build
|
54
|
+
end
|
55
|
+
|
56
|
+
def finder
|
57
|
+
@finder ||= Finder.new(client)
|
58
|
+
end
|
59
|
+
|
60
|
+
def issue_builder
|
61
|
+
@issue_builder ||= IssueBuilder.new(client, finder)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jira-ruby'
|
4
|
+
require_relative '../prompt'
|
5
|
+
|
6
|
+
module AbideDevUtils
|
7
|
+
module Jira
|
8
|
+
class ClientBuilder
|
9
|
+
def initialize(config, **options)
|
10
|
+
@options = options
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def username
|
15
|
+
find_option_value(:username)
|
16
|
+
end
|
17
|
+
|
18
|
+
def username=(username)
|
19
|
+
@options[:username] = username
|
20
|
+
end
|
21
|
+
|
22
|
+
def password
|
23
|
+
if find_option_value(:password)
|
24
|
+
'********'
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def password=(password)
|
31
|
+
@options[:password] = password
|
32
|
+
end
|
33
|
+
|
34
|
+
def site
|
35
|
+
find_option_value(:site)
|
36
|
+
end
|
37
|
+
|
38
|
+
def site=(site)
|
39
|
+
@options[:site] = site
|
40
|
+
end
|
41
|
+
|
42
|
+
def context_path
|
43
|
+
find_option_value(:context_path, default: '')
|
44
|
+
end
|
45
|
+
|
46
|
+
def context_path=(context_path)
|
47
|
+
@options[:context_path] = context_path
|
48
|
+
end
|
49
|
+
|
50
|
+
def auth_type
|
51
|
+
find_option_value(:auth_type, default: :basic)
|
52
|
+
end
|
53
|
+
|
54
|
+
def auth_type=(auth_type)
|
55
|
+
@options[:auth_type] = auth_type
|
56
|
+
end
|
57
|
+
|
58
|
+
def http_debug
|
59
|
+
find_option_value(:http_debug, default: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
def http_debug=(http_debug)
|
63
|
+
@options[:http_debug] = http_debug
|
64
|
+
end
|
65
|
+
|
66
|
+
def build
|
67
|
+
JIRA::Client.new({
|
68
|
+
username: find_option_value(:username, prompt: true),
|
69
|
+
password: find_option_value(:password, prompt: true),
|
70
|
+
site: find_option_value(:site, prompt: 'Jira site URL'),
|
71
|
+
context_path: find_option_value(:context_path, default: ''),
|
72
|
+
auth_type: find_option_value(:auth_type, default: :basic),
|
73
|
+
http_debug: find_option_value(:http_debug, default: false),
|
74
|
+
})
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def find_option_value(key, default: nil, prompt: nil)
|
80
|
+
if prompt
|
81
|
+
find_option_value_or_prompt(key, prompt)
|
82
|
+
else
|
83
|
+
find_option_value_or_default(key, default)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def find_option_val(key)
|
88
|
+
@options[key] || @config[key] || ENV["JIRA_#{key.to_s.upcase}"]
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_option_value_or_prompt(key, prompt = 'Enter value')
|
92
|
+
case key
|
93
|
+
when /password/i
|
94
|
+
find_option_val(key) || AbideDevUtils::Prompt.password
|
95
|
+
when /username/i
|
96
|
+
find_option_val(key) || AbideDevUtils::Prompt.username
|
97
|
+
else
|
98
|
+
find_option_val(key) || AbideDevUtils::Prompt.single_line(prompt)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def find_option_value_or_default(key, default)
|
103
|
+
find_option_val(key) || default
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../output'
|
4
|
+
|
5
|
+
module AbideDevUtils
|
6
|
+
module Jira
|
7
|
+
module DryRun
|
8
|
+
def dry_run(*method_names)
|
9
|
+
method_names.each do |method_name|
|
10
|
+
proxy = Module.new do
|
11
|
+
define_method(method_name) do |*args, **kwargs|
|
12
|
+
if !!@dry_run
|
13
|
+
case method_name
|
14
|
+
when %r{^create}
|
15
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{args[1].map { |k, v| "#{k}: #{v.inspect}" }.join(', ')})")
|
16
|
+
sleep 0.1
|
17
|
+
return DummyIssue.new if args[0].match?(%r{^issue$})
|
18
|
+
return DummySubtask.new if args[0].match?(%r{^subtask$})
|
19
|
+
when %r{^find}
|
20
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{args[1].inspect})")
|
21
|
+
return DummyIssue.new if args[0].match?(%r{^issue$})
|
22
|
+
return DummySubtask.new if args[0].match?(%r{^subtask$})
|
23
|
+
return DummyProject.new if args[0].match?(%r{^project$})
|
24
|
+
|
25
|
+
"Dummy #{args[0].capitalize}"
|
26
|
+
else
|
27
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args.map(&:inspect).join(', ')})")
|
28
|
+
end
|
29
|
+
else
|
30
|
+
super(*args, **kwargs)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
self.prepend(proxy)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def dry_run_simple(*method_names)
|
39
|
+
method_names.each do |method_name|
|
40
|
+
proxy = Module.new do
|
41
|
+
define_method(method_name) do |*args, **kwargs|
|
42
|
+
return if !!@dry_run
|
43
|
+
|
44
|
+
super(*args, **kwargs)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
self.prepend(proxy)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def dry_run_return_true(*method_names)
|
52
|
+
method_names.each do |method_name|
|
53
|
+
proxy = Module.new do
|
54
|
+
define_method(method_name) do |*args, **kwargs|
|
55
|
+
return true if !!@dry_run
|
56
|
+
|
57
|
+
super(*args, **kwargs)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
self.prepend(proxy)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def dry_run_return_false(*method_names)
|
65
|
+
method_names.each do |method_name|
|
66
|
+
proxy = Module.new do
|
67
|
+
define_method(method_name) do |*args, **kwargs|
|
68
|
+
return false if !!@dry_run
|
69
|
+
|
70
|
+
super(*args, **kwargs)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
self.prepend(proxy)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Dummy
|
78
|
+
attr_reader :dummy
|
79
|
+
|
80
|
+
def initialize
|
81
|
+
@dummy = true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class DummyIssue < Dummy
|
86
|
+
attr_reader :summary, :key
|
87
|
+
|
88
|
+
def initialize
|
89
|
+
super
|
90
|
+
@summary = 'Dummy Issue'
|
91
|
+
@key = 'DUM-111'
|
92
|
+
end
|
93
|
+
|
94
|
+
def attrs
|
95
|
+
{
|
96
|
+
'fields' => {
|
97
|
+
'project' => 'dummy',
|
98
|
+
'priority' => 'dummy',
|
99
|
+
},
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class DummySubtask < DummyIssue
|
105
|
+
def initialize
|
106
|
+
super
|
107
|
+
@summary = 'Dummy Subtask'
|
108
|
+
@key = 'DUM-222'
|
109
|
+
end
|
110
|
+
|
111
|
+
def attrs
|
112
|
+
{
|
113
|
+
'fields' => {
|
114
|
+
'project' => 'dummy',
|
115
|
+
'priority' => 'dummy',
|
116
|
+
'parent' => DummyIssue.new,
|
117
|
+
},
|
118
|
+
}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class DummyProject < Dummy
|
123
|
+
attr_reader :key, :issues
|
124
|
+
|
125
|
+
def initialize
|
126
|
+
super
|
127
|
+
@key = 'DUM'
|
128
|
+
@issues = [DummyIssue.new, DummySubtask.new]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../errors/jira'
|
4
|
+
|
5
|
+
module AbideDevUtils
|
6
|
+
module Jira
|
7
|
+
class Finder
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def myself
|
13
|
+
client.User.myself
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param id [String] The project key or ID
|
17
|
+
def project(id)
|
18
|
+
return id if id.is_a?(client.Project.target_class)
|
19
|
+
|
20
|
+
client.Project.find(id)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param id [String] The issue key or summary
|
24
|
+
def issue(id)
|
25
|
+
return id if id.is_a?(client.Issue.target_class)
|
26
|
+
|
27
|
+
client.Issue.find(id)
|
28
|
+
rescue URI::InvalidURIError
|
29
|
+
iss = client.Issue.all.find { |i| i.summary == id }
|
30
|
+
raise AbideDevUtils::Errors::Jira::FindIssueError, id if iss.nil?
|
31
|
+
|
32
|
+
iss
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param id [String] The issuetype ID or name
|
36
|
+
def issuetype(id)
|
37
|
+
return id if id.is_a?(client.Issuetype.target_class)
|
38
|
+
|
39
|
+
if id.match?(%r{^\d+$})
|
40
|
+
client.Issuetype.find(id)
|
41
|
+
else
|
42
|
+
client.Issuetype.all.find { |i| i.name == id }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param id [String] The priority ID or name
|
47
|
+
def priority(id)
|
48
|
+
return id if id.is_a?(client.Priority.target_class)
|
49
|
+
|
50
|
+
if id.match?(%r{^\d+$})
|
51
|
+
client.Priority.find(id)
|
52
|
+
else
|
53
|
+
client.Priority.all.find { |i| i.name == id }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :client
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'dry_run'
|
4
|
+
|
5
|
+
module AbideDevUtils
|
6
|
+
module Jira
|
7
|
+
class Helper
|
8
|
+
extend DryRun
|
9
|
+
|
10
|
+
dry_run_simple :add_issue_label
|
11
|
+
dry_run_return_false :summary_exist?
|
12
|
+
|
13
|
+
def initialize(client, dry_run: false)
|
14
|
+
@client = client
|
15
|
+
@dry_run = dry_run
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param project [JIRA::Resource::Project, String]
|
19
|
+
def all_project_issues_attrs(project)
|
20
|
+
project = @client.find(:project, project)
|
21
|
+
project.issues.collect(&:attrs)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param issue [JIRA::Resource::Issue, String]
|
25
|
+
# @param label [String]
|
26
|
+
def add_issue_label(issue, label)
|
27
|
+
issue = @client.find(:issue, issue)
|
28
|
+
return if issue.labels.include?(label)
|
29
|
+
|
30
|
+
issue.labels << label
|
31
|
+
issue.save
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param summary [String]
|
35
|
+
# @param issue_attrs [Array<Hash>]
|
36
|
+
def summary_exist?(summary, issue_attrs)
|
37
|
+
issue_attrs.any? { |attrs| attrs['fields'].key?('summary') && attrs['fields']['summary'] == summary }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../errors/jira'
|
4
|
+
|
5
|
+
module AbideDevUtils
|
6
|
+
module Jira
|
7
|
+
class IssueBuilder
|
8
|
+
CUSTOM_FIELDS = {
|
9
|
+
'epic_link' => 'customfield_10014',
|
10
|
+
'epic_name' => 'customfield_10011',
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
FIELD_DEFAULTS = {
|
14
|
+
'issuetype' => 'Task',
|
15
|
+
'priority' => 'Medium',
|
16
|
+
'labels' => ['abide_dev_utils'],
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
REQUIRED_FIELDS = %w[project summary].freeze
|
20
|
+
|
21
|
+
def initialize(client, finder)
|
22
|
+
@client = client
|
23
|
+
@finder = finder
|
24
|
+
end
|
25
|
+
|
26
|
+
def can_create?(type)
|
27
|
+
respond_to?("create_#{type}".to_sym, true)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create(type, **fields)
|
31
|
+
type = type.to_s.downcase.to_sym
|
32
|
+
raise ArgumentError, "Invalid type \"#{type}\"; no method \"create_#{type}\"" unless can_create?(type)
|
33
|
+
|
34
|
+
fields = process_fields(fields)
|
35
|
+
send("create_#{type}".to_sym, **fields)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :client
|
41
|
+
|
42
|
+
def create_issue(**fields)
|
43
|
+
iss = client.Issue.build
|
44
|
+
iss.save({ 'fields' => fields })
|
45
|
+
iss
|
46
|
+
rescue StandardError => e
|
47
|
+
raise AbideDevUtils::Errors::Jira::CreateIssueError, e
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_subtask(**fields)
|
51
|
+
fields['parent'] = find_if_not_type(:issue, client.Issue.target_class, fields['parent'])
|
52
|
+
issue_fields = fields['parent'].attrs['fields']
|
53
|
+
fields['project'] = issue_fields['project']
|
54
|
+
fields['issuetype'] = find_if_not_type(:issuetype, client.Issuetype.target_class, 'Sub-task')
|
55
|
+
fields['priority'] = issue_fields['priority']
|
56
|
+
iss = client.Issue.build
|
57
|
+
iss.save({ 'fields' => fields })
|
58
|
+
iss
|
59
|
+
rescue StandardError => e
|
60
|
+
raise AbideDevUtils::Errors::Jira::CreateSubtaskError, e
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_fields(fields)
|
64
|
+
fields = fields.dup
|
65
|
+
normalize_field_keys!(fields)
|
66
|
+
validate_required_fields!(fields)
|
67
|
+
normalize_field_values(fields)
|
68
|
+
end
|
69
|
+
|
70
|
+
def validate_required_fields!(fields)
|
71
|
+
missing = REQUIRED_FIELDS.reject { |f| fields.key?(f) }
|
72
|
+
raise "Missing required field(s) \"#{missing}\"; present fields: \"#{fields.keys}\"" unless missing.empty?
|
73
|
+
end
|
74
|
+
|
75
|
+
def normalize_field_keys!(fields)
|
76
|
+
fields.transform_keys! { |k| k.to_s.downcase }
|
77
|
+
fields.transform_keys! { |k| CUSTOM_FIELDS[k] || k }
|
78
|
+
end
|
79
|
+
|
80
|
+
def normalize_field_values(fields)
|
81
|
+
fields = FIELD_DEFAULTS.merge(fields).map do |k, v|
|
82
|
+
v = case k
|
83
|
+
when 'labels'
|
84
|
+
v.is_a?(Array) ? v : [v]
|
85
|
+
when 'issuetype'
|
86
|
+
find_if_not_type(:issuetype, client.Issuetype.target_class, v)
|
87
|
+
when 'parent'
|
88
|
+
find_if_not_type(:issue, client.Issue.target_class, v)
|
89
|
+
when 'priority'
|
90
|
+
find_if_not_type(:priority, client.Priority.target_class, v)
|
91
|
+
when 'epic_link', CUSTOM_FIELDS['epic_link']
|
92
|
+
find_if_not_type(:issue, client.Issue.target_class, v)&.key || v
|
93
|
+
when 'project'
|
94
|
+
find_if_not_type(:project, client.Project.target_class, v)
|
95
|
+
else
|
96
|
+
v
|
97
|
+
end
|
98
|
+
[k, v]
|
99
|
+
end
|
100
|
+
fields.to_h
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_if_not_type(typesym, typeklass, obj)
|
104
|
+
return obj if obj.is_a?(typeklass)
|
105
|
+
|
106
|
+
@finder.send(typesym, obj)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/abide_dev_utils/jira.rb
CHANGED
@@ -5,6 +5,7 @@ require 'abide_dev_utils/output'
|
|
5
5
|
require 'abide_dev_utils/prompt'
|
6
6
|
require 'abide_dev_utils/config'
|
7
7
|
require 'abide_dev_utils/errors/jira'
|
8
|
+
require_relative 'jira/client'
|
8
9
|
|
9
10
|
module AbideDevUtils
|
10
11
|
module Jira
|
@@ -14,192 +15,58 @@ module AbideDevUtils
|
|
14
15
|
UPD_EPIC_SUMMARY_PREFIX = '::BENCHMARK UPDATE::'
|
15
16
|
PROGRESS_BAR_FORMAT = '%a %e %P% Created: %c of %C'
|
16
17
|
|
17
|
-
def self.
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.issue(client, issue)
|
22
|
-
client.Issue.find(issue)
|
23
|
-
rescue URI::InvalidURIError
|
24
|
-
iss = client.Issue.all.find { |i| i.summary == issue }
|
25
|
-
raise ERRORS::FindIssueError, issue unless iss
|
26
|
-
|
27
|
-
iss
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.myself(client)
|
31
|
-
client.User.myself
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.issuetype(client, id)
|
35
|
-
if id.match?(%r{^\d+$})
|
36
|
-
client.Issuetype.find(id)
|
37
|
-
else
|
38
|
-
client.Issuetype.all.find { |i| i.name == id }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.priority(client, id)
|
43
|
-
if id.match?(%r{^\d+$})
|
44
|
-
client.Priority.find(id)
|
45
|
-
else
|
46
|
-
client.Priority.all.find { |i| i.name == id }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.all_project_issues_attrs(project)
|
51
|
-
raw_issues = project.issues
|
52
|
-
raw_issues.collect(&:attrs)
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.add_issue_label(iss, label, dry_run: false)
|
56
|
-
return if dry_run || iss.labels.include?(label)
|
57
|
-
|
58
|
-
iss.labels << profile_summary
|
59
|
-
iss.save
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.new_issue(client, project, summary, description: nil, labels: ['abide_dev_utils'], epic: nil, dry_run: false)
|
63
|
-
if dry_run
|
64
|
-
sleep(0.2)
|
65
|
-
return Dummy.new(summary)
|
66
|
-
end
|
67
|
-
fields = {}
|
68
|
-
fields['summary'] = summary
|
69
|
-
fields['project'] = project(client, project)
|
70
|
-
fields['issuetype'] = issuetype(client, 'Task')
|
71
|
-
fields['priority'] = priority(client, '3')
|
72
|
-
fields['description'] = description if description
|
73
|
-
fields['labels'] = labels
|
74
|
-
epic = issue(client, epic) if epic && !epic.is_a?(JIRA::Resource::Issue)
|
75
|
-
fields['customfield_10006'] = epic.key if epic # Epic_Link
|
76
|
-
iss = client.Issue.build
|
77
|
-
raise ERRORS::CreateIssueError, iss.attrs unless iss.save({ 'fields' => fields })
|
78
|
-
|
79
|
-
iss
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.new_epic(client, project, summary, dry_run: false)
|
83
|
-
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Creating epic '#{summary}'")
|
84
|
-
if dry_run
|
85
|
-
sleep(0.2)
|
86
|
-
return Dummy.new(summary)
|
87
|
-
end
|
88
|
-
fields = {
|
89
|
-
'summary' => summary,
|
90
|
-
'project' => project(client, project),
|
91
|
-
'issuetype' => issuetype(client, 'Epic'),
|
92
|
-
'customfield_10007' => summary, # Epic Name
|
93
|
-
}
|
94
|
-
iss = client.Issue.build
|
95
|
-
raise ERRORS::CreateEpicError, iss.attrs unless iss.save({ 'fields' => fields })
|
96
|
-
|
97
|
-
iss
|
98
|
-
end
|
99
|
-
|
100
|
-
# This should probably be threaded in the future
|
101
|
-
def self.bulk_new_issue(client, project, summaries, dry_run: false)
|
102
|
-
summaries.each { |s| new_issue(client, project, s, dry_run: dry_run) }
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.new_subtask(client, issue, summary, dry_run: false)
|
106
|
-
if dry_run
|
107
|
-
sleep(0.2)
|
108
|
-
return Dummy.new
|
109
|
-
end
|
110
|
-
issue_fields = issue.attrs['fields']
|
111
|
-
fields = {}
|
112
|
-
fields['parent'] = issue
|
113
|
-
fields['summary'] = summary
|
114
|
-
fields['project'] = issue_fields['project']
|
115
|
-
fields['issuetype'] = issuetype(client, '5')
|
116
|
-
fields['priority'] = issue_fields['priority']
|
117
|
-
subtask = client.Issue.build
|
118
|
-
raise ERRORS::CreateSubtaskError, subtask.attrs unless subtask.save({ 'fields' => fields })
|
119
|
-
|
120
|
-
subtask
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.bulk_new_subtask(client, issue, summaries, dry_run: false)
|
124
|
-
summaries.each do |s|
|
125
|
-
new_subtask(client, issue, s, dry_run: dry_run)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.client(options: {})
|
130
|
-
opts = merge_options(options)
|
131
|
-
return client_from_prompts if opts.empty?
|
132
|
-
|
133
|
-
opts[:username] = AbideDevUtils::Prompt.username if opts[:username].nil?
|
134
|
-
opts[:password] = AbideDevUtils::Prompt.password if opts[:password].nil?
|
135
|
-
opts[:site] = AbideDevUtils::Prompt.single_line('Jira URL') if opts[:site].nil?
|
136
|
-
opts[:context_path] = '' if opts[:context_path].nil?
|
137
|
-
opts[:auth_type] = :basic if opts[:auth_type].nil?
|
138
|
-
JIRA::Client.new(opts)
|
139
|
-
end
|
140
|
-
|
141
|
-
def self.client_from_prompts(http_debug: false)
|
142
|
-
options = {}
|
143
|
-
options[:username] = AbideDevUtils::Prompt.username
|
144
|
-
options[:password] = AbideDevUtils::Prompt.password
|
145
|
-
options[:site] = AbideDevUtils::Prompt.single_line('Jira URL')
|
146
|
-
options[:context_path] = ''
|
147
|
-
options[:auth_type] = :basic
|
148
|
-
options[:http_debug] = http_debug
|
149
|
-
JIRA::Client.new(options)
|
150
|
-
end
|
18
|
+
def self.client(memo: true, dry_run: false, **options)
|
19
|
+
return AbideDevUtils::Jira::Client.new(dry_run: dry_run, **options) unless memo
|
151
20
|
|
152
|
-
|
153
|
-
client = client_from_prompts(http_debug)
|
154
|
-
project = AbideDevUtils::Prompt.single_line('Project').upcase
|
155
|
-
client.Project.find(project)
|
21
|
+
@client ||= AbideDevUtils::Jira::Client.new(dry_run: dry_run, **options)
|
156
22
|
end
|
157
23
|
|
158
24
|
def self.new_issues_from_coverage(client, project, report, dry_run: false)
|
159
25
|
dr_prefix = dry_run ? 'DRY RUN: ' : ''
|
160
|
-
|
26
|
+
client(dry_run: dry_run) # Initializes the client if needed
|
27
|
+
i_attrs = client.helper.all_project_issues_attrs(project)
|
161
28
|
rep_sums = summaries_from_coverage_report(report)
|
162
29
|
rep_sums.each do |k, v|
|
163
|
-
next if summary_exist?(k, i_attrs)
|
30
|
+
next if client.helper.summary_exist?(k, i_attrs)
|
164
31
|
|
165
|
-
parent
|
166
|
-
|
167
|
-
parent_issue = issue(client, parent.attrs['key']) unless parent.respond_to?(:dummy)
|
32
|
+
AbideDevUtils::Output.simple("#{dr_prefix}Creating parent issue #{k}...")
|
33
|
+
parent = client.create(:issue, project: project, summary: k.to_s)
|
168
34
|
AbideDevUtils::Output.simple("#{dr_prefix}Creating subtasks, this can take a while...")
|
169
35
|
progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Subtasks", total: nil)
|
170
36
|
v.each do |s|
|
171
|
-
next if summary_exist?(s, i_attrs)
|
37
|
+
next if client.helper.summary_exist?(s, i_attrs)
|
172
38
|
|
173
39
|
progress.title = "#{dr_prefix}#{s}"
|
174
|
-
|
40
|
+
client.create(:subtask, parent: parent, summary: s)
|
175
41
|
progress.increment
|
176
42
|
end
|
177
43
|
end
|
178
44
|
end
|
179
45
|
|
180
|
-
def self.new_issues_from_xccdf(
|
181
|
-
|
46
|
+
def self.new_issues_from_xccdf(project, xccdf_path, epic: nil, dry_run: false, label_include: nil)
|
47
|
+
client(dry_run: dry_run) # Initializes the client if needed
|
48
|
+
i_attrs = client.helper.all_project_issues_attrs(project)
|
182
49
|
xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf_path)
|
183
50
|
# We need to get the actual epic Issue object, or create it if it doesn't exist
|
184
51
|
epic = if epic.nil?
|
185
52
|
new_epic_summary = "#{COV_PARENT_SUMMARY_PREFIX}#{xccdf.title}"
|
186
|
-
if summary_exist?(new_epic_summary, i_attrs)
|
187
|
-
issue
|
53
|
+
if client.helper.summary_exist?(new_epic_summary, i_attrs)
|
54
|
+
client.find(:issue, new_epic_summary)
|
188
55
|
else
|
189
56
|
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?")
|
190
57
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
|
191
58
|
exit(0)
|
192
59
|
end
|
193
|
-
|
60
|
+
client.create(:issue, project: project, summary: new_epic_summary, issuetype: 'Epic', epic_name: new_epic_summary)
|
194
61
|
end
|
195
62
|
else
|
196
|
-
issue
|
63
|
+
client.find(:issue, epic)
|
197
64
|
end
|
198
65
|
# Now we need to find out which issues we need to create for the benchmark
|
199
66
|
# The profiles that the control belongs to will be added as an issue label
|
200
67
|
to_create = {}
|
201
68
|
summaries_from_xccdf(xccdf).each do |profile_summary, control_summaries|
|
202
|
-
control_summaries.reject { |s| summary_exist?(s, i_attrs) }.each do |control_summary|
|
69
|
+
control_summaries.reject { |s| client.helper.summary_exist?(s, i_attrs) }.each do |control_summary|
|
203
70
|
if to_create.key?(control_summary)
|
204
71
|
to_create[control_summary] << profile_summary.split.join('_').downcase
|
205
72
|
else
|
@@ -208,6 +75,13 @@ module AbideDevUtils
|
|
208
75
|
end
|
209
76
|
end
|
210
77
|
|
78
|
+
# If we have a label_include, we need to filter out any controls that don't have that label
|
79
|
+
unless label_include.nil?
|
80
|
+
to_create = to_create.select do |_control_summary, labels|
|
81
|
+
labels.any? { |l| l.match?(label_include) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
211
85
|
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create #{to_create.keys.count} new Jira issues?")
|
212
86
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
|
213
87
|
exit(0)
|
@@ -219,31 +93,32 @@ module AbideDevUtils
|
|
219
93
|
to_create.each do |control_summary, labels|
|
220
94
|
abrev = control_summary.length > 40 ? control_summary[0..60] : control_summary
|
221
95
|
progress.log("#{dr_prefix(dry_run)}Creating #{abrev}...")
|
222
|
-
|
96
|
+
client.create(:issue, project: project, summary: control_summary, labels: labels, epic_link: epic)
|
223
97
|
progress.increment
|
224
98
|
end
|
225
99
|
progress.finish
|
226
100
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Done creating tasks in Epic '#{epic.summary}'")
|
227
101
|
end
|
228
102
|
|
229
|
-
def self.new_issues_from_xccdf_diff(
|
103
|
+
def self.new_issues_from_xccdf_diff(project, xccdf1_path, xccdf2_path, epic: nil, dry_run: false, auto_approve: false, diff_opts: {})
|
230
104
|
require 'abide_dev_utils/xccdf/diff'
|
231
105
|
diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(xccdf1_path, xccdf2_path, diff_opts)
|
232
|
-
|
106
|
+
client(dry_run: dry_run) # Initializes the client if needed
|
107
|
+
i_attrs = client.helper.all_project_issues_attrs(project)
|
233
108
|
# We need to get the actual epic Issue object, or create it if it doesn't exist
|
234
109
|
epic = if epic.nil?
|
235
|
-
new_epic_summary = "#{
|
236
|
-
if summary_exist?(new_epic_summary, i_attrs)
|
237
|
-
issue
|
110
|
+
new_epic_summary = "#{COV_PARENT_SUMMARY_PREFIX}#{xccdf.title}"
|
111
|
+
if client.helper.summary_exist?(new_epic_summary, i_attrs)
|
112
|
+
client.find(:issue, new_epic_summary)
|
238
113
|
else
|
239
|
-
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?"
|
114
|
+
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?")
|
240
115
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
|
241
116
|
exit(0)
|
242
117
|
end
|
243
|
-
|
118
|
+
client.create(:issue, project: project, summary: new_epic_summary, issuetype: 'Epic', epic_name: new_epic_summary)
|
244
119
|
end
|
245
120
|
else
|
246
|
-
issue
|
121
|
+
client.find(:issue, epic)
|
247
122
|
end
|
248
123
|
to_create = {}
|
249
124
|
diff.diff[:rules].each do |key, val|
|
@@ -285,7 +160,7 @@ module AbideDevUtils
|
|
285
160
|
format: PROGRESS_BAR_FORMAT)
|
286
161
|
approved_create.each do |summary, description|
|
287
162
|
progress.log("#{dr_prefix(dry_run)}Creating #{summary}...")
|
288
|
-
|
163
|
+
client.create(:issue, project: project, summary: summary, description: description, labels: [], epic_link: epic)
|
289
164
|
progress.increment
|
290
165
|
end
|
291
166
|
progress.finish
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide_dev_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- abide-team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 7.0.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 7.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: puppet-strings
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -322,16 +322,16 @@ dependencies:
|
|
322
322
|
name: fast_gettext
|
323
323
|
requirement: !ruby/object:Gem::Requirement
|
324
324
|
requirements:
|
325
|
-
- - "
|
325
|
+
- - ">="
|
326
326
|
- !ruby/object:Gem::Version
|
327
|
-
version: '
|
327
|
+
version: '2.0'
|
328
328
|
type: :development
|
329
329
|
prerelease: false
|
330
330
|
version_requirements: !ruby/object:Gem::Requirement
|
331
331
|
requirements:
|
332
|
-
- - "
|
332
|
+
- - ">="
|
333
333
|
- !ruby/object:Gem::Version
|
334
|
-
version: '
|
334
|
+
version: '2.0'
|
335
335
|
description: Provides a CLI with helpful utilities for developing compliance Puppet
|
336
336
|
code
|
337
337
|
email:
|
@@ -404,6 +404,12 @@ files:
|
|
404
404
|
- lib/abide_dev_utils/files.rb
|
405
405
|
- lib/abide_dev_utils/gcloud.rb
|
406
406
|
- lib/abide_dev_utils/jira.rb
|
407
|
+
- lib/abide_dev_utils/jira/client.rb
|
408
|
+
- lib/abide_dev_utils/jira/client_builder.rb
|
409
|
+
- lib/abide_dev_utils/jira/dry_run.rb
|
410
|
+
- lib/abide_dev_utils/jira/finder.rb
|
411
|
+
- lib/abide_dev_utils/jira/helper.rb
|
412
|
+
- lib/abide_dev_utils/jira/issue_builder.rb
|
407
413
|
- lib/abide_dev_utils/markdown.rb
|
408
414
|
- lib/abide_dev_utils/mixins.rb
|
409
415
|
- lib/abide_dev_utils/output.rb
|
@@ -463,7 +469,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
463
469
|
- !ruby/object:Gem::Version
|
464
470
|
version: '0'
|
465
471
|
requirements: []
|
466
|
-
rubygems_version: 3.4.
|
472
|
+
rubygems_version: 3.4.18
|
467
473
|
signing_key:
|
468
474
|
specification_version: 4
|
469
475
|
summary: Helper utilities for developing compliance Puppet code
|