abide_dev_utils 0.16.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 220a0a755c0e337d22a853e106935f4355564e51a759eb93967e3aeba5a9f020
4
- data.tar.gz: e0272122e07a4e53d3efa71486de5dc7a0229ca0d22214b3311c94df0c90100b
3
+ metadata.gz: 0216511efe504da6597b81a7b494975377b8afe013697e37f9985467a6a4fa14
4
+ data.tar.gz: '08265323331b31cb17e875b951ce89dfcb83bbb9649c0df97513cff26355f713'
5
5
  SHA512:
6
- metadata.gz: c7710f102655653f4181694c8dd076acff1dfd8040120c54157bc77a89f3db4a892854d2110ac4a47974ead2fdc23c3b3028c4459aa9e7bf75145e71fcebad0b
7
- data.tar.gz: a5d0d101010f6ba4129346c4c4447f433b5a61e36e9000c3dab653a1709b78ff08203ec2dd014e61489d09eb2a78badfb51e233d8cbe33d85c903c3654cae90f
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.16.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 (>= 6.23)
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)
@@ -17,7 +17,7 @@ GEM
17
17
  remote: https://rubygems.org/
18
18
  specs:
19
19
  CFPropertyList (2.3.6)
20
- activesupport (7.0.4.3)
20
+ activesupport (7.0.7.2)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -29,15 +29,15 @@ GEM
29
29
  console (~> 1.10)
30
30
  nio4r (~> 2.3)
31
31
  timers (~> 4.1)
32
- async-http (0.56.6)
32
+ async-http (0.60.2)
33
33
  async (>= 1.25)
34
34
  async-io (>= 1.28)
35
35
  async-pool (>= 0.2)
36
- protocol-http (~> 0.22.0)
37
- protocol-http1 (~> 0.14.0)
38
- protocol-http2 (~> 0.14.0)
39
- traces (~> 0.4.0)
40
- async-http-faraday (0.11.0)
36
+ protocol-http (~> 0.24.0)
37
+ protocol-http1 (~> 0.15.0)
38
+ protocol-http2 (~> 0.15.0)
39
+ traces (>= 0.10.0)
40
+ async-http-faraday (0.12.0)
41
41
  async-http (~> 0.42)
42
42
  faraday
43
43
  async-io (1.33.0)
@@ -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 (1.8.0)
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)
@@ -120,7 +120,7 @@ GEM
120
120
  hiera (3.12.0)
121
121
  hocon (1.4.0)
122
122
  httpclient (2.8.3)
123
- i18n (1.12.0)
123
+ i18n (1.14.1)
124
124
  concurrent-ruby (~> 1.0)
125
125
  jgrep (1.5.4)
126
126
  jira-ruby (2.3.0)
@@ -133,12 +133,16 @@ GEM
133
133
  memoist (0.16.2)
134
134
  method_source (1.0.0)
135
135
  mini_mime (1.1.2)
136
- minitest (5.18.0)
136
+ minitest (5.19.0)
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)
144
+ nokogiri (1.15.2-x86_64-linux)
145
+ racc (~> 1.4)
142
146
  oauth (0.6.2)
143
147
  snaky_hash (~> 2.0)
144
148
  version_gem (~> 1.1)
@@ -150,16 +154,27 @@ GEM
150
154
  parser (3.1.2.0)
151
155
  ast (~> 2.4.1)
152
156
  protocol-hpack (1.4.2)
153
- protocol-http (0.22.6)
154
- protocol-http1 (0.14.4)
157
+ protocol-http (0.24.7)
158
+ protocol-http1 (0.15.1)
155
159
  protocol-http (~> 0.22)
156
- protocol-http2 (0.14.2)
160
+ protocol-http2 (0.15.1)
157
161
  protocol-hpack (~> 1.4)
158
162
  protocol-http (~> 0.18)
159
163
  pry (0.14.1)
160
164
  coderay (~> 1.1)
161
165
  method_source (~> 1.0)
162
166
  public_suffix (4.0.7)
167
+ puppet (7.24.0)
168
+ concurrent-ruby (~> 1.0, < 1.2.0)
169
+ deep_merge (~> 1.0)
170
+ facter (> 2.0.1, < 5)
171
+ fast_gettext (>= 1.1, < 3)
172
+ hiera (>= 3.2.1, < 4)
173
+ locale (~> 2.1)
174
+ multi_json (~> 1.10)
175
+ puppet-resource_api (~> 1.5)
176
+ scanf (~> 1.0)
177
+ semantic_puppet (~> 1.0)
163
178
  puppet (7.24.0-universal-darwin)
164
179
  CFPropertyList (~> 2.2)
165
180
  concurrent-ruby (~> 1.0, < 1.2.0)
@@ -241,7 +256,7 @@ GEM
241
256
  version_gem (~> 1.1, >= 1.1.1)
242
257
  thor (1.2.2)
243
258
  timers (4.3.3)
244
- traces (0.4.1)
259
+ traces (0.11.1)
245
260
  trailblazer-option (0.1.2)
246
261
  tzinfo (2.0.6)
247
262
  concurrent-ruby (~> 1.0)
@@ -252,6 +267,7 @@ GEM
252
267
  yard (0.9.34)
253
268
 
254
269
  PLATFORMS
270
+ arm64-darwin-22
255
271
  x86_64-darwin-19
256
272
  x86_64-darwin-20
257
273
  x86_64-linux
@@ -260,7 +276,7 @@ DEPENDENCIES
260
276
  abide_dev_utils!
261
277
  bundler
262
278
  console
263
- fast_gettext (~> 1.8)
279
+ fast_gettext (>= 2.0)
264
280
  gem-release
265
281
  github_changelog_generator
266
282
  pry
@@ -273,4 +289,4 @@ DEPENDENCIES
273
289
  rubocop-rspec (~> 2.1)
274
290
 
275
291
  BUNDLED WITH
276
- 2.3.9
292
+ 2.4.19
@@ -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', '>= 6.23'
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', '~> 1.8'
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
- @md.add_ul('Supported Levels:')
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
- @md.add_ul('Supported Profiles:')
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|
@@ -459,7 +469,7 @@ module AbideDevUtils
459
469
 
460
470
  @control.title.nil? ? out_str.unshift(" #{@control.id.dump}:") : out_str.unshift(" #{@control.title.dump}:")
461
471
  out_str.unshift(' control_configs:')
462
- out_str.unshift("#{@module_name}::config:")
472
+ out_str.unshift("#{@module_name.split('-').last}::config:")
463
473
  @md.add_ul('Hiera Configuration Example:')
464
474
  @md.add_code_block(out_str.join("\n"), language: 'yaml')
465
475
  rescue StandardError => e
@@ -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
- client = JIRA.client
42
- myself = JIRA.myself(client)
43
- return if myself.attrs['name'].empty?
38
+ return if AbideDevUtils::Jira.client.myself.attrs['displayName'].empty?
44
39
 
45
- Abide::CLI::OUTPUT.simple("Successfully authenticated user #{myself.attrs['name']}!")
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
- client = JIRA.client(options: {})
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
- client = JIRA.client(options: {})
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
- JIRA.bulk_new_subtask(client, JIRA.issue(client, issue.attrs['key']), subtasks) unless subtasks.empty?
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
- JIRA.new_issues_from_coverage(client, proj, JSON.parse(f.read), dry_run: @data[:dry_run])
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
- @data[:dry_run] = false if @data[:dry_run].nil?
135
- client = JIRA.client(options: {})
136
- proj = JIRA.project(client, project)
137
- JIRA.new_issues_from_xccdf(client, proj, path, epic: @data[:epic], dry_run: @data[:dry_run])
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
- @data[:dry_run] = false if @data[:dry_run].nil?
171
- client = JIRA.client(options: {})
172
- proj = JIRA.project(client, project)
173
- JIRA.new_issues_from_xccdf_diff(client,
174
- proj,
175
- path1,
176
- path2,
177
- epic: @data[:epic],
178
- dry_run: @data[:dry_run],
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
@@ -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,195 +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.project(client, project)
18
- client.Project.find(project)
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['reporter'] = myself(client)
71
- fields['issuetype'] = issuetype(client, 'Task')
72
- fields['priority'] = priority(client, '6')
73
- fields['description'] = description if description
74
- fields['labels'] = labels
75
- epic = issue(client, epic) if epic && !epic.is_a?(JIRA::Resource::Issue)
76
- fields['customfield_10006'] = epic.key if epic # Epic_Link
77
- iss = client.Issue.build
78
- raise ERRORS::CreateIssueError, iss.attrs unless iss.save({ 'fields' => fields })
79
-
80
- iss
81
- end
82
-
83
- def self.new_epic(client, project, summary, dry_run: false)
84
- AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Creating epic '#{summary}'")
85
- if dry_run
86
- sleep(0.2)
87
- return Dummy.new(summary)
88
- end
89
- fields = {
90
- 'summary' => summary,
91
- 'project' => project(client, project),
92
- 'reporter' => myself(client),
93
- 'issuetype' => issuetype(client, 'Epic'),
94
- 'customfield_10007' => summary, # Epic Name
95
- }
96
- iss = client.Issue.build
97
- raise ERRORS::CreateEpicError, iss.attrs unless iss.save({ 'fields' => fields })
98
-
99
- iss
100
- end
101
-
102
- # This should probably be threaded in the future
103
- def self.bulk_new_issue(client, project, summaries, dry_run: false)
104
- summaries.each { |s| new_issue(client, project, s, dry_run: dry_run) }
105
- end
106
-
107
- def self.new_subtask(client, issue, summary, dry_run: false)
108
- if dry_run
109
- sleep(0.2)
110
- return Dummy.new
111
- end
112
- issue_fields = issue.attrs['fields']
113
- fields = {}
114
- fields['parent'] = issue
115
- fields['summary'] = summary
116
- fields['project'] = issue_fields['project']
117
- fields['reporter'] = myself(client)
118
- fields['issuetype'] = issuetype(client, '5')
119
- fields['priority'] = issue_fields['priority']
120
- subtask = client.Issue.build
121
- raise ERRORS::CreateSubtaskError, subtask.attrs unless subtask.save({ 'fields' => fields })
122
-
123
- subtask
124
- end
125
-
126
- def self.bulk_new_subtask(client, issue, summaries, dry_run: false)
127
- summaries.each do |s|
128
- new_subtask(client, issue, s, dry_run: dry_run)
129
- end
130
- end
131
-
132
- def self.client(options: {})
133
- opts = merge_options(options)
134
- return client_from_prompts if opts.empty?
135
-
136
- opts[:username] = AbideDevUtils::Prompt.username if opts[:username].nil?
137
- opts[:password] = AbideDevUtils::Prompt.password if opts[:password].nil?
138
- opts[:site] = AbideDevUtils::Prompt.single_line('Jira URL') if opts[:site].nil?
139
- opts[:context_path] = '' if opts[:context_path].nil?
140
- opts[:auth_type] = :basic if opts[:auth_type].nil?
141
- JIRA::Client.new(opts)
142
- end
143
-
144
- def self.client_from_prompts(http_debug: false)
145
- options = {}
146
- options[:username] = AbideDevUtils::Prompt.username
147
- options[:password] = AbideDevUtils::Prompt.password
148
- options[:site] = AbideDevUtils::Prompt.single_line('Jira URL')
149
- options[:context_path] = ''
150
- options[:auth_type] = :basic
151
- options[:http_debug] = http_debug
152
- JIRA::Client.new(options)
153
- end
18
+ def self.client(memo: true, dry_run: false, **options)
19
+ return AbideDevUtils::Jira::Client.new(dry_run: dry_run, **options) unless memo
154
20
 
155
- def self.project_from_prompts(http_debug: false)
156
- client = client_from_prompts(http_debug)
157
- project = AbideDevUtils::Prompt.single_line('Project').upcase
158
- client.Project.find(project)
21
+ @client ||= AbideDevUtils::Jira::Client.new(dry_run: dry_run, **options)
159
22
  end
160
23
 
161
24
  def self.new_issues_from_coverage(client, project, report, dry_run: false)
162
25
  dr_prefix = dry_run ? 'DRY RUN: ' : ''
163
- i_attrs = all_project_issues_attrs(project)
26
+ client(dry_run: dry_run) # Initializes the client if needed
27
+ i_attrs = client.helper.all_project_issues_attrs(project)
164
28
  rep_sums = summaries_from_coverage_report(report)
165
29
  rep_sums.each do |k, v|
166
- next if summary_exist?(k, i_attrs)
30
+ next if client.helper.summary_exist?(k, i_attrs)
167
31
 
168
- parent = new_issue(client, project.attrs['key'], k.to_s, dry_run: dry_run)
169
- AbideDevUtils::Output.simple("#{dr_prefix}Created parent issue #{k}")
170
- 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)
171
34
  AbideDevUtils::Output.simple("#{dr_prefix}Creating subtasks, this can take a while...")
172
35
  progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Subtasks", total: nil)
173
36
  v.each do |s|
174
- next if summary_exist?(s, i_attrs)
37
+ next if client.helper.summary_exist?(s, i_attrs)
175
38
 
176
39
  progress.title = "#{dr_prefix}#{s}"
177
- new_subtask(client, parent_issue, s, dry_run: dry_run)
40
+ client.create(:subtask, parent: parent, summary: s)
178
41
  progress.increment
179
42
  end
180
43
  end
181
44
  end
182
45
 
183
- def self.new_issues_from_xccdf(client, project, xccdf_path, epic: nil, dry_run: false)
184
- i_attrs = all_project_issues_attrs(project)
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)
185
49
  xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf_path)
186
50
  # We need to get the actual epic Issue object, or create it if it doesn't exist
187
51
  epic = if epic.nil?
188
52
  new_epic_summary = "#{COV_PARENT_SUMMARY_PREFIX}#{xccdf.title}"
189
- if summary_exist?(new_epic_summary, i_attrs)
190
- issue(client, new_epic_summary)
53
+ if client.helper.summary_exist?(new_epic_summary, i_attrs)
54
+ client.find(:issue, new_epic_summary)
191
55
  else
192
56
  unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?")
193
57
  AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
194
58
  exit(0)
195
59
  end
196
- new_epic(client, project.key, new_epic_summary, dry_run: dry_run)
60
+ client.create(:issue, project: project, summary: new_epic_summary, issuetype: 'Epic', epic_name: new_epic_summary)
197
61
  end
198
62
  else
199
- issue(client, epic)
63
+ client.find(:issue, epic)
200
64
  end
201
65
  # Now we need to find out which issues we need to create for the benchmark
202
66
  # The profiles that the control belongs to will be added as an issue label
203
67
  to_create = {}
204
68
  summaries_from_xccdf(xccdf).each do |profile_summary, control_summaries|
205
- 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|
206
70
  if to_create.key?(control_summary)
207
71
  to_create[control_summary] << profile_summary.split.join('_').downcase
208
72
  else
@@ -211,6 +75,13 @@ module AbideDevUtils
211
75
  end
212
76
  end
213
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
+
214
85
  unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create #{to_create.keys.count} new Jira issues?")
215
86
  AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
216
87
  exit(0)
@@ -222,31 +93,32 @@ module AbideDevUtils
222
93
  to_create.each do |control_summary, labels|
223
94
  abrev = control_summary.length > 40 ? control_summary[0..60] : control_summary
224
95
  progress.log("#{dr_prefix(dry_run)}Creating #{abrev}...")
225
- new_issue(client, project.key, control_summary, labels: labels, epic: epic, dry_run: dry_run)
96
+ client.create(:issue, project: project, summary: control_summary, labels: labels, epic_link: epic)
226
97
  progress.increment
227
98
  end
228
99
  progress.finish
229
100
  AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Done creating tasks in Epic '#{epic.summary}'")
230
101
  end
231
102
 
232
- def self.new_issues_from_xccdf_diff(client, project, xccdf1_path, xccdf2_path, epic: nil, dry_run: false, auto_approve: false, diff_opts: {})
103
+ def self.new_issues_from_xccdf_diff(project, xccdf1_path, xccdf2_path, epic: nil, dry_run: false, auto_approve: false, diff_opts: {})
233
104
  require 'abide_dev_utils/xccdf/diff'
234
105
  diff = AbideDevUtils::XCCDF::Diff::BenchmarkDiff.new(xccdf1_path, xccdf2_path, diff_opts)
235
- i_attrs = all_project_issues_attrs(project)
106
+ client(dry_run: dry_run) # Initializes the client if needed
107
+ i_attrs = client.helper.all_project_issues_attrs(project)
236
108
  # We need to get the actual epic Issue object, or create it if it doesn't exist
237
109
  epic = if epic.nil?
238
- new_epic_summary = "#{UPD_EPIC_SUMMARY_PREFIX}#{diff.this.title}: v#{diff.this.version} -> #{diff.other.version}"
239
- if summary_exist?(new_epic_summary, i_attrs)
240
- issue(client, new_epic_summary)
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)
241
113
  else
242
- unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?", auto_approve: auto_approve)
114
+ unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?")
243
115
  AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
244
116
  exit(0)
245
117
  end
246
- new_epic(client, project.key, new_epic_summary, dry_run: dry_run)
118
+ client.create(:issue, project: project, summary: new_epic_summary, issuetype: 'Epic', epic_name: new_epic_summary)
247
119
  end
248
120
  else
249
- issue(client, epic)
121
+ client.find(:issue, epic)
250
122
  end
251
123
  to_create = {}
252
124
  diff.diff[:rules].each do |key, val|
@@ -288,7 +160,7 @@ module AbideDevUtils
288
160
  format: PROGRESS_BAR_FORMAT)
289
161
  approved_create.each do |summary, description|
290
162
  progress.log("#{dr_prefix(dry_run)}Creating #{summary}...")
291
- new_issue(client, project.key, summary, description: description, labels: [], epic: epic, dry_run: dry_run)
163
+ client.create(:issue, project: project, summary: summary, description: description, labels: [], epic_link: epic)
292
164
  progress.increment
293
165
  end
294
166
  progress.finish
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.16.0"
4
+ VERSION = "0.17.0"
5
5
  end
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.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - abide-team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-21 00:00:00.000000000 Z
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: '6.23'
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: '6.23'
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: '1.8'
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: '1.8'
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
@@ -448,7 +454,7 @@ metadata:
448
454
  homepage_uri: https://github.com/puppetlabs/abide_dev_utils
449
455
  source_code_uri: https://github.com/puppetlabs/abide_dev_utils
450
456
  changelog_uri: https://github.com/puppetlabs/abide_dev_utils
451
- post_install_message:
457
+ post_install_message:
452
458
  rdoc_options: []
453
459
  require_paths:
454
460
  - lib
@@ -463,8 +469,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
463
469
  - !ruby/object:Gem::Version
464
470
  version: '0'
465
471
  requirements: []
466
- rubygems_version: 3.1.6
467
- signing_key:
472
+ rubygems_version: 3.4.18
473
+ signing_key:
468
474
  specification_version: 4
469
475
  summary: Helper utilities for developing compliance Puppet code
470
476
  test_files: []