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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.rdoc +27 -3
  4. data/db/migrate/201307250917_add_license_manual_to_dependencies.rb +7 -0
  5. data/db/migrate/201307251004_data_fix_manual_licenses.rb +15 -0
  6. data/db/migrate/201307251107_reassociate_license.rb +23 -0
  7. data/db/migrate/201307251340_remove_manual_from_license_aliases.rb +7 -0
  8. data/features/cli.feature +1 -1
  9. data/features/html_report.feature +3 -2
  10. data/features/project_name.feature +10 -0
  11. data/features/set_license.feature +1 -0
  12. data/features/step_definitions/cli_steps.rb +3 -3
  13. data/features/step_definitions/project_name_steps.rb +3 -0
  14. data/features/step_definitions/set_license_steps.rb +9 -4
  15. data/features/step_definitions/shared_steps.rb +11 -2
  16. data/features/step_definitions/text_report_steps.rb +12 -2
  17. data/features/text_report.feature +7 -1
  18. data/files/dependency_breakdown.png +0 -0
  19. data/files/license_finder.yml +1 -0
  20. data/files/report_breakdown.png +0 -0
  21. data/lib/license_finder.rb +0 -5
  22. data/lib/license_finder/bundle.rb +22 -4
  23. data/lib/license_finder/bundled_gem.rb +17 -10
  24. data/lib/license_finder/bundled_gem_saver.rb +42 -30
  25. data/lib/license_finder/cli.rb +37 -5
  26. data/lib/license_finder/configuration.rb +13 -2
  27. data/lib/license_finder/dependency_manager.rb +21 -8
  28. data/lib/license_finder/reports/dependency_report.rb +1 -1
  29. data/lib/license_finder/reports/reporter.rb +4 -0
  30. data/lib/license_finder/tables/dependency.rb +9 -1
  31. data/lib/license_finder/tables/license_alias.rb +0 -4
  32. data/lib/license_finder/yml_to_sql.rb +1 -11
  33. data/lib/templates/html_report.erb +13 -3
  34. data/license_finder.gemspec +3 -4
  35. data/readme.md +25 -3
  36. data/release/gem_version.rb +3 -0
  37. data/{release.md → release/manual_instructions.md} +6 -0
  38. data/release/publish.sh +29 -0
  39. data/spec/lib/license_finder/bundle_spec.rb +16 -4
  40. data/spec/lib/license_finder/bundled_gem_saver_spec.rb +41 -38
  41. data/spec/lib/license_finder/bundled_gem_spec.rb +22 -4
  42. data/spec/lib/license_finder/cli_spec.rb +22 -0
  43. data/spec/lib/license_finder/configuration_spec.rb +34 -14
  44. data/spec/lib/license_finder/dependency_manager_spec.rb +61 -10
  45. data/spec/lib/license_finder/reporter_spec.rb +35 -1
  46. data/spec/lib/license_finder/tables/dependency_spec.rb +23 -0
  47. data/spec/lib/license_finder/tables/license_alias_spec.rb +0 -16
  48. data/spec/lib/license_finder/yml_to_sql_spec.rb +11 -3
  49. data/spec/lib/license_finder_spec.rb +2 -2
  50. data/spec/spec_helper.rb +3 -13
  51. metadata +21 -8
@@ -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.split("::").last.downcase} #{command.usage}"
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 = LicenseFinder.current_gems.map(&:save_as_dependency)
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).license.set_manually(license) }
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
 
@@ -16,7 +16,7 @@ module LicenseFinder
16
16
 
17
17
  def to_s
18
18
  filename = ROOT_PATH.join('templates', "#{self.class.underscored_name}.erb")
19
- template = ERB.new(File.read(filename), 0, '-')
19
+ template = ERB.new(File.read(filename), nil, '-')
20
20
  template.result(binding)
21
21
  end
22
22
 
@@ -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
- (license && license.whitelisted?) || approval.state
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!
@@ -9,10 +9,6 @@ module LicenseFinder
9
9
  !!(config.whitelisted?(name))
10
10
  end
11
11
 
12
- def set_manually(name)
13
- update('name' => name, 'manual' => true)
14
- end
15
-
16
12
  private
17
13
 
18
14
  def config
@@ -67,7 +67,7 @@ module LicenseFinder
67
67
  end
68
68
 
69
69
  def create_license
70
- Sql::LicenseAlias.convert(legacy_attrs)
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="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet">
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
- <h1>Dependencies</h1>
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
- <h1>Action Items</h1>
50
+ <h2>Action Items</h2>
41
51
  <h4><%= unapproved_dependencies.size %> unapproved dependencies</h4>
42
52
  <ul>
43
53
  <% unapproved_dependencies.each do |dependency| -%>
@@ -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.0"
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
- ```yaml
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.txt, and dependencies.html file in the doc/
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
- ```txt
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:
@@ -0,0 +1,3 @@
1
+ require 'bundler'
2
+
3
+ puts Bundler.load_gemspec('license_finder.gemspec').version
@@ -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`
@@ -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."