metadata-json-lint 1.1.0 → 1.2.0

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