license_finder 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.rdoc +27 -3
- data/db/migrate/201307250917_add_license_manual_to_dependencies.rb +7 -0
- data/db/migrate/201307251004_data_fix_manual_licenses.rb +15 -0
- data/db/migrate/201307251107_reassociate_license.rb +23 -0
- data/db/migrate/201307251340_remove_manual_from_license_aliases.rb +7 -0
- data/features/cli.feature +1 -1
- data/features/html_report.feature +3 -2
- data/features/project_name.feature +10 -0
- data/features/set_license.feature +1 -0
- data/features/step_definitions/cli_steps.rb +3 -3
- data/features/step_definitions/project_name_steps.rb +3 -0
- data/features/step_definitions/set_license_steps.rb +9 -4
- data/features/step_definitions/shared_steps.rb +11 -2
- data/features/step_definitions/text_report_steps.rb +12 -2
- data/features/text_report.feature +7 -1
- data/files/dependency_breakdown.png +0 -0
- data/files/license_finder.yml +1 -0
- data/files/report_breakdown.png +0 -0
- data/lib/license_finder.rb +0 -5
- data/lib/license_finder/bundle.rb +22 -4
- data/lib/license_finder/bundled_gem.rb +17 -10
- data/lib/license_finder/bundled_gem_saver.rb +42 -30
- data/lib/license_finder/cli.rb +37 -5
- data/lib/license_finder/configuration.rb +13 -2
- data/lib/license_finder/dependency_manager.rb +21 -8
- data/lib/license_finder/reports/dependency_report.rb +1 -1
- data/lib/license_finder/reports/reporter.rb +4 -0
- data/lib/license_finder/tables/dependency.rb +9 -1
- data/lib/license_finder/tables/license_alias.rb +0 -4
- data/lib/license_finder/yml_to_sql.rb +1 -11
- data/lib/templates/html_report.erb +13 -3
- data/license_finder.gemspec +3 -4
- data/readme.md +25 -3
- data/release/gem_version.rb +3 -0
- data/{release.md → release/manual_instructions.md} +6 -0
- data/release/publish.sh +29 -0
- data/spec/lib/license_finder/bundle_spec.rb +16 -4
- data/spec/lib/license_finder/bundled_gem_saver_spec.rb +41 -38
- data/spec/lib/license_finder/bundled_gem_spec.rb +22 -4
- data/spec/lib/license_finder/cli_spec.rb +22 -0
- data/spec/lib/license_finder/configuration_spec.rb +34 -14
- data/spec/lib/license_finder/dependency_manager_spec.rb +61 -10
- data/spec/lib/license_finder/reporter_spec.rb +35 -1
- data/spec/lib/license_finder/tables/dependency_spec.rb +23 -0
- data/spec/lib/license_finder/tables/license_alias_spec.rb +0 -16
- data/spec/lib/license_finder/yml_to_sql_spec.rb +11 -3
- data/spec/lib/license_finder_spec.rb +2 -2
- data/spec/spec_helper.rb +3 -13
- metadata +21 -8
data/lib/license_finder/cli.rb
CHANGED
@@ -24,7 +24,17 @@ module LicenseFinder
|
|
24
24
|
# Hack to override the help message produced by Thor.
|
25
25
|
# https://github.com/wycats/thor/issues/261#issuecomment-16880836
|
26
26
|
def self.banner(command, namespace = nil, subcommand = nil)
|
27
|
-
"#{basename} #{name
|
27
|
+
"#{basename} #{underscore_name(name)} #{command.usage}"
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def self.underscore_name(name)
|
33
|
+
underscored = name.split("::").last
|
34
|
+
underscored.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
35
|
+
underscored.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
36
|
+
underscored.tr!("-", "_")
|
37
|
+
underscored.downcase
|
28
38
|
end
|
29
39
|
end
|
30
40
|
|
@@ -64,25 +74,42 @@ module LicenseFinder
|
|
64
74
|
end
|
65
75
|
end
|
66
76
|
|
67
|
-
desc "add", "Add a license to the whitelist"
|
77
|
+
desc "add LICENSE", "Add a license to the whitelist"
|
68
78
|
def add(license)
|
69
79
|
die_on_error {
|
70
80
|
LicenseFinder.config.whitelist.push(license)
|
71
81
|
LicenseFinder.config.save
|
82
|
+
|
83
|
+
Reporter.write_reports
|
72
84
|
}
|
73
85
|
say "Added #{license} to the license whitelist"
|
74
86
|
end
|
75
87
|
|
76
|
-
desc "remove", "Remove a license from the whitelist"
|
88
|
+
desc "remove LICENSE", "Remove a license from the whitelist"
|
77
89
|
def remove(license)
|
78
90
|
die_on_error {
|
79
91
|
LicenseFinder.config.whitelist.delete(license)
|
80
92
|
LicenseFinder.config.save
|
93
|
+
|
94
|
+
Reporter.write_reports
|
81
95
|
}
|
82
96
|
say "Removed #{license} from the license whitelist"
|
83
97
|
end
|
84
98
|
end
|
85
99
|
|
100
|
+
class ProjectName < Subcommand
|
101
|
+
desc "set NAME", "Set the project name"
|
102
|
+
def set(name)
|
103
|
+
die_on_error {
|
104
|
+
LicenseFinder.config.project_name = name
|
105
|
+
LicenseFinder.config.save
|
106
|
+
|
107
|
+
Reporter.write_reports
|
108
|
+
}
|
109
|
+
say "Set the project name to #{name}", :green
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
86
113
|
class IgnoredBundlerGroups < Subcommand
|
87
114
|
desc "list", "List all the ignored bundler groups"
|
88
115
|
def list
|
@@ -94,20 +121,24 @@ module LicenseFinder
|
|
94
121
|
end
|
95
122
|
end
|
96
123
|
|
97
|
-
desc "add", "Add a bundler group to be ignored"
|
124
|
+
desc "add GROUP", "Add a bundler group to be ignored"
|
98
125
|
def add(group)
|
99
126
|
die_on_error {
|
100
127
|
LicenseFinder.config.ignore_groups.push(group)
|
101
128
|
LicenseFinder.config.save
|
129
|
+
|
130
|
+
Reporter.write_reports
|
102
131
|
}
|
103
132
|
say "Added #{group} to the ignored bundler groups"
|
104
133
|
end
|
105
134
|
|
106
|
-
desc "remove", "Remove a bundler group from the ignored bundler groups"
|
135
|
+
desc "remove GROUP", "Remove a bundler group from the ignored bundler groups"
|
107
136
|
def remove(group)
|
108
137
|
die_on_error {
|
109
138
|
LicenseFinder.config.ignore_groups.delete(group)
|
110
139
|
LicenseFinder.config.save
|
140
|
+
|
141
|
+
Reporter.write_reports
|
111
142
|
}
|
112
143
|
say "Removed #{group} from the ignored bundler groups"
|
113
144
|
end
|
@@ -167,6 +198,7 @@ module LicenseFinder
|
|
167
198
|
subcommand "dependencies", Dependencies, "manage non-Bundler dependencies"
|
168
199
|
subcommand "ignored_bundler_groups", IgnoredBundlerGroups, "manage ignored bundler groups"
|
169
200
|
subcommand "whitelist", Whitelist, "manage whitelisted licenses"
|
201
|
+
subcommand "project_name", ProjectName, "manage the project name"
|
170
202
|
|
171
203
|
private
|
172
204
|
|
@@ -2,7 +2,7 @@ require "rake"
|
|
2
2
|
|
3
3
|
module LicenseFinder
|
4
4
|
class Configuration
|
5
|
-
attr_accessor :whitelist, :ignore_groups, :dependencies_dir
|
5
|
+
attr_accessor :whitelist, :ignore_groups, :dependencies_dir, :project_name
|
6
6
|
|
7
7
|
def self.config_file_path
|
8
8
|
File.join('.', 'config', 'license_finder.yml')
|
@@ -45,6 +45,7 @@ module LicenseFinder
|
|
45
45
|
@whitelist = config['whitelist'] || []
|
46
46
|
@ignore_groups = (config["ignore_groups"] || [])
|
47
47
|
@dependencies_dir = config['dependencies_file_dir'] || './doc/'
|
48
|
+
@project_name = config['project_name'] || determine_project_name
|
48
49
|
FileUtils.mkdir_p(@dependencies_dir)
|
49
50
|
end
|
50
51
|
|
@@ -57,6 +58,10 @@ module LicenseFinder
|
|
57
58
|
end
|
58
59
|
|
59
60
|
def dependencies_text
|
61
|
+
File.join(dependencies_dir, "dependencies.csv")
|
62
|
+
end
|
63
|
+
|
64
|
+
def dependencies_legacy_text
|
60
65
|
File.join(dependencies_dir, "dependencies.txt")
|
61
66
|
end
|
62
67
|
|
@@ -73,7 +78,9 @@ module LicenseFinder
|
|
73
78
|
File.open(Configuration.config_file_path, 'w') do |file|
|
74
79
|
file.write({
|
75
80
|
'whitelist' => @whitelist.uniq,
|
76
|
-
'ignore_groups' => @ignore_groups.uniq
|
81
|
+
'ignore_groups' => @ignore_groups.uniq,
|
82
|
+
'dependencies_file_dir' => @dependencies_dir,
|
83
|
+
'project_name' => @project_name
|
77
84
|
}.to_yaml)
|
78
85
|
end
|
79
86
|
end
|
@@ -85,5 +92,9 @@ module LicenseFinder
|
|
85
92
|
License.find_by_name(license_name) || license_name
|
86
93
|
end.compact
|
87
94
|
end
|
95
|
+
|
96
|
+
def determine_project_name
|
97
|
+
File.basename(Dir.getwd)
|
98
|
+
end
|
88
99
|
end
|
89
100
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
1
3
|
module LicenseFinder
|
2
4
|
module DependencyManager
|
3
5
|
def self.sync_with_bundler
|
4
6
|
modifying {
|
5
|
-
current_dependencies =
|
7
|
+
current_dependencies = BundledGemSaver.save_gems(Bundle.current_gems(LicenseFinder.config))
|
6
8
|
Dependency.bundler.obsolete(current_dependencies).each(&:destroy)
|
7
9
|
}
|
8
10
|
end
|
@@ -23,13 +25,30 @@ module LicenseFinder
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def self.license!(name, license)
|
26
|
-
modifying { find_by_name(name).
|
28
|
+
modifying { find_by_name(name).set_license_manually!(license) }
|
27
29
|
end
|
28
30
|
|
29
31
|
def self.approve!(name)
|
30
32
|
modifying { find_by_name(name).approve! }
|
31
33
|
end
|
32
34
|
|
35
|
+
def self.modifying
|
36
|
+
checksum_before_modifying = if File.exists? LicenseFinder.config.database_uri
|
37
|
+
Digest::SHA2.file(LicenseFinder.config.database_uri).hexdigest
|
38
|
+
end
|
39
|
+
result = yield
|
40
|
+
checksum_after_modifying = Digest::SHA2.file(LicenseFinder.config.database_uri).hexdigest
|
41
|
+
|
42
|
+
unless checksum_after_modifying == checksum_before_modifying
|
43
|
+
Reporter.write_reports
|
44
|
+
end
|
45
|
+
unless File.exists? LicenseFinder.config.dependencies_html
|
46
|
+
Reporter.write_reports
|
47
|
+
end
|
48
|
+
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
33
52
|
private # not really private, but it looks like it is!
|
34
53
|
|
35
54
|
def self.find_by_name(name, scope = Dependency)
|
@@ -37,12 +56,6 @@ module LicenseFinder
|
|
37
56
|
raise Error.new("could not find dependency named #{name}") unless dep
|
38
57
|
dep
|
39
58
|
end
|
40
|
-
|
41
|
-
def self.modifying
|
42
|
-
result = yield
|
43
|
-
Reporter.write_reports
|
44
|
-
result
|
45
|
-
end
|
46
59
|
end
|
47
60
|
end
|
48
61
|
|
@@ -7,6 +7,10 @@ module LicenseFinder
|
|
7
7
|
|
8
8
|
write_file LicenseFinder.config.dependencies_text, TextReport.new(dependencies).to_s
|
9
9
|
write_file LicenseFinder.config.dependencies_html, HtmlReport.new(dependencies).to_s
|
10
|
+
|
11
|
+
if File.exists?(LicenseFinder.config.dependencies_legacy_text)
|
12
|
+
File.delete(LicenseFinder.config.dependencies_legacy_text)
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
@@ -37,7 +37,15 @@ module LicenseFinder
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def approved?
|
40
|
-
|
40
|
+
# jruby adapter receives approval.state as Fixnum '0', which ruby evaluates
|
41
|
+
# as truthy, so we catch this here for jruby support.
|
42
|
+
(license && license.whitelisted?) || (approval.state && approval.state != 0)
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_license_manually!(license_name)
|
46
|
+
self.license = LicenseAlias.find_or_create(name: license_name)
|
47
|
+
self.license_manual = true
|
48
|
+
save
|
41
49
|
end
|
42
50
|
|
43
51
|
def ensure_approval_exists!
|
@@ -67,7 +67,7 @@ module LicenseFinder
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def create_license
|
70
|
-
|
70
|
+
LicenseAlias.find_or_create(name: legacy_attrs['license'])
|
71
71
|
end
|
72
72
|
|
73
73
|
def create_approval
|
@@ -110,16 +110,6 @@ module LicenseFinder
|
|
110
110
|
class BundlerGroup < Sequel::Model
|
111
111
|
end
|
112
112
|
|
113
|
-
class LicenseAlias < Sequel::Model
|
114
|
-
extend Convertable
|
115
|
-
|
116
|
-
VALID_ATTRIBUTES = {
|
117
|
-
'license' => 'name',
|
118
|
-
'license_url' => 'url',
|
119
|
-
'manual' => 'manual'
|
120
|
-
}
|
121
|
-
end
|
122
|
-
|
123
113
|
class Approval < Sequel::Model
|
124
114
|
extend Convertable
|
125
115
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
|
-
<link href="
|
3
|
+
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet">
|
4
4
|
<style type="text/css">
|
5
5
|
body {
|
6
6
|
margin: 50px;
|
@@ -13,11 +13,21 @@
|
|
13
13
|
content: " (unapproved)"
|
14
14
|
}
|
15
15
|
</style>
|
16
|
+
<script>
|
17
|
+
// Loads stylesheet when viewing file locally.
|
18
|
+
if (location.protocol === "file:") {
|
19
|
+
var link = document.querySelector('head link')
|
20
|
+
, href = link.href.replace(/file/, "http");
|
21
|
+
|
22
|
+
link.href = href;
|
23
|
+
}
|
24
|
+
</script>
|
16
25
|
</head>
|
17
26
|
<body>
|
18
27
|
<div class="container">
|
28
|
+
<h1><%= LicenseFinder.config.project_name %></h1>
|
19
29
|
<div class="summary hero-unit">
|
20
|
-
<
|
30
|
+
<h2>Dependencies</h2>
|
21
31
|
|
22
32
|
<p>As of <%= Time.now.strftime("%B %e, %Y %l:%M%P") %></p>
|
23
33
|
|
@@ -37,7 +47,7 @@
|
|
37
47
|
</div>
|
38
48
|
<% if unapproved_dependencies.any? -%>
|
39
49
|
<div class="action-items hero-unit">
|
40
|
-
<
|
50
|
+
<h2>Action Items</h2>
|
41
51
|
<h4><%= unapproved_dependencies.size %> unapproved dependencies</h4>
|
42
52
|
<ul>
|
43
53
|
<% unapproved_dependencies.each do |dependency| -%>
|
data/license_finder.gemspec
CHANGED
@@ -2,8 +2,8 @@ require './lib/license_finder/platform'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "license_finder"
|
5
|
-
s.version = "0.9.
|
6
|
-
s.authors = ["Jacob Maine", "Matthew Kane Parker", "Ian Lesperance", "David Edwards", "Paul Meskers", "Brent Wheeldon", "David Tengdin", "William Ramsey"]
|
5
|
+
s.version = "0.9.1"
|
6
|
+
s.authors = ["Jacob Maine", "Matthew Kane Parker", "Ian Lesperance", "David Edwards", "Paul Meskers", "Brent Wheeldon", "Trevor John", "David Tengdin", "William Ramsey"]
|
7
7
|
s.email = ["licensefinder@pivotalabs.com"]
|
8
8
|
s.homepage = "https://github.com/pivotal/LicenseFinder"
|
9
9
|
s.summary = "Audit the OSS licenses of your application's dependencies."
|
@@ -24,11 +24,10 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_dependency "rake"
|
25
25
|
s.add_dependency LicenseFinder::Platform.sqlite_gem
|
26
26
|
|
27
|
-
%w(rspec xpath cucumber).each do |gem|
|
27
|
+
%w(rspec xpath cucumber pry).each do |gem|
|
28
28
|
s.add_development_dependency gem
|
29
29
|
end
|
30
30
|
|
31
|
-
s.add_development_dependency "database_cleaner", "0.9.1"
|
32
31
|
s.add_development_dependency "capybara", "~> 2.0.0"
|
33
32
|
s.add_development_dependency "rails", "~> 3.2.0"
|
34
33
|
|
data/readme.md
CHANGED
@@ -28,7 +28,7 @@ $ license_finder
|
|
28
28
|
On a brand new Rails project, you could expect `license_finder` to output something like the following
|
29
29
|
(assuming you whitelisted the MIT license -- see [Configuration](#configuration)):
|
30
30
|
|
31
|
-
```
|
31
|
+
```
|
32
32
|
Dependencies that need approval:
|
33
33
|
|
34
34
|
highline, 1.6.14, ruby
|
@@ -40,7 +40,7 @@ rubyzip, 0.9.9, ruby
|
|
40
40
|
xml-simple, 1.1.1, other
|
41
41
|
```
|
42
42
|
|
43
|
-
The executable task will also write out a dependencies.db, dependencies.
|
43
|
+
The executable task will also write out a dependencies.db, dependencies.csv, and dependencies.html file in the doc/
|
44
44
|
directory (by default -- see [Configuration](#configuration)).
|
45
45
|
|
46
46
|
The latter two files are human readable reports that you could send to your non-technical business partners, lawyers, etc.
|
@@ -73,7 +73,7 @@ whitelisted the "MIT" license in your `config/license_finder.yml`. You then add
|
|
73
73
|
which we'll assume is licensed with the `GPL` license. You then run `license_finder` and see
|
74
74
|
the gem listed in the output:
|
75
75
|
|
76
|
-
```
|
76
|
+
```sh
|
77
77
|
awesome_gpl_gem, 1.0.0, GPL
|
78
78
|
```
|
79
79
|
|
@@ -156,6 +156,17 @@ project, so you can use:
|
|
156
156
|
$ license_finder dependencies remove my_js_dep
|
157
157
|
```
|
158
158
|
|
159
|
+
### Managing project name
|
160
|
+
|
161
|
+
The HTML report generated by license_finder will have the name of your project at the top. By default, this is set to the name of your working directory. However, this can be changed using the command line:
|
162
|
+
|
163
|
+
```sh
|
164
|
+
$ license_finder project_name set 'My Project Name'
|
165
|
+
```
|
166
|
+
|
167
|
+
The changes will be reflected in the report the next time you run license_finder.
|
168
|
+
|
169
|
+
|
159
170
|
## Configuration
|
160
171
|
|
161
172
|
The first time you run `license_finder` it will create a default configuration file `./config/license_finder.yml`:
|
@@ -169,6 +180,7 @@ ignore_groups:
|
|
169
180
|
#- test
|
170
181
|
#- development
|
171
182
|
dependencies_file_dir: './doc/'
|
183
|
+
project_name: My Project Name
|
172
184
|
```
|
173
185
|
|
174
186
|
By modifying this file, you can configure license_finder's behavior. `Whitelisted` licenses will be automatically approved
|
@@ -176,6 +188,16 @@ and `ignore_groups` will limit which dependencies are included in your license r
|
|
176
188
|
and text files in another directory by changing `dependencies_file_dir`.
|
177
189
|
|
178
190
|
|
191
|
+
## HTML Report
|
192
|
+
|
193
|
+
The HTML report generated by license_finder has two sections, an overview at the top, and then a series of dependency summaries afterwards.
|
194
|
+
|
195
|
+
![HTML Report](files/report_breakdown.png)
|
196
|
+
|
197
|
+
The individual dependency summary follows a pattern like this:
|
198
|
+
|
199
|
+
![HTML Report](files/dependency_breakdown.png)
|
200
|
+
|
179
201
|
## Upgrade for pre 0.8.0 users
|
180
202
|
|
181
203
|
If you wish to cleanup your root directory you can run:
|
@@ -20,3 +20,9 @@ Push both versions of the gem
|
|
20
20
|
$ rake release # will push default MRI build of gem, and importantly, tag the gem
|
21
21
|
$ gem push pkg/license_finder-LATEST_VERSION_HERE-java.gem
|
22
22
|
```
|
23
|
+
|
24
|
+
|
25
|
+
## Release Script
|
26
|
+
|
27
|
+
There is now a release bash script that automates this process. You will need the necessary
|
28
|
+
rubies installed before performing the script in `release/publish.sh`
|
data/release/publish.sh
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env bash -l
|
2
|
+
|
3
|
+
export LF_GEM_VERSION=`ruby release/gem_version.rb`
|
4
|
+
|
5
|
+
read -p "This will build and release license_finder $LF_GEM_VERSION -- are you sure you wish to continue? [Y/n] " -n 1 -r
|
6
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
7
|
+
then
|
8
|
+
printf "\nAborted!"
|
9
|
+
exit
|
10
|
+
fi
|
11
|
+
|
12
|
+
function perform {
|
13
|
+
printf "\n> $1\n"
|
14
|
+
$1
|
15
|
+
}
|
16
|
+
|
17
|
+
printf "\nBuilding jruby... (1.7.4)"
|
18
|
+
perform "rvm use jruby-1.7.4"
|
19
|
+
perform "rake build"
|
20
|
+
|
21
|
+
printf "\nBuilding ruby... (2.0.0)"
|
22
|
+
perform "rvm use ruby-2.0.0"
|
23
|
+
perform "rake build"
|
24
|
+
|
25
|
+
printf "\nPublishing to rubygems..."
|
26
|
+
perform "rake release"
|
27
|
+
perform "gem push pkg/license_finder-$LF_GEM_VERSION-java.gem"
|
28
|
+
|
29
|
+
printf "\nRelease finished."
|