metadata-json-lint 1.2.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +4 -0
- data/README.md +25 -4
- data/lib/metadata-json-lint/schema.rb +150 -0
- data/lib/metadata_json_lint.rb +5 -17
- data/metadata-json-lint.gemspec +12 -3
- data/spec/schema_spec.rb +38 -0
- data/tests/long_summary/expected +1 -1
- data/tests/noname/expected +1 -1
- data/tests/tags_no_array/expected +1 -1
- metadata +20 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 656d4c9a85eceaa230fe84711819956a3d746a71
|
4
|
+
data.tar.gz: 69c06229897d87ec0a65115b28b01eec85dfa5b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36c139d8de7c19a488b0e73ed06f2461e6a177c65c62abc548b58ce36a715e3b574d08edb62c765c357fccb35a8754972eca0a411ccff303e5b58aef38599de7
|
7
|
+
data.tar.gz: 79a89a232bdae551740952c7827ebac93568006cce890f63eb913b5e3bf4fb111729a06bbfff4042659581ae0d11d390d30a399433c8b1d89d2e6a44fb6e8c3c
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
7
7
|
|
8
|
+
## 2.0.0
|
9
|
+
|
10
|
+
### Changes
|
11
|
+
* The `semantic_puppet` gem is no longer included as a runtime dependency due to conflicts with Puppet 5.x libraries that break the `puppet module` command. As such, `semantic_puppet` must be added to a user's Gemfile in Puppet <= 4.x. See [Installation](https://github.com/voxpupuli/metadata-json-lint#installation) docs for more info
|
12
|
+
* `metadata-json-lint` now officially only supports Ruby >= 2.0.0
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
* Fix puppet 5.x `semantic_puppet` conflicts ([#79](https://github.com/voxpupuli/metadata-json-lint/issues/79))
|
16
|
+
* Clarify Ruby >= 2.x only support ([#74](https://github.com/voxpupuli/metadata-json-lint/issues/74))
|
17
|
+
|
8
18
|
## 1.2.2
|
9
19
|
|
10
20
|
### Fixed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,14 +4,35 @@ The metadata-json-lint tool validates and lints `metadata.json` files in Puppet
|
|
4
4
|
|
5
5
|
## Compatibility
|
6
6
|
|
7
|
-
metadata-json-lint is compatible with Ruby versions 2.0.0, 2.1.9, and 2.
|
7
|
+
metadata-json-lint is compatible with Ruby versions 2.0.0, 2.1.9, 2.3.1, and 2.4.1.
|
8
8
|
|
9
9
|
## Installation
|
10
|
+
**NOTE: `metadata-json-lint` has a dependency on the `semantic_puppet` gem if you're on
|
11
|
+
Puppet 4 or earlier. This dependency was removed from the gemspec file due to a conflict
|
12
|
+
in Puppet 5 where the `semantic_puppet` ruby gem conflicts with a version of
|
13
|
+
`semantic_puppet` bundled with the core Puppet 5 code.**
|
14
|
+
|
15
|
+
### Puppet 5
|
16
|
+
via `gem` command:
|
17
|
+
``` shell
|
18
|
+
gem install metadata-json-lint
|
19
|
+
```
|
10
20
|
|
11
|
-
|
21
|
+
via Gemfile:
|
22
|
+
``` ruby
|
23
|
+
gem 'metadata-json-lint'
|
24
|
+
```
|
12
25
|
|
13
|
-
|
14
|
-
gem
|
26
|
+
### Puppet 4 and earlier
|
27
|
+
via `gem` command:
|
28
|
+
``` shell
|
29
|
+
gem install metadata-json-lint semantic_puppet
|
30
|
+
```
|
31
|
+
|
32
|
+
via Gemfile:
|
33
|
+
``` ruby
|
34
|
+
gem 'metadata-json-lint'
|
35
|
+
gem 'semantic_puppet'
|
15
36
|
```
|
16
37
|
|
17
38
|
## Usage
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'json-schema'
|
2
|
+
|
3
|
+
module MetadataJsonLint
|
4
|
+
# Provides validation of metadata.json against a JSON schema document
|
5
|
+
# maintained in this class. Provides a good first pass over the metadata with
|
6
|
+
# type checking and basic format/length validations.
|
7
|
+
#
|
8
|
+
# rubocop:disable Metrics/ClassLength # schema data structure is quite large
|
9
|
+
class Schema
|
10
|
+
# Based on https://docs.puppet.com/puppet/latest/modules_metadata.html
|
11
|
+
#
|
12
|
+
# rubocop:disable Style/TrailingCommaInLiteral # easier to modify individual lines
|
13
|
+
def schema
|
14
|
+
{
|
15
|
+
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
16
|
+
'properties' => {
|
17
|
+
'author' => {
|
18
|
+
'type' => 'string',
|
19
|
+
},
|
20
|
+
'data_provider' => {
|
21
|
+
'type' => %w[null string],
|
22
|
+
},
|
23
|
+
'dependencies' => {
|
24
|
+
'type' => 'array',
|
25
|
+
'items' => {
|
26
|
+
'properties' => {
|
27
|
+
'name' => {
|
28
|
+
'type' => 'string',
|
29
|
+
'pattern' => '^\w+[/-][a-z][a-z0-9_]*$',
|
30
|
+
},
|
31
|
+
'version_requirement' => {
|
32
|
+
'type' => 'string',
|
33
|
+
},
|
34
|
+
},
|
35
|
+
'required' => %w[
|
36
|
+
name
|
37
|
+
],
|
38
|
+
},
|
39
|
+
},
|
40
|
+
'description' => {
|
41
|
+
'type' => 'string',
|
42
|
+
},
|
43
|
+
'issues_url' => {
|
44
|
+
'type' => 'string',
|
45
|
+
'format' => 'uri',
|
46
|
+
},
|
47
|
+
'license' => {
|
48
|
+
'type' => 'string',
|
49
|
+
},
|
50
|
+
'operatingsystem_support' => {
|
51
|
+
'type' => 'array',
|
52
|
+
'items' => {
|
53
|
+
'properties' => {
|
54
|
+
'operatingsystem' => {
|
55
|
+
'type' => 'string',
|
56
|
+
},
|
57
|
+
'operatingsystemrelease' => {
|
58
|
+
'type' => 'array',
|
59
|
+
'items' => {
|
60
|
+
'type' => 'string',
|
61
|
+
},
|
62
|
+
},
|
63
|
+
},
|
64
|
+
'required' => %w[
|
65
|
+
operatingsystem
|
66
|
+
],
|
67
|
+
},
|
68
|
+
},
|
69
|
+
'name' => {
|
70
|
+
'type' => 'string',
|
71
|
+
'pattern' => '^\w+-[a-z][a-z0-9_]*$',
|
72
|
+
},
|
73
|
+
'project_page' => {
|
74
|
+
'type' => 'string',
|
75
|
+
'format' => 'uri',
|
76
|
+
},
|
77
|
+
# Undocumented but in use: https://tickets.puppetlabs.com/browse/DOCUMENT-387
|
78
|
+
'requirements' => {
|
79
|
+
'type' => 'array',
|
80
|
+
'items' => {
|
81
|
+
'properties' => {
|
82
|
+
'name' => {
|
83
|
+
'type' => 'string',
|
84
|
+
},
|
85
|
+
'version_requirement' => {
|
86
|
+
'type' => 'string',
|
87
|
+
},
|
88
|
+
},
|
89
|
+
'required' => %w[
|
90
|
+
name
|
91
|
+
],
|
92
|
+
},
|
93
|
+
},
|
94
|
+
'source' => {
|
95
|
+
'type' => 'string',
|
96
|
+
},
|
97
|
+
'summary' => {
|
98
|
+
'type' => 'string',
|
99
|
+
'maxLength' => 144,
|
100
|
+
},
|
101
|
+
'tags' => {
|
102
|
+
'type' => 'array',
|
103
|
+
'items' => {
|
104
|
+
'type' => 'string'
|
105
|
+
},
|
106
|
+
},
|
107
|
+
'version' => {
|
108
|
+
'type' => 'string',
|
109
|
+
'format' => 'semver',
|
110
|
+
},
|
111
|
+
},
|
112
|
+
# from https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#write-a-metadatajson-file
|
113
|
+
'required' => %w[
|
114
|
+
author
|
115
|
+
dependencies
|
116
|
+
license
|
117
|
+
name
|
118
|
+
source
|
119
|
+
summary
|
120
|
+
version
|
121
|
+
],
|
122
|
+
}
|
123
|
+
end
|
124
|
+
# rubocop:enable Style/TrailingCommaInLiteral
|
125
|
+
|
126
|
+
def validate(data, options = {})
|
127
|
+
JSON::Validator.register_format_validator('semver', method(:semver_validator))
|
128
|
+
|
129
|
+
JSON::Validator.fully_validate(schema, data, options.merge(errors_as_objects: true)).map do |error|
|
130
|
+
field = error[:fragment].split('/')[1]
|
131
|
+
field = 'root' if field.nil? || field.empty?
|
132
|
+
|
133
|
+
message = error[:message]
|
134
|
+
.sub(/ in schema [\w-]+/, '') # remove schema UUID, not needed in output
|
135
|
+
.sub(%r{'#/}, "'") # remove root #/ prefix from document paths
|
136
|
+
.sub("property ''", 'file') # call the root #/ node the file
|
137
|
+
|
138
|
+
{ field: field, message: message }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def semver_validator(value)
|
145
|
+
SemanticPuppet::Version.parse(value)
|
146
|
+
rescue SemanticPuppet::Version::ValidationFailure => e
|
147
|
+
raise JSON::Schema::CustomFormatError, "must be a valid semantic version: #{e.message}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
data/lib/metadata_json_lint.rb
CHANGED
@@ -2,6 +2,7 @@ require 'json'
|
|
2
2
|
require 'spdx-licenses'
|
3
3
|
require 'optparse'
|
4
4
|
|
5
|
+
require 'metadata-json-lint/schema'
|
5
6
|
require 'metadata-json-lint/version_requirement'
|
6
7
|
|
7
8
|
module MetadataJsonLint
|
@@ -75,13 +76,10 @@ module MetadataJsonLint
|
|
75
76
|
abort("Error: Unable to parse metadata.json: #{e.exception}")
|
76
77
|
end
|
77
78
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
if parsed[field].nil?
|
83
|
-
error :required_fields, "Required field '#{field}' not found in metadata.json."
|
84
|
-
end
|
79
|
+
# Validate basic structure against JSON schema
|
80
|
+
schema_errors = Schema.new.validate(parsed)
|
81
|
+
schema_errors.each do |err|
|
82
|
+
error (err[:field] == 'root' ? :required_fields : err[:field]), err[:message]
|
85
83
|
end
|
86
84
|
|
87
85
|
validate_dependencies!(parsed['dependencies']) if parsed['dependencies']
|
@@ -99,12 +97,6 @@ module MetadataJsonLint
|
|
99
97
|
# https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/puppet-users/nkRPvG4q0Oo/GmXa109aJQAJ
|
100
98
|
validate_requirements!(parsed['requirements']) if parsed['requirements']
|
101
99
|
|
102
|
-
# Summary can not be over 144 characters:
|
103
|
-
# From: https://forge.puppetlabs.com/razorsedge/snmp/3.3.1/scores
|
104
|
-
if !parsed['summary'].nil? && parsed['summary'].size > 144
|
105
|
-
error :summary, 'Field \'summary\' exceeds 144 characters in metadata.json.'
|
106
|
-
end
|
107
|
-
|
108
100
|
# Shoulds/recommendations
|
109
101
|
# From: https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#write-a-metadatajson-file
|
110
102
|
#
|
@@ -113,10 +105,6 @@ module MetadataJsonLint
|
|
113
105
|
warn(:license, msg)
|
114
106
|
end
|
115
107
|
|
116
|
-
if !parsed['tags'].nil? && !parsed['tags'].is_a?(Array)
|
117
|
-
error :tags, "Tags must be in an array. Currently it's a #{parsed['tags'].class}."
|
118
|
-
end
|
119
|
-
|
120
108
|
if !@errors.empty? || !@warnings.empty?
|
121
109
|
result = @errors.empty? ? "Warnings found in #{metadata}" : "Errors found in #{metadata}"
|
122
110
|
|
data/metadata-json-lint.gemspec
CHANGED
@@ -2,7 +2,7 @@ require 'date'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'metadata-json-lint'
|
5
|
-
s.version = '
|
5
|
+
s.version = '2.0.0'
|
6
6
|
s.date = Date.today.to_s
|
7
7
|
s.summary = 'metadata-json-lint /path/to/metadata.json'
|
8
8
|
s.description = 'Utility to verify Puppet metadata.json files'
|
@@ -16,10 +16,19 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.homepage = 'http://github.com/voxpupuli/metadata-json-lint'
|
17
17
|
s.license = 'Apache-2.0'
|
18
18
|
|
19
|
+
s.required_ruby_version = '>= 2.0.0'
|
19
20
|
s.add_runtime_dependency 'spdx-licenses', '~> 1.0'
|
20
|
-
s.add_runtime_dependency 'json'
|
21
|
-
s.add_runtime_dependency 'semantic_puppet', '>= 0.1.2', '< 2.0.0'
|
21
|
+
s.add_runtime_dependency 'json-schema', '~> 2.8'
|
22
22
|
s.add_development_dependency 'rake'
|
23
23
|
s.add_development_dependency 'rspec'
|
24
24
|
s.add_development_dependency 'rubocop'
|
25
|
+
s.requirements << 'semantic_puppet >= 0.1.2 < 2.0.0'
|
26
|
+
s.post_install_message = <<-EOS
|
27
|
+
-------------------------------------------------------------------
|
28
|
+
If your puppet is <= 4.x, then the semantic_puppet gem MUST
|
29
|
+
be in your Gemfile!!
|
30
|
+
|
31
|
+
On puppet >= 5.x, semantic_puppet will break functionality!
|
32
|
+
-------------------------------------------------------------------
|
33
|
+
EOS
|
25
34
|
end
|
data/spec/schema_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
describe MetadataJsonLint::Schema do
|
2
|
+
describe '#schema' do
|
3
|
+
it { expect(subject.schema).to be_a(Hash) }
|
4
|
+
end
|
5
|
+
|
6
|
+
describe '#validate' do
|
7
|
+
let(:minimal) { { author: '', dependencies: [], license: 'A', name: 'a-a', source: '', summary: '', version: '1.0.0' } }
|
8
|
+
|
9
|
+
context 'with empty hash' do
|
10
|
+
subject { described_class.new.validate({}) }
|
11
|
+
it { is_expected.to be_a(Array) }
|
12
|
+
it { expect(subject.size).to eq(7) }
|
13
|
+
it { is_expected.to include(field: 'root', message: "The file did not contain a required property of 'author'") }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with minimal entries' do
|
17
|
+
subject { described_class.new.validate(minimal) }
|
18
|
+
it { is_expected.to eq([]) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with validation error on entry' do
|
22
|
+
subject { described_class.new.validate(minimal.merge(summary: 'A' * 145)) }
|
23
|
+
it { is_expected.to eq([{ field: 'summary', message: "The property 'summary' was not of a maximum string length of 144" }]) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with validation error on nested entry' do
|
27
|
+
subject { described_class.new.validate(minimal.merge(dependencies: [{ name: 'in###id' }])) }
|
28
|
+
it { expect(subject.size).to eq(1) }
|
29
|
+
it { is_expected.to include(field: 'dependencies', message: a_string_matching(%r{The property 'dependencies/0/name' value "in###id" did not match the regex})) }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with semver validation failure' do
|
33
|
+
subject { described_class.new.validate(minimal.merge(version: 'a')) }
|
34
|
+
it { expect(subject.size).to eq(1) }
|
35
|
+
it { is_expected.to include(field: 'version', message: a_string_matching(/The property 'version' must be a valid semantic version/)) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/tests/long_summary/expected
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
(ERROR) summary: The property 'summary' was not of a maximum string length of 144
|
data/tests/noname/expected
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
(ERROR) required_fields: The file did not contain a required property of 'name'
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
(ERROR) tags: The property 'tags' of type string did not match the following type: array
|
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:
|
4
|
+
version: 2.0.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-06-
|
11
|
+
date: 2017-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spdx-licenses
|
@@ -25,39 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: json
|
28
|
+
name: json-schema
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: semantic_puppet
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.2
|
48
|
-
- - "<"
|
31
|
+
- - "~>"
|
49
32
|
- !ruby/object:Gem::Version
|
50
|
-
version: 2.
|
33
|
+
version: '2.8'
|
51
34
|
type: :runtime
|
52
35
|
prerelease: false
|
53
36
|
version_requirements: !ruby/object:Gem::Requirement
|
54
37
|
requirements:
|
55
|
-
- - "
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: 0.1.2
|
58
|
-
- - "<"
|
38
|
+
- - "~>"
|
59
39
|
- !ruby/object:Gem::Version
|
60
|
-
version: 2.
|
40
|
+
version: '2.8'
|
61
41
|
- !ruby/object:Gem::Dependency
|
62
42
|
name: rake
|
63
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,9 +99,11 @@ files:
|
|
119
99
|
- Rakefile
|
120
100
|
- bin/metadata-json-lint
|
121
101
|
- lib/metadata-json-lint/rake_task.rb
|
102
|
+
- lib/metadata-json-lint/schema.rb
|
122
103
|
- lib/metadata-json-lint/version_requirement.rb
|
123
104
|
- lib/metadata_json_lint.rb
|
124
105
|
- metadata-json-lint.gemspec
|
106
|
+
- spec/schema_spec.rb
|
125
107
|
- spec/spec_helper.rb
|
126
108
|
- spec/version_requirement_spec.rb
|
127
109
|
- tests/bad_license/Rakefile
|
@@ -187,7 +169,13 @@ homepage: http://github.com/voxpupuli/metadata-json-lint
|
|
187
169
|
licenses:
|
188
170
|
- Apache-2.0
|
189
171
|
metadata: {}
|
190
|
-
post_install_message:
|
172
|
+
post_install_message: |2
|
173
|
+
-------------------------------------------------------------------
|
174
|
+
If your puppet is <= 4.x, then the semantic_puppet gem MUST
|
175
|
+
be in your Gemfile!!
|
176
|
+
|
177
|
+
On puppet >= 5.x, semantic_puppet will break functionality!
|
178
|
+
-------------------------------------------------------------------
|
191
179
|
rdoc_options: []
|
192
180
|
require_paths:
|
193
181
|
- lib
|
@@ -195,19 +183,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
183
|
requirements:
|
196
184
|
- - ">="
|
197
185
|
- !ruby/object:Gem::Version
|
198
|
-
version:
|
186
|
+
version: 2.0.0
|
199
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
188
|
requirements:
|
201
189
|
- - ">="
|
202
190
|
- !ruby/object:Gem::Version
|
203
191
|
version: '0'
|
204
|
-
requirements:
|
192
|
+
requirements:
|
193
|
+
- semantic_puppet >= 0.1.2 < 2.0.0
|
205
194
|
rubyforge_project:
|
206
195
|
rubygems_version: 2.4.5
|
207
196
|
signing_key:
|
208
197
|
specification_version: 4
|
209
198
|
summary: metadata-json-lint /path/to/metadata.json
|
210
199
|
test_files:
|
200
|
+
- spec/schema_spec.rb
|
211
201
|
- spec/spec_helper.rb
|
212
202
|
- spec/version_requirement_spec.rb
|
213
203
|
- tests/bad_license/Rakefile
|