abide_dev_utils 0.17.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|