papers 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MjJiMDlhOTlmYjAzNjcwNDE1N2QxN2IyOGU2MTllOGNhNjVlMDI3Yg==
5
+ data.tar.gz: !binary |-
6
+ MDBlNGZjZTRmMGQ5NTQ2Mjg4YWNjYzM0Y2M1MzNlM2RiMWY2NTBiYw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NGFhMTE2ZDg5MTg4ZDQ4NThhMDZjZTE3MzVkNDUwMDE4YzA0YzhhNDY3NWJk
10
+ ZDYwNGQzM2ExZWM1ZGU3ZmJjODgzNGM2NzRlYzBjMjhlOWFkYjI5OGFmODI4
11
+ NzQzZjI0ZWYxMzcyZDM1M2QyMmE3ZDgyOWFkMDQ3ZWUyNzg5NTU=
12
+ data.tar.gz: !binary |-
13
+ OWRkODEwYmFmNTRkZjE5OTg3OGUwZjU0MTJiNTVhNWVkZTgxMGIwNDc1MTEw
14
+ YzU1ZGU0ZGIyODQ0ZDNjODllZjBkYWM2MjdhMDJlYmI5ZWNiNWU1MzQ5ZDZm
15
+ YWUzZDBlM2Q0ZjBlNzA1YjE4YjRmNWMxMzgxYTI1ZDg3ZmQ4ZDY=
@@ -0,0 +1,5 @@
1
+ config/*
2
+ .DS_Store
3
+ Guardfile
4
+ *.swp
5
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2013 New Relic
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,163 @@
1
+ # Papers
2
+
3
+ > "Papers, please."
4
+
5
+ Check that your Ruby/Rails project's dependencies are licensed with only the licenses you specify. **Papers** will validate that your gems and JavaScript files conform to a whitelist of software licenses. Don't get caught flat-footed by the GPL.
6
+
7
+ # Contents
8
+ * [Usage](#usage)
9
+ * [Validations](#validations)
10
+ * [Configuration](#configuration)
11
+ * [Structure of Dependency Manifest](#dependency-manifest-structure)
12
+ * [License](#license)
13
+ * [Contributing](#contributing)
14
+
15
+
16
+ # Usage
17
+
18
+ tl;dr -- add gem, generate dependency manifest, run spec
19
+
20
+ ### 0. Add gem to Gemfile
21
+
22
+ ```
23
+ gem 'papers'
24
+ ```
25
+ ### 1. Generate Dependency Manifest from your bundled gems and JS
26
+
27
+ ```
28
+ $ papers
29
+ ```
30
+ ### 2. Create [Validation Spec](#testing-with-rspec)
31
+
32
+ ### 3. Run the specs
33
+
34
+ ```
35
+ $ rake spec spec/integration/papers_license_validation_spec.rb
36
+ ...
37
+ Failures:
38
+
39
+ 1) Papers License Validation finds no errors during license validation
40
+ Failure/Error: expect(validator.errors).to eq([])
41
+
42
+ expected: []
43
+ got: ["sass-3.2.12 is licensed under GPL, which is not whitelisted"]
44
+
45
+ (compared using ==)
46
+ # ./spec/integration/papers_license_validation_spec.rb:14:in `block (2 levels) in <top (required)>'
47
+
48
+ 2) Papers License Validation knows and is satisfied by all dependency licenses
49
+ Failure/Error: expect(validator.valid?).to be_true
50
+ expected: true value
51
+ got: false
52
+ # ./spec/integration/papers_license_validation_spec.rb:9:in `block (2 levels) in <top (required)>'
53
+
54
+ Finished in 0.01043 seconds
55
+ 2 examples, 2 failures
56
+ ...
57
+ ```
58
+
59
+ # Validations
60
+
61
+ ## testing with RSpec
62
+
63
+ ```
64
+ # => spec/integration/papers_license_validation_spec.rb
65
+
66
+ require 'spec_helper'
67
+ require 'papers'
68
+
69
+ describe 'Papers License Validation' do
70
+
71
+ let(:validator) { Papers::LicenseValidator.new }
72
+
73
+ it 'knows and is satisfied by all dependency licenses' do
74
+ expect(validator.valid?).to be_true
75
+ end
76
+
77
+ it 'finds no errors during license validation' do
78
+ validator.valid?
79
+ expect(validator.errors).to eq([])
80
+ end
81
+ end
82
+ ```
83
+
84
+ ## testing with MiniTest
85
+
86
+ ```
87
+ # => test/integration/papers_license_validation_test.rb
88
+
89
+ require 'test_helper'
90
+ require 'papers'
91
+
92
+ class PapersLicenseValidationTest < ActiveSupport::TestCase
93
+ def test_know_and_be_satisfied_by_all_licenses
94
+ validator = Papers::LicenseValidator.new
95
+
96
+ assert validator.valid?, "License validator failed:\n#{validator.errors.join("\n")}"
97
+
98
+ assert_equal validator.errors, []
99
+ end
100
+ end
101
+ ```
102
+
103
+ # Configuration
104
+
105
+ The default whitelist allows for permissive licensing for proprietary or commercial usage while avoiding strong copyleft licenses.
106
+
107
+ ```
108
+ @license_whitelist = [
109
+ 'MIT',
110
+ 'BSD',
111
+ 'Apache 2.0',
112
+ 'Apache-2.0',
113
+ 'LGPLv2.1',
114
+ 'LGPLv3',
115
+ 'Ruby',
116
+ 'Manually Reviewed',
117
+ 'Unlicensed'
118
+ ]
119
+ ```
120
+
121
+ ## Available configuration options
122
+
123
+ To configure the Papers gem, pass options to ```Papers.configure``` before initialization of LicenseValidator:
124
+
125
+ ```
126
+ Papers.configure do |c|
127
+ c.license_whitelist << 'New Relic'
128
+ c.manifest_file = File.join('some','other','dependency_manifest.yml')
129
+ c.validate_gems = true
130
+ c.validate_javascript = true
131
+ c.javascript_paths << File.join('some','other','javascripts')
132
+ end
133
+
134
+ validator = Papers::LicenseValidator.new
135
+ ...
136
+ ```
137
+
138
+ # Dependency Manifest structure
139
+
140
+ ```
141
+ # => config/papers_manifest.yml
142
+ ---
143
+ gems:
144
+ sqlite3-1.3.7:
145
+ license: MIT
146
+ license_url: https://github.com/luislavena/sqlite3-ruby
147
+ project_url: https://github.com/luislavena/sqlite3-ruby/blob/master/LICENSE
148
+ ...
149
+
150
+ javascripts:
151
+ app/assets/javascripts/application.js:
152
+ license: New Relic
153
+ license_url: http://newrelic.com
154
+ project_url: http://newrelic.com
155
+ ```
156
+
157
+ # License
158
+
159
+ The Papers Gem is licensed under the __MIT License__. See [MIT-LICENSE](https://github.com/newrelic/papers/blob/master/MIT-LICENSE) for full text.
160
+
161
+ # Contributing
162
+
163
+ You are welcome to send pull requests to us - however, by doing so you agree that you are granting New Relic a non-exclusive, non-revokable, no-cost license to use the code, algorithms, patents, and ideas in that code in our products if we so choose. You also agree the code is provided as-is and you provide no warranties as to its fitness or correctness for any purpose.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = "-c"
6
+ end
7
+
8
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
5
+ require 'papers'
6
+
7
+ cli = Papers::CLI.new
8
+ cli.run
@@ -0,0 +1,25 @@
1
+ require 'papers/configuration'
2
+ require 'papers/license_validator'
3
+ require 'papers/manifest_generator'
4
+ require 'papers/cli'
5
+ require 'papers/version'
6
+
7
+ require 'papers/dependency_specification'
8
+ require 'papers/dependency_specification/gem'
9
+ require 'papers/dependency_specification/javascript'
10
+
11
+ module Papers
12
+ def self.configure(&block)
13
+ yield configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @config ||= Configuration.new
18
+ end
19
+
20
+ # alias
21
+ def self.config
22
+ configuration
23
+ end
24
+
25
+ end
@@ -0,0 +1,41 @@
1
+ require 'optparse'
2
+
3
+ module Papers
4
+
5
+ class CLI
6
+
7
+ def run
8
+ if parse_options[:generate]
9
+ begin
10
+ generator = Papers::ManifestGenerator.new
11
+ generator.generate!
12
+ rescue Papers::FileExistsError => e
13
+ warn "Error: 'papers_manifest.yml' already exists at '#{e.message}'. Aborting..."
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def parse_options
21
+ options = {}
22
+ OptionParser.new do |opts|
23
+ opts.banner = "Usage: papers [options]"
24
+
25
+ opts.on("-g", "--generate", "Generate papers_manifest.yml") do |v|
26
+ options[:generate] = v
27
+ end
28
+
29
+ opts.on_tail( '-h', '--help', 'Display this screen' ) do |v|
30
+ p opts
31
+ exit
32
+ end
33
+ @avail_opts = opts
34
+ end.parse!
35
+
36
+ p @avail_opts if options.empty?
37
+
38
+ return options
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ module Papers
2
+ class Configuration
3
+ attr_accessor :license_whitelist
4
+
5
+ attr_accessor :manifest_file
6
+
7
+ attr_accessor :validate_gems
8
+
9
+ attr_accessor :validate_javascript
10
+
11
+ attr_accessor :javascript_paths
12
+
13
+ def initialize
14
+ @license_whitelist = [
15
+ 'MIT',
16
+ 'BSD',
17
+ 'Apache 2.0',
18
+ 'Apache-2.0',
19
+ 'LGPLv2.1',
20
+ 'LGPLv3',
21
+ 'Ruby',
22
+ 'Manually Reviewed',
23
+ 'Unlicensed'
24
+ ]
25
+
26
+ @manifest_file = File.join(Dir.pwd, 'config', 'papers_manifest.yml')
27
+
28
+ @validate_gems = true
29
+ @validate_javascript = true
30
+
31
+ @javascript_paths = [
32
+ File.join(Dir.pwd, 'app', 'assets', 'javascripts'),
33
+ File.join(Dir.pwd, 'lib', 'assets', 'javascripts'),
34
+ File.join(Dir.pwd, 'vendor', 'assets', 'javascripts')
35
+ ]
36
+ end
37
+
38
+ def validate_gems?
39
+ !!@validate_gems
40
+ end
41
+
42
+ def validate_javascript?
43
+ !!@validate_javascript
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ module Papers
2
+ class DependencySpecification
3
+ attr_accessor :name, :license, :license_url, :project_url
4
+
5
+ def initialize(options)
6
+ @name = options[:name]
7
+ @license = options[:license]
8
+ @license_url = options[:license_url]
9
+ @project_url = options[:project_url]
10
+ end
11
+
12
+ def acceptable_license?
13
+ Papers.config.license_whitelist.include?(license)
14
+ end
15
+
16
+ protected
17
+
18
+ def self.all_from_manifest(manifest)
19
+ (manifest[manifest_key] || []).map do |name, info|
20
+ license_url = info['license_url']
21
+ license = info['license']
22
+ project_url = info['project_url']
23
+ self.new(name: name, license: license, license_url: license_url, project_url: project_url)
24
+ end.sort { |a, b| a.name.downcase <=> b.name.downcase }
25
+ end
26
+
27
+ def self.missing_from_manifest(manifest)
28
+ introspected.to_set - all_from_manifest(manifest).map(&:name).to_set
29
+ end
30
+
31
+ def self.unknown_in_manifest(manifest)
32
+ all_from_manifest(manifest).map(&:name).to_set - introspected.to_set
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ module Papers
2
+ class Gem < DependencySpecification
3
+ def pretty_hash
4
+ {
5
+ name: name_without_version,
6
+ license: license,
7
+ license_url: @license_url,
8
+ project_url: @project_url
9
+ }
10
+ end
11
+
12
+ def name_without_version
13
+ return @name unless @name.include?('-')
14
+ @name.split('-')[0..-2].join('-')
15
+ end
16
+
17
+ def self.introspected
18
+ Bundler.load.specs.map do |spec|
19
+ # bundler versions aren't controlled by the Gemfile
20
+ if spec.name == "bundler"
21
+ spec.name
22
+ else
23
+ "#{spec.name}-#{spec.version}"
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.manifest_key
29
+ "gems"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ module Papers
2
+ class Javascript < DependencySpecification
3
+ def pretty_hash
4
+ {
5
+ name: @name,
6
+ license: license,
7
+ license_url: @license_url,
8
+ project_url: @project_url
9
+ }
10
+ end
11
+
12
+ def self.introspected
13
+ dirs = Papers.config.javascript_paths
14
+
15
+ # TODO: add logic for determining rails. Is Rails.root better than Dir.pwd for such a case?
16
+ root_regexp = /^#{Regexp.escape Dir.pwd.to_s}\//
17
+ dirs.map { |dir| Dir["#{dir}/**/*.js"] }.flatten.map { |name| name.sub(root_regexp, '') }
18
+ end
19
+
20
+ def self.manifest_key
21
+ "javascripts"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,62 @@
1
+ require 'yaml'
2
+
3
+ require 'papers/dependency_specification'
4
+ require 'papers/dependency_specification/gem'
5
+ require 'papers/dependency_specification/javascript'
6
+
7
+ module Papers
8
+ class LicenseValidator
9
+ attr_reader :errors
10
+
11
+ def initialize
12
+ @errors = []
13
+ end
14
+
15
+ def valid?
16
+ @errors = []
17
+
18
+ validate_gems if Papers.config.validate_gems?
19
+ validate_js if Papers.config.validate_javascript?
20
+
21
+ @errors.empty?
22
+ end
23
+
24
+ def manifest
25
+ @manifest ||= YAML.load_file(Papers.config.manifest_file)
26
+ end
27
+
28
+ def pretty_gem_list
29
+ Gem.all_from_manifest(manifest).map(&:pretty_hash)
30
+ end
31
+
32
+ def pretty_js_list
33
+ Javascript.all_from_manifest(manifest).map(&:pretty_hash)
34
+ end
35
+
36
+ private
37
+
38
+ def validate_spec_type(spec_type)
39
+ spec_type.missing_from_manifest(manifest).each do |name|
40
+ errors << "#{name} is included in the application, but not in the manifest"
41
+ end
42
+
43
+ spec_type.unknown_in_manifest(manifest).each do |name|
44
+ errors << "#{name} is included in the manifest, but not in the application"
45
+ end
46
+
47
+ spec_type.all_from_manifest(manifest).each do |spec|
48
+ unless spec.acceptable_license?
49
+ errors << "#{spec.name} is licensed under #{spec.license}, which is not whitelisted"
50
+ end
51
+ end
52
+ end
53
+
54
+ def validate_gems
55
+ validate_spec_type Gem
56
+ end
57
+
58
+ def validate_js
59
+ validate_spec_type Javascript
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,92 @@
1
+ require 'bundler'
2
+ require 'yaml'
3
+ require 'fileutils'
4
+
5
+ module Papers
6
+
7
+ class FileExistsError < StandardError;
8
+ attr_reader :manifest_path
9
+
10
+ def initialize(path)
11
+ @manifest_path = path
12
+ super
13
+ end
14
+ end
15
+
16
+ class ManifestGenerator
17
+
18
+ def generate!(args = ARGV)
19
+ @manifest_path = File.join('config','papers_manifest.yml')
20
+
21
+ raise Papers::FileExistsError.new(@manifest_path) if manifest_exists?
22
+
23
+ begin
24
+ if FileUtils.mkdir_p(File.dirname(@manifest_path))
25
+ File.open(@manifest_path, 'w') do |file|
26
+ file.write(build_header)
27
+ file.write(YAML.dump(build_manifest))
28
+ end
29
+ puts "Created #{@manifest_path}!"
30
+ end
31
+ rescue RuntimeError => e
32
+ warn "Failure! #{e}"
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def build_manifest
39
+ manifest = {
40
+ "gems" => get_installed_gems,
41
+ "javascripts" => get_installed_javascripts
42
+ }
43
+ return manifest
44
+ end
45
+
46
+ def get_installed_gems
47
+ gems = {}
48
+ Bundler.load.specs.each do |spec|
49
+ if spec.name == 'bundler'
50
+ name_and_version = spec.name
51
+ else
52
+ name_and_version = "#{spec.name}-#{spec.version}"
53
+ end
54
+
55
+ gems[name_and_version] = {
56
+ 'license' => spec.license || 'Unknown',
57
+ 'license_url' => nil,
58
+ 'project_url' => spec.homepage || nil
59
+ # TODO: add support for multiple licenses? some gemspecs have dual licensing
60
+ }
61
+ end
62
+ return gems
63
+ end
64
+
65
+ def get_installed_javascripts
66
+ js = {}
67
+ Javascript.introspected.each do |entry|
68
+ js[entry] = {
69
+ 'license' => 'Unknown',
70
+ 'license_url' => nil,
71
+ 'project_url' => nil
72
+ }
73
+ end
74
+ js.empty? ? nil : js
75
+ end
76
+
77
+ def manifest_exists?
78
+ !!File.exist?(@manifest_path)
79
+ end
80
+
81
+ def build_header
82
+ [
83
+ "# Dependency Manifest for the Papers gem",
84
+ "# Used to test your gems and javascript against license whitelist",
85
+ "#",
86
+ "# http://github.com/newrelic/papers\n"
87
+ ].join("\n")
88
+ end
89
+
90
+ end
91
+
92
+ end
@@ -0,0 +1,8 @@
1
+ module Papers
2
+ MAJOR = 1
3
+ MINOR = 0
4
+ PATCH = 1
5
+
6
+ VERSION = [MAJOR, MINOR, PATCH].join('.')
7
+ end
8
+
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
4
+
5
+ require 'papers/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'papers'
9
+ s.version = Papers::VERSION
10
+ s.summary = 'Validate the licenses of software dependencies you use'
11
+
12
+ s.description = <<-DESCRIPTION
13
+ Validate that the licenses used by your Ruby project's dependencies (both gems
14
+ and javascript libraries) conform to a software license whitelist. Don't get
15
+ caught flat-footed by the GPL.
16
+ DESCRIPTION
17
+
18
+ s.authors = ['Ralph Bodenner', 'Jade Rubick', 'Andrew Bloomgarden', 'Lucas Charles']
19
+ s.email = 'support@newrelic.com'
20
+ s.license = 'MIT'
21
+ s.homepage = 'http://github.com/newrelic/papers'
22
+
23
+ s.files = `git ls-files`.split($/)
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split($/)
25
+ s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
26
+
27
+ s.require_paths = ['lib']
28
+
29
+ # dependencies
30
+ s.add_dependency 'rake', '~> 10.1'
31
+ s.add_development_dependency 'rspec', '~> 2.14'
32
+ end
@@ -0,0 +1,206 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ require_relative '../lib/papers'
4
+
5
+ describe 'Papers' do
6
+
7
+ let(:validator) { Papers::LicenseValidator.new }
8
+
9
+ it 'validates a manifest with empty values and set of dependencies' do
10
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
11
+ "javascripts" => {},
12
+ "gems" => {}
13
+ })
14
+ Papers::Gem.stub(:introspected).and_return([])
15
+
16
+ expect(validator.valid?).to be_true
17
+ end
18
+
19
+ it 'detects mismatched gems' do
20
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
21
+ "javascripts" => {},
22
+ "gems" => {
23
+ "foo-1.2" => {
24
+ 'license' => "MIT",
25
+ 'license_url' => nil,
26
+ 'project_url' => nil
27
+ },
28
+ "baz-1.3" => {
29
+ 'license' => "BSD",
30
+ 'license_url' => nil,
31
+ 'project_url' => nil
32
+ }
33
+ }
34
+ })
35
+ Papers::Gem.stub(:introspected).and_return(["bar-1.2", "baz-1.3"])
36
+
37
+ expect(validator.valid?).to be_false
38
+
39
+ expect(validator.errors).to eq([
40
+ "bar-1.2 is included in the application, but not in the manifest",
41
+ "foo-1.2 is included in the manifest, but not in the application"
42
+ ])
43
+
44
+ validator.valid?
45
+ end
46
+
47
+ it 'detects mismatched gem versions' do
48
+ Papers::Configuration.any_instance.stub(:validate_javascript?).and_return(true)
49
+
50
+ expect(validator).to receive(:validate_js).at_least(:once)
51
+
52
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
53
+ "javascripts" => {},
54
+ "gems" => {
55
+ "foo-1.2" => {
56
+ 'license' => "MIT",
57
+ 'license_url' => nil,
58
+ 'project_url' => nil
59
+ },
60
+ "baz-1.3" => {
61
+ 'license' => "BSD",
62
+ 'license_url' => nil,
63
+ 'project_url' => nil
64
+ }
65
+ }
66
+ })
67
+ Papers::Gem.stub(:introspected).and_return(["foo-1.2", "baz-1.2"])
68
+
69
+ expect(validator.valid?).to be_false
70
+
71
+ expect(validator.errors).to eq([
72
+ "baz-1.2 is included in the application, but not in the manifest",
73
+ "baz-1.3 is included in the manifest, but not in the application"
74
+ ])
75
+ validator.valid?
76
+ end
77
+
78
+ it 'is OK with matching gem sets' do
79
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
80
+ "javascripts" => {},
81
+ "gems" => {
82
+ "foo-1.2" => {
83
+ 'license' => "MIT",
84
+ 'license_url' => nil,
85
+ 'project_url' => nil
86
+ },
87
+ "baz-1.3" => {
88
+ 'license' => "BSD",
89
+ 'license_url' => nil,
90
+ 'project_url' => nil
91
+ }
92
+ },
93
+ })
94
+ Papers::Gem.stub(:introspected).and_return(["foo-1.2", "baz-1.3"])
95
+
96
+ expect(validator.valid?).to be_true
97
+ end
98
+
99
+ it 'is OK with matching gem sets but complain about a license issue' do
100
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
101
+ "javascripts" => {},
102
+ "gems" => {
103
+ "foo-1.2" => {
104
+ 'license' => "MIT",
105
+ 'license_url' => nil,
106
+ 'project_url' => nil
107
+ },
108
+ "baz-1.3" => {
109
+ 'license' => "GPL",
110
+ 'license_url' => nil,
111
+ 'project_url' => nil
112
+ }
113
+ },
114
+ })
115
+ Papers::Gem.stub(:introspected).and_return(["foo-1.2", "baz-1.3"])
116
+
117
+ expect(validator.valid?).to be_false
118
+
119
+ expect(validator.errors).to eq([
120
+ "baz-1.3 is licensed under GPL, which is not whitelisted"
121
+ ])
122
+
123
+ validator.valid?
124
+ end
125
+
126
+ it 'displays gem licenses in a pretty format without versions' do
127
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
128
+ "javascripts" => {},
129
+ "gems" => {
130
+ "foo-1.2" => {
131
+ 'license' => "MIT",
132
+ 'license_url' => nil,
133
+ 'project_url' => nil
134
+ },
135
+ "baz-1.3" => {
136
+ 'license' => "BSD",
137
+ 'license_url' => nil,
138
+ 'project_url' => nil
139
+ },
140
+ "with-hyphens-1.4" => {
141
+ 'license' => "MIT",
142
+ 'license_url' => nil,
143
+ 'project_url' => nil
144
+ }
145
+ },
146
+ })
147
+ expect(validator.pretty_gem_list).to eq([
148
+ {
149
+ :name=>"baz",
150
+ :license=>"BSD",
151
+ :license_url => nil,
152
+ :project_url => nil
153
+ },
154
+ {
155
+ :name=>"foo",
156
+ :license=>"MIT",
157
+ :license_url => nil,
158
+ :project_url => nil
159
+ },
160
+ {
161
+ :name=>"with-hyphens",
162
+ :license=>"MIT",
163
+ :license_url => nil,
164
+ :project_url => nil
165
+ }
166
+ ])
167
+ end
168
+
169
+ it 'displays JS libraries in a pretty format without versions' do
170
+ Papers::LicenseValidator.any_instance.stub(:manifest).and_return({
171
+ "javascripts" => {
172
+ "/path/to/foo.js" => {
173
+ 'license' => "MIT",
174
+ 'license_url' => nil,
175
+ 'project_url' => nil
176
+ },
177
+ "/path/to/newrelic.js" => {
178
+ 'license' => "New Relic",
179
+ 'license_url' => nil,
180
+ 'project_url' => nil
181
+ }
182
+ },
183
+ "gems" => {}
184
+ })
185
+ expect(validator.pretty_js_list).to eq([
186
+ {
187
+ :name =>"/path/to/foo.js",
188
+ :license =>"MIT",
189
+ :license_url => nil,
190
+ :project_url => nil
191
+ },
192
+ {
193
+ :name =>"/path/to/newrelic.js",
194
+ :license =>"New Relic",
195
+ :license_url => nil,
196
+ :project_url => nil
197
+ }
198
+ ])
199
+ end
200
+
201
+ it 'displays the gem name when the gemspec does not specify a version' do
202
+ gemspec = Papers::Gem.new(name: 'foo')
203
+ expect('foo').to eq(gemspec.name_without_version)
204
+ end
205
+
206
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: papers
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ralph Bodenner
8
+ - Jade Rubick
9
+ - Andrew Bloomgarden
10
+ - Lucas Charles
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-12-10 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rake
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '10.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '10.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: '2.14'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '2.14'
44
+ description: ! 'Validate that the licenses used by your Ruby project''s dependencies
45
+ (both gems
46
+
47
+ and javascript libraries) conform to a software license whitelist. Don''t get
48
+
49
+ caught flat-footed by the GPL.
50
+
51
+ '
52
+ email: support@newrelic.com
53
+ executables:
54
+ - papers
55
+ extensions: []
56
+ extra_rdoc_files: []
57
+ files:
58
+ - .gitignore
59
+ - Gemfile
60
+ - MIT-LICENSE
61
+ - README.md
62
+ - Rakefile
63
+ - bin/papers
64
+ - lib/papers.rb
65
+ - lib/papers/cli.rb
66
+ - lib/papers/configuration.rb
67
+ - lib/papers/dependency_specification.rb
68
+ - lib/papers/dependency_specification/gem.rb
69
+ - lib/papers/dependency_specification/javascript.rb
70
+ - lib/papers/license_validator.rb
71
+ - lib/papers/manifest_generator.rb
72
+ - lib/papers/version.rb
73
+ - papers.gemspec
74
+ - spec/papers_spec.rb
75
+ homepage: http://github.com/newrelic/papers
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.1.5
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Validate the licenses of software dependencies you use
99
+ test_files:
100
+ - spec/papers_spec.rb
101
+ has_rdoc: