metadata-json-lint 1.1.0 → 1.2.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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metadata_json_lint.rb +94 -51
  3. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98bde19c3628ff9f087cddf19bda737480646331
4
- data.tar.gz: 79bc0a7ba2e8f160bf57359059f000d47120d817
3
+ metadata.gz: 26b0284277b14da2149836312d2f7470eeb42fec
4
+ data.tar.gz: 1f700550be689ad9379a1bfb5a617f4de64a18db
5
5
  SHA512:
6
- metadata.gz: c6897facd6d33655ff84f489373f589269ff5646e3f8977560ec9609b7235051198a9997499a1d6e9ebb7a62904471a5599bf3b16be5379ca58c836a00820bcb
7
- data.tar.gz: 0ede3fccd32938c18df7e3da63cd52c25d9be3033c63148fb2c1146afa0d1699734ebb176bee11285a85d06d468187c6c3a9683ba980f355601ea78a5edd1725
6
+ metadata.gz: f0160d90cb4707dc94deb44d16f9a3d22dcd15f9f6b7749c054b8354ea593089407de42e679040a052c634637d6718d636f7abec41c3cd0e2811ee439d2a9211
7
+ data.tar.gz: 9cbad4cbd0437415b6c347a05491a4a17f5324ca2c4472fc02772701fc7c37ebbda5a2c95106cbf5305f8afe11b4bc224e9de13ce4b74967eb9fed593da3743f
@@ -1,18 +1,21 @@
1
1
  require 'json'
2
2
  require 'spdx-licenses'
3
3
  require 'optparse'
4
- require 'semantic_puppet'
4
+
5
+ require 'metadata-json-lint/version_requirement'
5
6
 
6
7
  module MetadataJsonLint
7
8
  def options
8
9
  @options ||= Struct.new(
9
10
  :fail_on_warnings,
10
11
  :strict_license,
11
- :strict_dependencies
12
+ :strict_dependencies,
13
+ :format
12
14
  ).new(
13
15
  true, # fail_on_warnings
14
16
  true, # strict_license
15
- false # strict_dependencies
17
+ false, # strict_dependencies
18
+ 'text', # format
16
19
  )
17
20
  end
18
21
  module_function :options
@@ -32,6 +35,10 @@ module MetadataJsonLint
32
35
  opts.on('--[no-]fail-on-warnings', "Fail on any warnings. Defaults to '#{options[:fail_on_warnings]}'.") do |v|
33
36
  options[:fail_on_warnings] = v
34
37
  end
38
+
39
+ opts.on('-f', '--format FORMAT', %i[text json], 'The format in which results will be output (text, json)') do |format|
40
+ options[:format] = format
41
+ end
35
42
  end.parse!
36
43
 
37
44
  mj = if ARGV[0].nil?
@@ -49,6 +56,9 @@ module MetadataJsonLint
49
56
  module_function :run
50
57
 
51
58
  def parse(metadata)
59
+ @errors = []
60
+ @warnings = []
61
+
52
62
  # Small hack to use the module settings as defaults but allow overriding for different rake tasks
53
63
  options = options().clone
54
64
  # Configuration from rake tasks
@@ -65,111 +75,144 @@ module MetadataJsonLint
65
75
  abort("Error: Unable to parse metadata.json: #{e.exception}")
66
76
  end
67
77
 
68
- error_state = false
69
-
70
78
  # Fields required to be in metadata.json
71
79
  # From: https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#write-a-metadatajson-file
72
- required_fields = %w(name version author license summary source dependencies)
80
+ required_fields = %w[name version author license summary source dependencies]
73
81
  required_fields.each do |field|
74
82
  if parsed[field].nil?
75
- puts "Error: Required field '#{field}' not found in metadata.json."
76
- error_state = true
83
+ error :required_fields, "Required field '#{field}' not found in metadata.json."
77
84
  end
78
85
  end
79
86
 
80
- error_state ||= invalid_dependencies?(parsed['dependencies']) if parsed['dependencies']
87
+ validate_dependencies!(parsed['dependencies']) if parsed['dependencies']
81
88
 
82
89
  # Deprecated fields
83
90
  # From: https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#write-a-metadatajson-file
84
- deprecated_fields = %w(types checksum)
91
+ deprecated_fields = %w[types checksum]
85
92
  deprecated_fields.each do |field|
86
93
  unless parsed[field].nil?
87
- puts "Error: Deprecated field '#{field}' found in metadata.json."
88
- error_state = true
94
+ error :deprecated_fields, "Deprecated field '#{field}' found in metadata.json."
89
95
  end
90
96
  end
91
97
 
92
98
  # The nested 'requirements' name of 'pe' is deprecated as well.
93
99
  # https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/puppet-users/nkRPvG4q0Oo/GmXa109aJQAJ
94
- error_state ||= invalid_requirements?(parsed['requirements']) if parsed['requirements']
100
+ validate_requirements!(parsed['requirements']) if parsed['requirements']
95
101
 
96
102
  # Summary can not be over 144 characters:
97
103
  # From: https://forge.puppetlabs.com/razorsedge/snmp/3.3.1/scores
98
104
  if !parsed['summary'].nil? && parsed['summary'].size > 144
99
- puts 'Error: summary exceeds 144 characters in metadata.json.'
100
- error_state = true
105
+ error :summary, 'Field \'summary\' exceeds 144 characters in metadata.json.'
101
106
  end
102
107
 
103
108
  # Shoulds/recommendations
104
109
  # From: https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#write-a-metadatajson-file
105
110
  #
106
111
  if !parsed['license'].nil? && !SpdxLicenses.exist?(parsed['license']) && parsed['license'] != 'proprietary'
107
- puts "Warning: License identifier #{parsed['license']} is not in the SPDX list: http://spdx.org/licenses/"
108
- error_state = true if options[:strict_license]
112
+ msg = "License identifier #{parsed['license']} is not in the SPDX list: http://spdx.org/licenses/"
113
+
114
+ options[:strict_license] == true ? error(:license, msg) : warn(:license, msg)
109
115
  end
110
116
 
111
117
  if !parsed['tags'].nil? && !parsed['tags'].is_a?(Array)
112
- puts "Warning: Tags must be in an array. Currently it's a #{parsed['tags'].class}."
113
- error_state = true
118
+ error :tags, "Tags must be in an array. Currently it's a #{parsed['tags'].class}."
114
119
  end
115
120
 
116
- return unless error_state
117
- if options[:fail_on_warnings] == true
118
- abort("Errors found in #{metadata}")
119
- else
120
- puts "Errors found in #{metadata}"
121
+ if !@errors.empty? || !@warnings.empty?
122
+ result = @errors.empty? ? "Warnings found in #{metadata}" : "Errors found in #{metadata}"
123
+
124
+ case options[:format]
125
+ when :json
126
+ puts JSON.fast_generate(:result => result, :warnings => @warnings, :errors => @errors)
127
+ else
128
+ @warnings.each { |warn| puts "(WARN) #{warn}" }
129
+ @errors.each { |err| puts "(ERROR) #{err}" }
130
+ puts result
131
+ end
132
+
133
+ if !@errors.empty? || (!@warnings.empty? && (options[:fail_on_warnings] == true))
134
+ exit(1)
135
+ end
121
136
  end
137
+
138
+ exit(0)
122
139
  end
123
140
  module_function :parse
124
141
 
125
- def invalid_requirements?(requirements)
126
- error_state = false
142
+ def validate_requirements!(requirements)
127
143
  requirements.each do |requirement|
128
144
  if requirement['name'] == 'pe'
129
- puts "The 'pe' requirement is no longer supported by the Forge."
130
- error_state = true
145
+ warn :requirements, "The 'pe' requirement is no longer supported by the Forge."
131
146
  end
132
147
  end
133
- error_state
134
148
  end
135
- module_function :invalid_requirements?
149
+ module_function :validate_requirements!
136
150
 
137
- def invalid_dependencies?(deps)
138
- error_state = false
151
+ def validate_dependencies!(deps)
139
152
  dep_names = []
140
153
  deps.each do |dep|
141
154
  if dep_names.include?(dep['name'])
142
- puts "Error: duplicate dependencies on #{dep['name']}"
143
- error_state = true
155
+ warn :dependencies, "Duplicate dependencies on #{dep['name']}"
144
156
  end
145
157
  dep_names << dep['name']
146
158
 
147
- # Open ended dependency
148
- # From: https://docs.puppet.com/puppet/latest/reference/modules_metadata.html#best-practice-set-an-upper-bound-for-dependencies
149
159
  begin
150
- next unless dep['version_requirement'].nil? || open_ended?(dep['version_requirement'])
151
- puts "Warning: Dependency #{dep['name']} has an open " \
152
- "ended dependency version requirement #{dep['version_requirement']}"
153
- error_state = true if options[:strict_dependencies]
160
+ requirement = VersionRequirement.new(dep.fetch('version_requirement', ''))
154
161
  rescue ArgumentError => e
155
162
  # Raised when the version_requirement provided could not be parsed
156
- puts "Invalid 'version_requirement' field in metadata.json: #{e}"
157
- error_state = true
163
+ error :dependencies, "Invalid 'version_requirement' field in metadata.json: #{e}"
158
164
  end
165
+ validate_version_requirement!(dep, requirement)
159
166
 
160
167
  # 'version_range' is no longer used by the forge
161
168
  # See https://tickets.puppetlabs.com/browse/PUP-2781
162
- next unless dep['version_range']
163
- puts "Warning: Dependency #{dep['name']} has a 'version_range' attribute " \
164
- 'which is no longer used by the forge.'
165
- error_state = true
169
+ if dep.key?('version_range')
170
+ warn :dependencies, "Dependency #{dep['name']} has a 'version_range' attribute " \
171
+ 'which is no longer used by the forge.'
172
+ end
173
+ end
174
+ end
175
+ module_function :validate_dependencies!
176
+
177
+ def validate_version_requirement!(dep, requirement)
178
+ # Open ended dependency
179
+ # From: https://docs.puppet.com/puppet/latest/reference/modules_metadata.html#best-practice-set-an-upper-bound-for-dependencies
180
+ if requirement.open_ended?
181
+ msg = "Dependency #{dep['name']} has an open " \
182
+ "ended dependency version requirement #{dep['version_requirement']}"
183
+ options[:strict_dependencies] == true ? error(:dependencies, msg) : warn(:dependencies, msg)
184
+ end
185
+
186
+ # Mixing operator and wildcard version syntax
187
+ # From: https://docs.puppet.com/puppet/latest/modules_metadata.html#version-specifiers
188
+ # Supported in Puppet 5 and higher, but the syntax is unclear and incompatible with older versions
189
+ return unless requirement.mixed_syntax?
190
+ warn(:dependencies, 'Mixing "x" or "*" version syntax with operators is not recommended in ' \
191
+ "metadata.json, use one style in the #{dep['name']} dependency: #{dep['version_requirement']}")
192
+ end
193
+ module_function :validate_version_requirement!
194
+
195
+ def format_error(check, msg)
196
+ case options[:format]
197
+ when :json
198
+ { :check => check, :msg => msg }
199
+ else
200
+ "#{check}: #{msg}"
166
201
  end
167
- error_state
168
202
  end
169
- module_function :invalid_dependencies?
203
+ module_function :format_error
204
+
205
+ def warn(check, msg)
206
+ @warnings ||= []
207
+
208
+ @warnings << format_error(check, msg)
209
+ end
210
+ module_function :warn
211
+
212
+ def error(check, msg)
213
+ @errors ||= []
170
214
 
171
- def open_ended?(module_end)
172
- SemanticPuppet::VersionRange.parse(module_end).end == SemanticPuppet::Version::MAX
215
+ @errors << format_error(check, msg)
173
216
  end
174
- module_function :open_ended?
217
+ module_function :error
175
218
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metadata-json-lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vox Pupuli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-14 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spdx-licenses
@@ -72,6 +72,20 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
75
89
  - !ruby/object:Gem::Dependency
76
90
  name: rubocop
77
91
  requirement: !ruby/object:Gem::Requirement