abide_dev_utils 0.17.0 → 0.17.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/Gemfile.lock +1 -1
- data/lib/abide_dev_utils/cli/jira.rb +8 -2
- data/lib/abide_dev_utils/jira/client.rb +4 -0
- data/lib/abide_dev_utils/jira/dry_run.rb +15 -12
- data/lib/abide_dev_utils/jira/finder.rb +6 -0
- data/lib/abide_dev_utils/jira.rb +89 -17
- data/lib/abide_dev_utils/output.rb +8 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba0491c8fbcaa0a69015c410a2aa7e61ac61e6b30caca6fb5b334d22fd77069c
|
4
|
+
data.tar.gz: 119c837a5ea897957e63744ec3f38a7567222d7dbb5b952302ec71cd70aafc24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 492066b562bee8dd3c3d3b465396a569d66a66200018bb74e606c8f3a78320853ecc71a8f30ee0c4f18194dbdc0d8679ff8c32fd38fbaf7936267eae1b35d5eb
|
7
|
+
data.tar.gz: 2766d7c84c887b573cd9cb23f5d2aa869a4f238e5208ab2377832827e88d44056d180226a31c93ee242ed954d6aaf65b0e075d282b65ba53ea475ae1adb8e45a
|
data/Gemfile.lock
CHANGED
@@ -118,7 +118,12 @@ module Abide
|
|
118
118
|
short_desc(CMD_SHORT)
|
119
119
|
long_desc(CMD_LONG)
|
120
120
|
argument_desc(PATH: 'An XCCDF file', PROJECT: 'A Jira project')
|
121
|
-
options.on('-d', '--dry-run', '
|
121
|
+
options.on('-d', '--dry-run', 'Runs through mock issue creation. Useful for testing, but not reliable for knowing what exactly will be created. Use --explain for more accurate information.') do
|
122
|
+
@data[:dry_run] = true
|
123
|
+
end
|
124
|
+
options.on('-x', '--explain', 'Shows a report of all the controls that will and won\'t be created as issues, and why. DOES NOT create issues.') do
|
125
|
+
@data[:explain] = true
|
126
|
+
end
|
122
127
|
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
128
|
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
129
|
@data[:level] = x
|
@@ -136,12 +141,13 @@ module Abide
|
|
136
141
|
@data[:label_include] = nil
|
137
142
|
@data[:label_include] = "level_#{@data[:level]}_" if @data[:level]
|
138
143
|
@data[:label_include] = "#{@data[:label_include]}#{@data[:profile]}" if @data[:profile]
|
139
|
-
Abide::CLI::
|
144
|
+
Abide::CLI::OUTPUT.simple "Label include: #{@data[:label_include]}"
|
140
145
|
AbideDevUtils::Jira.new_issues_from_xccdf(
|
141
146
|
project,
|
142
147
|
path,
|
143
148
|
epic: @data[:epic],
|
144
149
|
dry_run: @data[:dry_run],
|
150
|
+
explain: @data[:explain],
|
145
151
|
label_include: @data[:label_include],
|
146
152
|
)
|
147
153
|
end
|
@@ -12,19 +12,20 @@ module AbideDevUtils
|
|
12
12
|
if !!@dry_run
|
13
13
|
case method_name
|
14
14
|
when %r{^create}
|
15
|
-
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{
|
15
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')})")
|
16
16
|
sleep 0.1
|
17
17
|
return DummyIssue.new if args[0].match?(%r{^issue$})
|
18
18
|
return DummySubtask.new if args[0].match?(%r{^subtask$})
|
19
19
|
when %r{^find}
|
20
|
-
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{
|
20
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args[0]}, #{kwargs.inspect})")
|
21
21
|
return DummyIssue.new if args[0].match?(%r{^issue$})
|
22
22
|
return DummySubtask.new if args[0].match?(%r{^subtask$})
|
23
23
|
return DummyProject.new if args[0].match?(%r{^project$})
|
24
|
+
return [] if args[0].match?(%r{^issues_by_jql$})
|
24
25
|
|
25
26
|
"Dummy #{args[0].capitalize}"
|
26
27
|
else
|
27
|
-
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args.map(&:inspect).join(', ')})")
|
28
|
+
AbideDevUtils::Output.simple("DRY RUN: #{self.class.name}##{method_name}(#{args.map(&:inspect).join(', ')}, #{kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')})")
|
28
29
|
end
|
29
30
|
else
|
30
31
|
super(*args, **kwargs)
|
@@ -77,7 +78,7 @@ module AbideDevUtils
|
|
77
78
|
class Dummy
|
78
79
|
attr_reader :dummy
|
79
80
|
|
80
|
-
def initialize
|
81
|
+
def initialize(*_args, **_kwargs)
|
81
82
|
@dummy = true
|
82
83
|
end
|
83
84
|
end
|
@@ -85,10 +86,14 @@ module AbideDevUtils
|
|
85
86
|
class DummyIssue < Dummy
|
86
87
|
attr_reader :summary, :key
|
87
88
|
|
88
|
-
def initialize
|
89
|
+
def initialize(summary = 'Dummy Issue', key = 'DUM-111')
|
89
90
|
super
|
90
|
-
@summary =
|
91
|
-
@key =
|
91
|
+
@summary = summary
|
92
|
+
@key = key
|
93
|
+
end
|
94
|
+
|
95
|
+
def labels
|
96
|
+
@labels ||= ['abide_dev_utils']
|
92
97
|
end
|
93
98
|
|
94
99
|
def attrs
|
@@ -102,10 +107,8 @@ module AbideDevUtils
|
|
102
107
|
end
|
103
108
|
|
104
109
|
class DummySubtask < DummyIssue
|
105
|
-
def initialize
|
106
|
-
super
|
107
|
-
@summary = 'Dummy Subtask'
|
108
|
-
@key = 'DUM-222'
|
110
|
+
def initialize(summary = 'Dummy Subtask', key = 'DUM-222')
|
111
|
+
super(summary, key)
|
109
112
|
end
|
110
113
|
|
111
114
|
def attrs
|
@@ -122,7 +125,7 @@ module AbideDevUtils
|
|
122
125
|
class DummyProject < Dummy
|
123
126
|
attr_reader :key, :issues
|
124
127
|
|
125
|
-
def initialize
|
128
|
+
def initialize(key = 'DUM', issues = [DummyIssue.new, DummySubtask.new])
|
126
129
|
super
|
127
130
|
@key = 'DUM'
|
128
131
|
@issues = [DummyIssue.new, DummySubtask.new]
|
@@ -32,6 +32,12 @@ module AbideDevUtils
|
|
32
32
|
iss
|
33
33
|
end
|
34
34
|
|
35
|
+
# @param jql [String] The JQL query
|
36
|
+
# @return [Array<JIRA::Resource::Issue>]
|
37
|
+
def issues_by_jql(jql)
|
38
|
+
client.Issue.jql(jql, max_results: 1000)
|
39
|
+
end
|
40
|
+
|
35
41
|
# @param id [String] The issuetype ID or name
|
36
42
|
def issuetype(id)
|
37
43
|
return id if id.is_a?(client.Issuetype.target_class)
|
data/lib/abide_dev_utils/jira.rb
CHANGED
@@ -43,7 +43,9 @@ module AbideDevUtils
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
ToCreateData = Struct.new(:summary, :labels, :should_create, :metadata)
|
47
|
+
|
48
|
+
def self.new_issues_from_xccdf(project, xccdf_path, epic: nil, dry_run: false, explain: false, label_include: nil)
|
47
49
|
client(dry_run: dry_run) # Initializes the client if needed
|
48
50
|
i_attrs = client.helper.all_project_issues_attrs(project)
|
49
51
|
xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf_path)
|
@@ -64,42 +66,112 @@ module AbideDevUtils
|
|
64
66
|
end
|
65
67
|
# Now we need to find out which issues we need to create for the benchmark
|
66
68
|
# The profiles that the control belongs to will be added as an issue label
|
67
|
-
to_create =
|
69
|
+
to_create = []
|
68
70
|
summaries_from_xccdf(xccdf).each do |profile_summary, control_summaries|
|
69
|
-
control_summaries.
|
70
|
-
|
71
|
-
|
71
|
+
control_summaries.each do |control_summary|
|
72
|
+
existing_to_create = to_create.find { |tc| tc.summary == control_summary }
|
73
|
+
if existing_to_create
|
74
|
+
existing_to_create.labels << profile_summary.split.join('_').downcase
|
72
75
|
else
|
73
|
-
|
76
|
+
new_to_create = ToCreateData.new(
|
77
|
+
summary: control_summary,
|
78
|
+
labels: [profile_summary.split.join('_').downcase],
|
79
|
+
should_create: true,
|
80
|
+
metadata: {
|
81
|
+
epic_key: epic.key,
|
82
|
+
project: project,
|
83
|
+
},
|
84
|
+
)
|
85
|
+
to_create << new_to_create
|
74
86
|
end
|
75
87
|
end
|
76
88
|
end
|
77
89
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
labels.any? { |l| l.match?(label_include) }
|
82
|
-
end
|
83
|
-
end
|
90
|
+
final_to_create = filter_to_create(to_create, label_include, project, epic)
|
91
|
+
|
92
|
+
return explain_this(to_create) if explain
|
84
93
|
|
85
|
-
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create #{
|
94
|
+
unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create #{final_to_create.count} new Jira issues?")
|
86
95
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
|
87
96
|
exit(0)
|
88
97
|
end
|
89
98
|
|
90
99
|
progress = AbideDevUtils::Output.progress(title: "#{dr_prefix(dry_run)}Creating issues",
|
91
|
-
total:
|
100
|
+
total: final_to_create.count,
|
92
101
|
format: PROGRESS_BAR_FORMAT)
|
93
|
-
|
94
|
-
abrev =
|
102
|
+
final_to_create.each do |tc|
|
103
|
+
abrev = tc.summary.length > 40 ? tc.summary[0..60] : tc.summary
|
95
104
|
progress.log("#{dr_prefix(dry_run)}Creating #{abrev}...")
|
96
|
-
client.create(:issue, project: project, summary:
|
105
|
+
client.create(:issue, project: project, summary: tc.summary, labels: tc.labels, epic_link: epic)
|
97
106
|
progress.increment
|
98
107
|
end
|
99
108
|
progress.finish
|
100
109
|
AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Done creating tasks in Epic '#{epic.summary}'")
|
101
110
|
end
|
102
111
|
|
112
|
+
def self.filter_to_create(to_create, label_include, project, epic)
|
113
|
+
not_already_exists = filter_already_exists(to_create, project, epic)
|
114
|
+
AbideDevUtils::Output.simple(
|
115
|
+
"Filtered out #{to_create.count - not_already_exists.count} issues that already existed",
|
116
|
+
)
|
117
|
+
only_label_include = filter_label_include(not_already_exists, label_include)
|
118
|
+
AbideDevUtils::Output.simple(
|
119
|
+
"Filtered out #{not_already_exists.count - only_label_include.count} issues that didn't include the label #{label_include}",
|
120
|
+
)
|
121
|
+
only_label_include
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.filter_already_exists(to_create, project, epic)
|
125
|
+
AbideDevUtils::Output.simple('Checking if issues already exist...')
|
126
|
+
project = client.find(:project, project)
|
127
|
+
epic = client.find(:issue, epic)
|
128
|
+
issues = client.find(:issues_by_jql, "project = \"#{project.key}\" AND 'Epic Link' = \"#{epic.key}\"")
|
129
|
+
to_create.reject do |tc|
|
130
|
+
if issues.any? { |i| i.summary == tc.summary }
|
131
|
+
tc.metadata[:already_exists] = true
|
132
|
+
tc.should_create = false
|
133
|
+
true
|
134
|
+
else
|
135
|
+
tc.metadata[:already_exists] = false
|
136
|
+
false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# If we have a label_include, we need to filter out any controls that don't have that label
|
142
|
+
def self.filter_label_include(to_create, label_include)
|
143
|
+
return to_create if label_include.nil?
|
144
|
+
|
145
|
+
AbideDevUtils::Output.simple("Filtering out controls that don't match label include: #{label_include}")
|
146
|
+
to_create.select do |tc|
|
147
|
+
if tc.labels.any? { |l| l.match?(label_include) }
|
148
|
+
tc.metadata[:label_include] = true
|
149
|
+
true
|
150
|
+
else
|
151
|
+
tc.metadata[:label_include] = false
|
152
|
+
tc.should_create = false
|
153
|
+
false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.explain_this(to_create)
|
159
|
+
should_create = to_create.select(&:should_create)
|
160
|
+
should_not_create = to_create.reject(&:should_create)
|
161
|
+
AbideDevUtils::Output.simple(AbideDevUtils::Output.simple_section_separator('EXPLAIN'))
|
162
|
+
AbideDevUtils::Output.simple("Will create #{should_create.count} issues")
|
163
|
+
AbideDevUtils::Output.simple("Will not create #{should_not_create.count} issues")
|
164
|
+
AbideDevUtils::Output.simple(AbideDevUtils::Output.simple_section_separator('WILL CREATE'))
|
165
|
+
should_create.each do |tc|
|
166
|
+
AbideDevUtils::Output.simple("\"#{tc.summary}\"; labels: #{tc.labels}; metadata: #{tc.metadata}")
|
167
|
+
end
|
168
|
+
AbideDevUtils::Output.simple(AbideDevUtils::Output.simple_section_separator('WILL NOT CREATE'))
|
169
|
+
should_not_create.each do |tc|
|
170
|
+
AbideDevUtils::Output.simple("\"#{tc.summary}\"; labels: #{tc.labels}; metadata: #{tc.metadata}")
|
171
|
+
end
|
172
|
+
exit(0)
|
173
|
+
end
|
174
|
+
|
103
175
|
def self.new_issues_from_xccdf_diff(project, xccdf1_path, xccdf2_path, epic: nil, dry_run: false, auto_approve: false, diff_opts: {})
|
104
176
|
require 'abide_dev_utils/xccdf/diff'
|
105
177
|
diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(xccdf1_path, xccdf2_path, diff_opts)
|
@@ -10,6 +10,14 @@ require 'abide_dev_utils/files'
|
|
10
10
|
module AbideDevUtils
|
11
11
|
module Output
|
12
12
|
FWRITER = AbideDevUtils::Files::Writer.new
|
13
|
+
def self.simple_section_separator(section_text, sepchar: '#', width: 60, **_)
|
14
|
+
section_text = section_text.to_s
|
15
|
+
section_text = section_text[0..width - 4] if section_text.length > width
|
16
|
+
section_text = " #{section_text} "
|
17
|
+
section_sep_line = sepchar * width
|
18
|
+
[section_sep_line, section_text.center(width, sepchar), section_sep_line].join("\n")
|
19
|
+
end
|
20
|
+
|
13
21
|
def self.simple(msg, stream: $stdout, **_)
|
14
22
|
case msg
|
15
23
|
when Hash
|
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.17.
|
4
|
+
version: 0.17.1
|
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-
|
11
|
+
date: 2023-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|