puppet-lint-module_reference-check 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 165ae50c695f4525d85426dea4ec555b9d4f44b7321f642d86783277319787fb
4
+ data.tar.gz: 952b6da27bc82a66b29a23df6bae49ecd16e742750a94cb75f0ce0d4646af1f8
5
+ SHA512:
6
+ metadata.gz: 96cdff2aed65b20e028d2093dc27668a7b32c8479ad3f552bc9bbdc59f655a6858d3ee2a36713367b949242978cd048854e0cb2c0a2b6cabd6d8c78caf476587
7
+ data.tar.gz: 124c80e7b55984c5a06d2fc5ecf70e192625d8984003d2f9277fbce6d4130e08028c4ce6140d4ae1105d44e6d155e6d9eee7ec7ef704212a6424204841c3f3ad
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 DO! DevOps
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # Puppet lint module reference check
2
+
3
+ This checks whether used modules are properly referenced in the comments by these rules:
4
+
5
+ - All internal prefixed with profile:: or role:: based on the Puppet role/profile concept) modules have to be
6
+ referenced using a @see tag
7
+ - All component modules have to be referenced like the following
8
+ - All used classes and defined types need to be gathered in a comma-separated list of regexps in a @ref tag
9
+ - The full module name (vendor-module) has to be referenced in a @note tag
10
+ - At minimum one @see tag with a reference to the puppet forge page of the component module
11
+ - Example:
12
+ ```
13
+ # @ref apache.*,a2mod
14
+ # @note puppetlabs-apache
15
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
16
+ ```
17
+ - Modules referenced by features (using our own role::include_features function) have to be referenced with @see
18
+ - The module references have to be sorted alphabetically and grouped by this:
19
+ - component module
20
+ - internal modules
21
+ - modules referenced by features
22
+
23
+ ## Usage
24
+
25
+ To use the plugin, add the following line to the Gemfile:
26
+
27
+ gem 'puppet-lint-module_reference-check'
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../puppet-lint-module_reference-check/reference'
4
+
5
+ # Find the header comments for a class or a defined type
6
+ #
7
+ # @param tokens The list of all tokens
8
+ # @param token_start The index of the token to start from upwards
9
+ # @return The head comments
10
+ def get_comments(tokens, token_start)
11
+ comments = []
12
+ token_pointer = token_start - 1
13
+ while token_pointer >= 0
14
+ break unless %i[COMMENT NEWLINE].include? tokens[token_pointer].type
15
+
16
+ comments.append(tokens[token_pointer])
17
+ token_pointer -= 1
18
+ end
19
+ comments.reject { |comment| comment.type == :NEWLINE }.reverse!
20
+ end
21
+
22
+ def get_first_index_of_type(comments, type, feature_refs)
23
+ comments.each_with_index do |comment, index|
24
+ comment.match(/@see (?<name>\S+)/) do |match|
25
+ next if feature_refs.any? { |ref| ref[:name] == match.named_captures['name'] }
26
+ return index if match.named_captures['name'].match?(INTERNAL_MODULE_REGEXP) && type == REF_TYPE_ENUM[:internal]
27
+ return index if !match.named_captures['name'].match?(INTERNAL_MODULE_REGEXP) && type == REF_TYPE_ENUM[:component]
28
+ end
29
+ end
30
+ 0
31
+ end
32
+
33
+ PuppetLint.new_check(:module_reference) do
34
+ def initialize
35
+ @workflow = Reference.new
36
+ # noinspection RubySuperCallWithoutSuperclassInspection
37
+ super
38
+ end
39
+
40
+ def warn(message, line = 1, column = 1)
41
+ notify :warning, { message: message, line: line, column: column }
42
+ false
43
+ end
44
+
45
+ def check_sees_exist(references, comments)
46
+ references.each do |reference|
47
+ next if comments.any? { |comment| comment.match?("^@see #{reference[:name]}\\s?") }
48
+
49
+ return warn(
50
+ "Module #{reference[:name]} not referenced in the comments",
51
+ reference[:token].line,
52
+ reference[:token].column
53
+ )
54
+ end
55
+ true
56
+ end
57
+
58
+ def check_reference_order(references, comments, below_index)
59
+ references.each do |reference|
60
+ if comments.find_index { |comment| comment.match?("^@see #{reference[:name]}\\s?") } < below_index
61
+ return warn("Reference to #{reference[:name]} was found higher than #{comments[below_index]}")
62
+ end
63
+ end
64
+ true
65
+ end
66
+
67
+ def check_internal_references(comments)
68
+ internal_references = @workflow.references.filter { |ref| ref[:type] == REF_TYPE_ENUM[:internal] }
69
+ return false unless check_sees_exist(internal_references, comments)
70
+ return false unless check_reference_order(
71
+ internal_references,
72
+ comments,
73
+ get_first_index_of_type(
74
+ comments,
75
+ REF_TYPE_ENUM[:component],
76
+ @workflow.references.filter { |ref| ref[:type] == REF_TYPE_ENUM[:feature] }
77
+ )
78
+ )
79
+
80
+ true
81
+ end
82
+
83
+ def find_ref_index(name, comments)
84
+ comments.each_with_index do |comment, index|
85
+ comment.match(/^@ref (?<ref_regexps>.+)\s?/) do |match|
86
+ match.named_captures['ref_regexps'].split(',').each do |ref_regexp|
87
+ return index if name.match?(ref_regexp)
88
+ end
89
+ end
90
+ end
91
+ nil
92
+ end
93
+
94
+ def check_component_references(comments)
95
+ component_refs = @workflow.references.filter { |ref| ref[:type] == REF_TYPE_ENUM[:component] }
96
+ component_refs.each do |reference|
97
+ ref_index = find_ref_index(reference[:name], comments)
98
+ return warn("Can't find @ref tag for reference #{reference[:name]}") if ref_index.nil?
99
+ return warn("Missing @note tag for reference #{reference[:name]}") unless comments[ref_index + 1].match?(/@note/)
100
+ return warn("Missing @see tag for reference #{reference[:name]}") unless comments[ref_index + 2].match?(/@see/)
101
+ next if comments[ref_index + 2].include?('https://forge.puppet.com/')
102
+
103
+ return warn("First @see for reference #{reference[:name]} is not the Puppet forge")
104
+ end
105
+ true
106
+ end
107
+
108
+ def check_feature_references(comments)
109
+ feature_refs = @workflow.references.filter { |ref| ref[:type] == REF_TYPE_ENUM[:feature] }
110
+ return false unless check_sees_exist(feature_refs, comments)
111
+ return false unless check_reference_order(
112
+ feature_refs,
113
+ comments,
114
+ get_first_index_of_type(
115
+ comments,
116
+ REF_TYPE_ENUM[:internal],
117
+ @workflow.references.filter { |ref| ref[:type] == REF_TYPE_ENUM[:feature] }
118
+ )
119
+ )
120
+
121
+ true
122
+ end
123
+
124
+ def get_relevant_name(captures, comments, index)
125
+ return_object = {
126
+ name: captures['name'],
127
+ type: nil
128
+ }
129
+ if captures['type'] == 'see' && (index == 0 || index > 0 && !comments[index - 1].match(/@note/))
130
+ return return_object if captures['name'].match?(%r(https?://))
131
+
132
+ reference = @workflow.references.select { |ref| ref[:name] == captures['name'] }
133
+ return warn("Can't find referenced module #{captures['name']}") if reference.empty?
134
+
135
+ return_object[:type] = reference.first[:type]
136
+ else
137
+ @workflow
138
+ .references
139
+ .select { |ref| ref[:type] == REF_TYPE_ENUM[:component] }
140
+ .each do |ref|
141
+ next unless captures['name'].split(',').any? { |refmatch| ref[:name].match?(refmatch) }
142
+
143
+ comments[index + 1].match(/^@note (?<name>.+)$/) do |matchdata|
144
+ return_object[:name] = matchdata['name']
145
+ return_object[:type] = ref[:type]
146
+ break
147
+ end
148
+ end
149
+ end
150
+ return_object
151
+ end
152
+
153
+ def check_order(comments)
154
+ last_comment = nil
155
+ current_type = REF_TYPE_ENUM[:component]
156
+ comments.each_with_index do |comment, index|
157
+ comment.match(/@(?<type>see|ref) (?<name>\S+)/) do |match|
158
+ ref_object = get_relevant_name(match.named_captures, comments, index)
159
+ return false unless ref_object
160
+
161
+ current_comment = ref_object[:name]
162
+ return warn("No relevant name found for #{comment}") if current_comment.nil?
163
+ next if current_comment.match?('https?://')
164
+
165
+ if ref_object[:type] != current_type
166
+ last_comment = nil
167
+ current_type = ref_object[:type]
168
+ end
169
+ last_comment = current_comment if last_comment.nil?
170
+ return warn("#{current_comment} sorted after #{last_comment}") if last_comment > current_comment
171
+ end
172
+ end
173
+ end
174
+
175
+ # Check class or defined type indexes
176
+ def check_indexes(indexes)
177
+ indexes.each do |index|
178
+ comments = get_comments(tokens, index[:start] - 1)
179
+ .map { |comment| comment.value.strip }
180
+ .filter { |comment| comment.match?(/^@(see|note|ref)/) }
181
+ begin
182
+ @workflow.process(tokens[index[:start], index[:end]])
183
+ rescue InvalidTokenForState => e
184
+ warn(e.message, e.token.line, e.token.column)
185
+ end
186
+ return false unless check_internal_references(comments)
187
+ return false unless check_component_references(comments)
188
+ return false unless check_feature_references(comments)
189
+ return false unless check_order(comments)
190
+ end
191
+ true
192
+ end
193
+
194
+ # Run the check
195
+ def check
196
+ return unless check_indexes(class_indexes)
197
+ return unless check_indexes(defined_type_indexes)
198
+ end
199
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'reference_workflow'
4
+
5
+ REF_TYPE_ENUM = {
6
+ internal: 0,
7
+ component: 1,
8
+ feature: 2
9
+ }.freeze
10
+
11
+ INTERNAL_MODULE_REGEXP = /^(role|profile)::/.freeze
12
+
13
+ # Comment received in an invalid state
14
+ class InvalidTokenForState < StandardError
15
+ def initialize(token, state)
16
+ @token = token
17
+ @state = state
18
+ super "Can not process the token '#{@token.value.strip}' in the state #{@state}"
19
+ end
20
+
21
+ attr_reader :token
22
+ end
23
+
24
+ # A utility class to process tokens and analyze includes
25
+ class Reference
26
+ def initialize
27
+ @workflow = ReferenceWorkflow.new(self)
28
+
29
+ reset
30
+ end
31
+
32
+ def reset
33
+ @current_token = nil
34
+ @references = []
35
+ end
36
+
37
+ def get_body_start(tokens)
38
+ params_started = false
39
+ params_ended = false
40
+ params_brackets = 0
41
+ tokens.each_with_index do |token, index|
42
+ params_started = true if token.type == :LPAREN && !params_started
43
+ params_brackets += 1 if token.type == :LPAREN && params_started
44
+ params_brackets -= 1 if token.type == :RPAREN && params_started
45
+ params_ended = true if params_started && params_brackets.zero?
46
+ return index + 1 if params_ended && token.type == :LBRACE
47
+ end
48
+ warn('No class or type body found')
49
+ end
50
+
51
+ def process(tokens)
52
+ tokens = tokens.drop(get_body_start(tokens))
53
+ feature_includes = []
54
+ tokens.reject { |token| %i[WHITESPACE NEWLINE INDENT].include? token.type }.each do |token|
55
+ @current_token = token
56
+ @workflow.got_include if token.value == 'include'
57
+ @workflow.got_class if token.value == 'class'
58
+ @workflow.got_features_start if token.value == 'role::include_features'
59
+ @workflow.got_feature if token.type == :LBRACK && @workflow.current == :awaiting_feature
60
+ @workflow.got_feature_end if token.type == :RBRACK && @workflow.current == :awaiting_feature_include
61
+ @workflow.got_features_end(feature_includes) if token.type == :RBRACE && @workflow.current == :got_feature_start
62
+ next unless %i[NAME SSTRING].include?(token.type)
63
+ next if %w[include class role::include_features].include?(token.value)
64
+
65
+ # noinspection RubyCaseWithoutElseBlockInspection
66
+ case @workflow.current
67
+ when :awaiting_include_name
68
+ @workflow.got_include_name(token.value)
69
+ when :awaiting_class_name
70
+ @workflow.got_class_name(token.value)
71
+ when :awaiting_feature_include
72
+ feature_includes.append(token.value)
73
+ end
74
+ end
75
+ end
76
+
77
+ def got_include_name_trigger(include_name)
78
+ @references.append(
79
+ {
80
+ type: include_name.match(INTERNAL_MODULE_REGEXP) ? REF_TYPE_ENUM[:internal] : REF_TYPE_ENUM[:component],
81
+ name: include_name,
82
+ token: @current_token
83
+ }
84
+ )
85
+ end
86
+
87
+ def got_class_name_trigger(class_name)
88
+ @references.append(
89
+ {
90
+ type: class_name.match(INTERNAL_MODULE_REGEXP) ? REF_TYPE_ENUM[:internal] : REF_TYPE_ENUM[:component],
91
+ name: class_name,
92
+ token: @current_token
93
+ }
94
+ )
95
+ end
96
+
97
+ def got_features_end_trigger(feature_includes)
98
+ feature_includes.each do |include_name|
99
+ @references.append(
100
+ {
101
+ type: REF_TYPE_ENUM[:feature],
102
+ name: include_name,
103
+ token: @current_token
104
+ }
105
+ )
106
+ end
107
+ end
108
+
109
+ def invalid_state
110
+ raise InvalidTokenForState.new @current_token, @workflow.current
111
+ end
112
+
113
+ attr_reader :references
114
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'finite_machine'
4
+
5
+ # A workflow to describe includes and class declarations
6
+ class ReferenceWorkflow < FiniteMachine::Definition
7
+ initial :start
8
+
9
+ event :got_include, from: :start, to: :awaiting_include_name
10
+ event :got_include_name, from: :awaiting_include_name, to: :start
11
+
12
+ event :got_class, from: :start, to: :awaiting_class_name
13
+ event :got_class_name, from: :awaiting_class_name, to: :start
14
+
15
+ event :got_features_start, from: :start, to: :awaiting_feature
16
+ event :got_feature, from: :awaiting_feature, to: :awaiting_feature_include
17
+ event :got_feature_end, from: :awaiting_feature_include, to: :got_feature_start
18
+ event :got_features_end, from: :got_feature_start, to: :start
19
+
20
+ on_before(:got_include_name) { |_, include_name| target.got_include_name_trigger(include_name) }
21
+ on_before(:got_class_name) { |_, class_name| target.got_class_name_trigger(class_name) }
22
+ on_before(:got_features_end) { |_, feature_includes| target.got_features_end_trigger(feature_includes) }
23
+
24
+ handle FiniteMachine::InvalidStateError, with: -> { target.invalid_state }
25
+ end
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+
5
+ describe 'module_reference' do
6
+ context 'valid code' do
7
+ let(:code) do
8
+ <<~CODE
9
+ # @ref apache
10
+ # @note puppetlabs-apache
11
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
12
+ #
13
+ # @see profile::test
14
+ #
15
+ # @see profile::testfeature - Feature "test"
16
+ class test () {
17
+ include profile::test
18
+ class {
19
+ 'apache':
20
+ }
21
+ include apache
22
+
23
+ role::include_features({
24
+ 'testfeature' => [
25
+ profile::testfeature,
26
+ ],
27
+ })
28
+ }
29
+ CODE
30
+ end
31
+
32
+ it 'should not detect any problems' do
33
+ expect(problems).to have(0).problems
34
+ end
35
+ end
36
+
37
+ context 'code with missing internal link' do
38
+ let(:code) do
39
+ <<~CODE
40
+ class test () {
41
+ include profile::test
42
+ }
43
+ CODE
44
+ end
45
+
46
+ it 'should detect exactly one problem' do
47
+ expect(problems).to have(1).problems
48
+ end
49
+
50
+ it 'should create a warning' do
51
+ expect(problems).to contain_warning('Module profile::test not referenced in the comments').on_line(2).in_column(11)
52
+ end
53
+ end
54
+
55
+ context 'code with missing component link' do
56
+ let(:code) do
57
+ <<~CODE
58
+ class test () {
59
+ class {
60
+ 'apache':
61
+ }
62
+ }
63
+ CODE
64
+ end
65
+
66
+ it 'should detect exactly one problem' do
67
+ expect(problems).to have(1).problems
68
+ end
69
+
70
+ it 'should create a warning' do
71
+ expect(problems).to contain_warning('Can\'t find @ref tag for reference apache').on_line(1).in_column(1)
72
+ end
73
+ end
74
+
75
+ context 'code with wrong component @see' do
76
+ let(:code) do
77
+ <<~CODE
78
+ # @ref apache
79
+ # @note puppetlabs-apache
80
+ # @see https://example.com
81
+ class test () {
82
+ class {
83
+ 'apache':
84
+ }
85
+ }
86
+ CODE
87
+ end
88
+
89
+ it 'should detect exactly one problem' do
90
+ expect(problems).to have(1).problems
91
+ end
92
+
93
+ it 'should create a warning' do
94
+ expect(problems).to contain_warning('First @see for reference apache is not the Puppet forge').on_line(1).in_column(1)
95
+ end
96
+ end
97
+
98
+ context 'code with internal references sorted before component references' do
99
+ let(:code) do
100
+ <<~CODE
101
+ # @see profile::test
102
+ #
103
+ # @ref apache
104
+ # @note puppetlabs-apache
105
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
106
+ #
107
+ # @see profile::testfeature - Feature "test"
108
+ class test () {
109
+ include profile::test
110
+ class {
111
+ 'apache':
112
+ }
113
+ include apache
114
+
115
+ role::include_features({
116
+ 'testfeature' => [
117
+ profile::testfeature,
118
+ ],
119
+ })
120
+ }
121
+ CODE
122
+ end
123
+
124
+ it 'should detect exactly one problem' do
125
+ expect(problems).to have(1).problems
126
+ end
127
+
128
+ it 'should create a warning' do
129
+ expect(problems).to contain_warning('Reference to profile::test was found higher than @see https://forge.puppet.com/modules/puppetlabs/apache').on_line(1).in_column(1)
130
+ end
131
+ end
132
+
133
+ context 'code with feature references sorted before internal references' do
134
+ let(:code) do
135
+ <<~CODE
136
+ # @ref apache
137
+ # @note puppetlabs-apache
138
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
139
+ #
140
+ # @see profile::testfeature - Feature "test"
141
+ #
142
+ # @see profile::test
143
+ class test () {
144
+ include profile::test
145
+ class {
146
+ 'apache':
147
+ }
148
+ include apache
149
+
150
+ role::include_features({
151
+ 'testfeature' => [
152
+ profile::testfeature,
153
+ ],
154
+ })
155
+ }
156
+ CODE
157
+ end
158
+
159
+ it 'should detect exactly one problem' do
160
+ expect(problems).to have(1).problems
161
+ end
162
+
163
+ it 'should create a warning' do
164
+ expect(problems).to contain_warning('Reference to profile::testfeature was found higher than @see profile::test').on_line(1).in_column(1)
165
+ end
166
+ end
167
+
168
+ context 'code with reference to unused module' do
169
+ let(:code) do
170
+ <<~CODE
171
+ # @ref apache
172
+ # @note puppetlabs-apache
173
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
174
+ #
175
+ # @see profile::test
176
+ #
177
+ # @see profile::testfeature - Feature "test"
178
+ class test () {
179
+ include profile::test
180
+ class {
181
+ 'apache':
182
+ }
183
+ include apache
184
+ }
185
+ CODE
186
+ end
187
+
188
+ it 'should detect exactly one problem' do
189
+ expect(problems).to have(1).problems
190
+ end
191
+
192
+ it 'should create a warning' do
193
+ expect(problems).to contain_warning('Can\'t find referenced module profile::testfeature').on_line(1).in_column(1)
194
+ end
195
+ end
196
+
197
+ context 'code with unsorted component references' do
198
+ let(:code) do
199
+ <<~CODE
200
+ # @ref postgresql
201
+ # @note puppetlabs-postgresql
202
+ # @see https://forge.puppet.com/modules/puppetlabs/postgresql
203
+ #
204
+ # @ref apache
205
+ # @note puppetlabs-apache
206
+ # @see https://forge.puppet.com/modules/puppetlabs/apache
207
+ class test () {
208
+ class {
209
+ 'apache':
210
+ }
211
+ include postgresql
212
+ }
213
+ CODE
214
+ end
215
+
216
+ it 'should detect exactly one problem' do
217
+ expect(problems).to have(1).problems
218
+ end
219
+
220
+ it 'should create a warning' do
221
+ expect(problems).to contain_warning('puppetlabs-apache sorted after puppetlabs-postgresql').on_line(1).in_column(1)
222
+ end
223
+ end
224
+
225
+ context 'code with unsorted internal references' do
226
+ let(:code) do
227
+ <<~CODE
228
+ # @see profile::b
229
+ # @see profile::a
230
+ class test () {
231
+ include profile::a
232
+ include profile::b
233
+ }
234
+ CODE
235
+ end
236
+
237
+ it 'should detect exactly one problem' do
238
+ expect(problems).to have(1).problems
239
+ end
240
+
241
+ it 'should create a warning' do
242
+ expect(problems).to contain_warning('profile::a sorted after profile::b').on_line(1).in_column(1)
243
+ end
244
+ end
245
+
246
+ context 'code with unsorted feature references' do
247
+ let(:code) do
248
+ <<~CODE
249
+ # @see profile::b
250
+ # @see profile::a
251
+ class test () {
252
+ role::include_features({
253
+ 'testfeature' => [
254
+ profile::a,
255
+ profile::b
256
+ ],
257
+ })
258
+ }
259
+ CODE
260
+ end
261
+
262
+ it 'should detect exactly one problem' do
263
+ expect(problems).to have(1).problems
264
+ end
265
+
266
+ it 'should create a warning' do
267
+ expect(problems).to contain_warning('profile::a sorted after profile::b').on_line(1).in_column(1)
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ SimpleCov.add_filter 'vendor'
5
+ SimpleCov.start
6
+
7
+ require 'puppet-lint'
8
+
9
+ PuppetLint::Plugins.load_spec_helper
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puppet-lint-module_reference-check
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dennis Ploeger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: finite_machine
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: puppet-lint
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-collection_matchers
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-its
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: |2
126
+ A puppet-lint plugin to check that manifest files contain valid reference comments for included
127
+ modules.
128
+ email: develop@dieploegers.de
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - LICENSE
134
+ - README.md
135
+ - lib/puppet-lint-module_reference-check/reference.rb
136
+ - lib/puppet-lint-module_reference-check/reference_workflow.rb
137
+ - lib/puppet-lint/plugins/check_module_reference.rb
138
+ - spec/puppet-lint/plugins/check_module_reference_spec.rb
139
+ - spec/spec_helper.rb
140
+ homepage: https://github.com/dodevops/puppet-lint-module_reference-check
141
+ licenses:
142
+ - MIT
143
+ metadata: {}
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubygems_version: 3.0.3.1
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: A puppet-lint plugin to check the @see and @note comments for included modules.
163
+ test_files:
164
+ - spec/spec_helper.rb
165
+ - spec/puppet-lint/plugins/check_module_reference_spec.rb