licensed 2.13.0 → 2.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4477f07cae2650a7d8679a9042f73a7d14d8de019088be22d09f30e0f8af4c2
4
- data.tar.gz: b4cbd8769c1f98b1a0729e5d603ff08c15d2d5c5e4e8e029cd3bce7f69f395c1
3
+ metadata.gz: 1042edfc8e49ab1430a73001612f260fb20f80931139649f8b8ae6f044d74463
4
+ data.tar.gz: 386c548165ed4c4ed1b5b78131635552c11ec03f6a09e8f75e328d1446b129a7
5
5
  SHA512:
6
- metadata.gz: 83e7612e7a1fe2dbb77d48893c68db036630a45cdbc37f38f6630be0380231d9ac7fc0d37298d3a8a349d4bd43eb1dad64b7ec26a4b8d795806fb682091d94b7
7
- data.tar.gz: 26e4fed8cede2d4de43fc511a85a82507dcc0cbcc9a66537d39a189d533a7cfbb22fdf2be5ad242ae72f4943fde6676c23b0bdcdf906beeecef813369177c158
6
+ metadata.gz: c163d4d2bbffe0756b4aecfa353a99d8d3be92ea7fe5b536d00dc79b1581132b31bf69fd0947a85de095ec2d5604da547d175507a199427b1e74da25e8b63a03
7
+ data.tar.gz: 719df2438ad31e8e525f15ae2b9948f1fc3a0a83b5e72f2e109b10d498f65734d6ab49af99fb92486e31d4314a635a0a2d5bdca793bd51412804b76d9b48042a
@@ -1,20 +1,97 @@
1
- name: Create release
2
-
3
- on: create
1
+ name: Build and publish release assets
2
+
3
+ on:
4
+ release:
5
+ types: [created]
6
+ workflow_dispatch:
7
+ inputs:
8
+ version:
9
+ description: 'Commit-like version of github/licensed to build package at'
10
+ required: true
11
+ release_tag:
12
+ description: 'Release tag to upload built packages to'
13
+ required: false
4
14
 
5
15
  jobs:
6
- tag_filter:
16
+ vars:
17
+ name: "Gather values for remainder of steps"
7
18
  runs-on: ubuntu-latest
8
- if: startsWith(github.ref, 'refs/tags/')
19
+ outputs:
20
+ version: ${{ steps.get_version.outputs.result }}
21
+ upload_url: ${{ steps.get_url.outputs.result }}
22
+ ref: ${{ steps.get_ref.outputs.result }}
9
23
  steps:
10
- - run: exit 0
24
+ - id: get_version
25
+ name: Get package version
26
+ uses: actions/github-script@v3
27
+ with:
28
+ github-token: ${{ secrets.GITHUB_TOKEN }}
29
+ result-encoding: string
30
+ script: |
31
+ let version = "${{ github.event.release.tag_name }}"
32
+ if (!version) {
33
+ version = "${{ github.event.inputs.version }}"
34
+ }
35
+
36
+ if (!version) {
37
+ throw new Error("unable to find package build version")
38
+ }
39
+
40
+ return version
41
+
42
+ - id: get_url
43
+ name: Get release upload url
44
+ uses: actions/github-script@v3
45
+ with:
46
+ github-token: ${{ secrets.GITHUB_TOKEN }}
47
+ result-encoding: string
48
+ script: |
49
+ let uploadUrl = "${{ github.event.release.upload_url}}"
50
+ const tag = "${{ github.event.inputs.release_tag }}"
51
+ if (!uploadUrl && tag) {
52
+ const { data: release } = await github.repos.getReleaseByTag({
53
+ ...context.repo,
54
+ tag
55
+ })
56
+
57
+ if (!release.upload_url) {
58
+ throw new Error("unable to find a release upload url")
59
+ }
60
+
61
+ uploadUrl = release.upload_url
62
+ }
63
+
64
+ return uploadUrl
65
+
66
+ - id: get_ref
67
+ name: Get checkout ref for custom build scripts
68
+ uses: actions/github-script@v3
69
+ with:
70
+ github-token: ${{ secrets.GITHUB_TOKEN }}
71
+ result-encoding: string
72
+ script: |
73
+ let ref = "${{ github.event.release.tag_name }}"
74
+ if (!ref) {
75
+ ref = "${{ github.event.ref }}".replace(/refs\/[^\/]+\//, '')
76
+ }
77
+
78
+ if (!ref) {
79
+ throw new Error("unable to find a ref for action")
80
+ }
81
+
82
+ return ref
11
83
 
12
84
  package_linux:
85
+ needs: vars
13
86
  runs-on: ubuntu-latest
14
- needs: tag_filter
15
-
16
87
  steps:
17
88
  - uses: actions/checkout@v2
89
+ with:
90
+ # checkout at the ref for the action, separate from the target build version
91
+ # this allows running build scripts independent of the target version
92
+ ref: ${{needs.vars.outputs.ref}}
93
+ fetch-depth: 0
94
+
18
95
  - name: Set up Ruby 2.6
19
96
  uses: actions/setup-ruby@v1
20
97
  with:
@@ -23,19 +100,24 @@ jobs:
23
100
  - name: Build package
24
101
  run: script/packages/linux
25
102
  env:
26
- VERSION: ${{github.event.ref}}
103
+ VERSION: ${{needs.vars.outputs.version}}
27
104
 
28
105
  - uses: actions/upload-artifact@v2
29
106
  with:
30
- name: ${{github.event.ref}}-linux
31
- path: pkg/${{github.event.ref}}/licensed-${{github.event.ref}}-linux-x64.tar.gz
107
+ name: ${{needs.vars.outputs.version}}-linux
108
+ path: pkg/${{needs.vars.outputs.version}}/licensed-${{needs.vars.outputs.version}}-linux-x64.tar.gz
32
109
 
33
110
  package_mac:
111
+ needs: vars
34
112
  runs-on: macOS-latest
35
- needs: tag_filter
36
-
37
113
  steps:
38
114
  - uses: actions/checkout@v2
115
+ with:
116
+ # checkout at the ref for the action, separate from the target build version
117
+ # this allows running build scripts independent of the target version
118
+ ref: ${{needs.vars.outputs.ref}}
119
+ fetch-depth: 0
120
+
39
121
  - name: Set up Ruby 2.6
40
122
  uses: actions/setup-ruby@v1
41
123
  with:
@@ -44,44 +126,39 @@ jobs:
44
126
  - name: Build package
45
127
  run: script/packages/mac
46
128
  env:
47
- VERSION: ${{github.event.ref}}
129
+ VERSION: ${{needs.vars.outputs.version}}
48
130
 
49
131
  - uses: actions/upload-artifact@v2
50
132
  with:
51
- name: ${{github.event.ref}}-darwin
52
- path: pkg/${{github.event.ref}}/licensed-${{github.event.ref}}-darwin-x64.tar.gz
133
+ name: ${{needs.vars.outputs.version}}-darwin
134
+ path: pkg/${{needs.vars.outputs.version}}/licensed-${{needs.vars.outputs.version}}-darwin-x64.tar.gz
53
135
 
54
136
  build_gem:
137
+ needs: vars
55
138
  runs-on: ubuntu-latest
56
- needs: tag_filter
57
-
58
139
  steps:
59
140
  - uses: actions/checkout@v2
141
+ with:
142
+ # building a gem doesn't use a different ref from the version input
143
+ ref: ${{needs.vars.outputs.version}}
144
+
60
145
  - name: Set up Ruby 2.6
61
146
  uses: actions/setup-ruby@v1
62
147
  with:
63
148
  ruby-version: 2.6.x
64
149
 
65
150
  - name: Build gem
66
- run: gem build *.gemspec
151
+ run: gem build licensed.gemspec -o licensed-${{needs.vars.outputs.version}}.gem
67
152
 
68
153
  - uses: actions/upload-artifact@v2
69
154
  with:
70
- name: ${{github.event.ref}}-gem
71
- path: licensed-${{github.event.ref}}.gem
72
-
73
- create_release:
74
- runs-on: ubuntu-latest
75
- needs: [package_linux, package_mac, build_gem]
76
- steps:
77
- - uses: Roang-zero1/github-create-release-action@v1.0.2
78
- env:
79
- GITHUB_TOKEN: ${{ secrets.API_AUTH_TOKEN }}
80
- VERSION_REGEX: "^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+"
155
+ name: ${{needs.vars.outputs.version}}-gem
156
+ path: licensed-${{needs.vars.outputs.version}}.gem
81
157
 
82
158
  upload_packages:
159
+ if: ${{ needs.vars.outputs.upload_url != '' }}
83
160
  runs-on: ubuntu-latest
84
- needs: [create_release]
161
+ needs: [vars, package_linux, package_mac, build_gem]
85
162
 
86
163
  steps:
87
164
  - name: Set up Ruby 2.6
@@ -92,32 +169,45 @@ jobs:
92
169
  - name: Download linux package
93
170
  uses: actions/download-artifact@v2
94
171
  with:
95
- name: ${{github.event.ref}}-linux
172
+ name: ${{needs.vars.outputs.version}}-linux
96
173
 
97
174
  - name: Download macOS package
98
175
  uses: actions/download-artifact@v2
99
176
  with:
100
- name: ${{github.event.ref}}-darwin
177
+ name: ${{needs.vars.outputs.version}}-darwin
101
178
 
102
179
  - name: Download gem
103
180
  uses: actions/download-artifact@v2
104
181
  with:
105
- name: ${{github.event.ref}}-gem
182
+ name: ${{needs.vars.outputs.version}}-gem
106
183
 
107
- - name: Publish packages to GitHub Release
108
- uses: Roang-zero1/github-upload-release-artifacts-action@v2.0.0
184
+ - name: Publish linux package
185
+ uses: actions/upload-release-asset@v1
186
+ env:
187
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109
188
  with:
110
- args: licensed-${{github.event.ref}}-linux-x64.tar.gz licensed-${{github.event.ref}}-darwin-x64.tar.gz
189
+ upload_url: ${{ needs.vars.outputs.upload_url }}
190
+ asset_path: ./licensed-${{needs.vars.outputs.version}}-linux-x64.tar.gz
191
+ asset_name: licensed-${{needs.vars.outputs.version}}-linux-x64.tar.gz
192
+ asset_content_type: application/gzip
193
+
194
+ - name: Publish mac package
195
+ uses: actions/upload-release-asset@v1
111
196
  env:
112
- GITHUB_TOKEN: ${{secrets.API_AUTH_TOKEN}}
197
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
198
+ with:
199
+ upload_url: ${{ needs.vars.outputs.upload_url }}
200
+ asset_path: ./licensed-${{needs.vars.outputs.version}}-darwin-x64.tar.gz
201
+ asset_name: licensed-${{needs.vars.outputs.version}}-darwin-x64.tar.gz
202
+ asset_content_type: application/gzip
113
203
 
114
204
  - name: Publish gem to RubyGems
115
205
  run: |
116
206
  mkdir -p $HOME/.gem
117
207
  touch $HOME/.gem/credentials
118
208
  chmod 0600 $HOME/.gem/credentials
119
- printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
209
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
120
210
  gem push $GEM
121
211
  env:
122
- GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
123
- GEM: licensed-${{github.event.ref}}.gem
212
+ RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
213
+ GEM: licensed-${{needs.vars.outputs.version}}.gem
@@ -165,7 +165,7 @@ jobs:
165
165
  runs-on: ubuntu-latest
166
166
  strategy:
167
167
  matrix:
168
- go: [ '1.7.x', '1.10.x', '1.11.x', '1.12.x', '1.13.x', '1.14.x' ]
168
+ go: [ '1.10.x', '1.11.x', '1.12.x', '1.13.x', '1.14.x', '1.15.x' ]
169
169
  steps:
170
170
  - uses: actions/checkout@v2
171
171
  - name: Setup go
data/CHANGELOG.md CHANGED
@@ -6,6 +6,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 2.14.4
10
+ 2021-02-09
11
+
12
+ ## Added
13
+ - `list` and `cache` commands optionally print output in JSON or YML formats using the `--format/-f` flag (https://github.com/github/licensed/pull/334)
14
+ - `list` command will include detected license keys using the `--licenses/-l` flag (https://github.com/github/licensed/pull/334)
15
+
16
+ ## 2.14.3
17
+ 2020-12-11
18
+
19
+ ## Fixed
20
+ - Auto-generating license text for a known license will no longer raise an error if the found license has no text (:tada: @Eun https://github.com/github/licensed/pull/328)
21
+
22
+ ## 2.14.2
23
+ 2020-11-20
24
+
25
+ ## Fixed
26
+ - Yarn source correctly finds dependency paths on disk (https://github.com/github/licensed/pull/326)
27
+ - Go source better handles finding dependencies that have been vendored (https://github.com/github/licensed/pull/323)
28
+
29
+ ## 2.14.1
30
+ 2020-10-09
31
+
32
+ ### Fixed
33
+ - Shell command output is encoded to UTF8 (https://github.com/github/licensed/pull/319)
34
+
35
+ ## 2.14.0
36
+ 2020-10-04
37
+
38
+ ### Added
39
+ - `reviewed` dependencies can use glob pattern matching (https://github.com/github/licensed/pull/313)
40
+
41
+ ### Fixed
42
+ - Fix configuring source path globs that expand into a single directory (https://github.com/github/licensed/pull/312)
43
+
9
44
  ## 2.13.0
10
45
  2020-09-23
11
46
 
@@ -351,4 +386,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
351
386
 
352
387
  Initial release :tada:
353
388
 
354
- [Unreleased]: https://github.com/github/licensed/compare/2.13.0...HEAD
389
+ [Unreleased]: https://github.com/github/licensed/compare/2.14.4...HEAD
data/CONTRIBUTING.md CHANGED
@@ -39,7 +39,7 @@ Pull requests that include a new dependency source must also
39
39
  ## Releasing
40
40
  If you are the current maintainer of this gem:
41
41
 
42
- 1. Create a branch for the release: git checkout -b cut-release-vxx.xx.xx
42
+ 1. Create a branch for the release: git checkout -b cut-release-xx.xx.xx
43
43
  2. Make sure your local dependencies are up to date: `script/bootstrap`
44
44
  3. Ensure that tests are green: `bundle exec rake test`
45
45
  4. Bump gem version in lib/licensed/version.rb.
@@ -51,15 +51,16 @@ If you are the current maintainer of this gem:
51
51
  2. Install the new gem locally
52
52
  3. Test behavior locally, branch deploy, whatever needs to happen
53
53
  9. Merge github/licensed PR
54
- 10. Tag and push: `git tag x.xx.xx; git push --tags`
54
+ 10. Create a new [github/licensed release](https://github.com/github/licensed/releases)
55
+ - Set the release name and tag to the release version - `x.xx.x`
56
+ - Set the release body to the changelog entries for the release
55
57
 
56
58
  The following steps will happen automatically from a GitHub Actions workflow
57
- after pushing a new tag. In case that fails, the following steps can be performed manually
59
+ after creating the release. In case that fails, the following steps can be performed manually
58
60
 
59
- 11. Push to rubygems.org -- `gem push licensed-x.xx.xx.gem`
61
+ 11. Push the gem from (7) to rubygems.org -- `gem push licensed-x.xx.xx.gem`
60
62
  12. Build packages for new tag: `VERSION=x.xx.xx bundle exec rake package`
61
- 13. Create release for new tag at github/licensed.
62
- 14. Add built packages to new release
63
+ 13. Upload packages from (12) to release from (10)
63
64
 
64
65
  ## Resources
65
66
 
@@ -12,3 +12,4 @@ RUN gem update --system && gem update bundler
12
12
  ENV CPPFLAGS="-P"
13
13
  ENV RUBYC="/usr/local/bin/rubyc"
14
14
  ENV LANG=C.UTF-8
15
+ ENV SSL_CERT_DIR="/etc/ssl/certs"
@@ -23,7 +23,7 @@ If a root path is not specified, it will default to using the following, in orde
23
23
 
24
24
  The `source_path` property can use a glob path to share configuration properties across multiple application entrypoints.
25
25
 
26
- For example, there is a common pattern in go projects to include multiple executable entrypoints under folders in `cmd`. Using a glob pattern allows users to avoid manually configuring and maintaining multiple licensed application `source_path`s. Using a glob pattern will also ensure that any new entrypoints matching the pattern are automatically picked up by licensed commands as they are added.
26
+ For example, there is a common pattern in Go projects to include multiple executable entrypoints under folders in `cmd`. Using a glob pattern allows users to avoid manually configuring and maintaining multiple licensed application `source_path`s. Using a glob pattern will also ensure that any new entrypoints matching the pattern are automatically picked up by licensed commands as they are added.
27
27
 
28
28
  ```yml
29
29
  sources:
@@ -118,12 +118,6 @@ ignored:
118
118
  bower:
119
119
  - some-internal-package
120
120
 
121
- go:
122
- # ignore all go packages from import paths starting with github.com/internal-package
123
- # see the `File.fnmatch?` documentation for details on how patterns are matched.
124
- # comparisons use the FNM_CASEFOLD and FNM_PATHNAME flags
125
- - github.com/internal-package/**/*
126
-
127
121
  # These dependencies have licenses not on the `allowed` list and have been reviewed.
128
122
  # They will be cached and checked, but will not raise errors or warnings for a
129
123
  # non-allowed license. Dependencies on this list will still raise errors if
data/docs/sources/go.md CHANGED
@@ -24,6 +24,26 @@ The setting supports absolute, relative and expandable (e.g. "~") paths. Relati
24
24
 
25
25
  Non-empty `GOPATH` configuration settings will override the `GOPATH` environment variable while enumerating `go` dependencies. The `GOPATH` environment variable is restored once dependencies have been enumerated.
26
26
 
27
+ #### Reviewing and ignoring all packages from a Go module
28
+
29
+ Go's package and module structure has common conventions that documentation and metadata for all packages in a module live in the module root. In this scenario all packages share the same LICENSE information and can be reviewed or ignored at the module level rather than per-package using glob patterns.
30
+
31
+ ```yaml
32
+ reviewed:
33
+ go:
34
+ # review all Go packages from import paths starting with github.com/external-package
35
+ # see the `File.fnmatch?` documentation for details on how patterns are matched.
36
+ # comparisons use the FNM_CASEFOLD and FNM_PATHNAME flags
37
+ - github.com/external-package/**/*
38
+
39
+ ignored:
40
+ go:
41
+ # ignore all Go packages from import paths starting with github.com/internal-package
42
+ # see the `File.fnmatch?` documentation for details on how patterns are matched.
43
+ # comparisons use the FNM_CASEFOLD and FNM_PATHNAME flags
44
+ - github.com/internal-package/**/*
45
+ ```
46
+
27
47
  #### Versioning
28
48
 
29
49
  The go source supports multiple versioning strategies to determine if cached dependency metadata is stale. A version strategy is chosen based on the availability of go module information along with the current app configuration.
data/lib/licensed/cli.rb CHANGED
@@ -12,9 +12,11 @@ module Licensed
12
12
  desc: "Path to licensed configuration file"
13
13
  method_option :sources, aliases: "-s", type: :array,
14
14
  desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
15
+ method_option :format, aliases: "-f", enum: ["yaml", "json"],
16
+ desc: "Output format"
15
17
  def cache
16
18
  run Licensed::Commands::Cache.new(config: config),
17
- force: options[:force], sources: options[:sources]
19
+ force: options[:force], sources: options[:sources], reporter: options[:format]
18
20
  end
19
21
 
20
22
  desc "status", "Check status of dependencies' cached licenses"
@@ -33,8 +35,12 @@ module Licensed
33
35
  desc: "Path to licensed configuration file"
34
36
  method_option :sources, aliases: "-s", type: :array,
35
37
  desc: "Individual source(s) to evaluate. Must also be enabled via configuration."
38
+ method_option :format, aliases: "-f", enum: ["yaml", "json"],
39
+ desc: "Output format"
40
+ method_option :licenses, aliases: "-l", type: :boolean,
41
+ desc: "Include detected licenses in output"
36
42
  def list
37
- run Licensed::Commands::List.new(config: config), sources: options[:sources]
43
+ run Licensed::Commands::List.new(config: config), sources: options[:sources], reporter: options[:format], licenses: options[:licenses]
38
44
  end
39
45
 
40
46
  desc "notices", "Generate a NOTICE file from cached records"
@@ -72,6 +72,12 @@ module Licensed
72
72
  # Returns whether the command succeeded for the application.
73
73
  def run_app(app)
74
74
  reporter.report_app(app) do |report|
75
+ # ensure the app source path exists before evaluation
76
+ if !Dir.exist?(app.source_path)
77
+ report.errors << "No such directory #{app.source_path}"
78
+ next false
79
+ end
80
+
75
81
  Dir.chdir app.source_path do
76
82
  begin
77
83
  # allow additional report data to be given by commands
@@ -41,6 +41,13 @@ module Licensed
41
41
  #
42
42
  # Returns true.
43
43
  def evaluate_dependency(app, source, dependency, report)
44
+ report["dependency"] = dependency.name
45
+ report["version"] = dependency.version
46
+
47
+ if options[:licenses]
48
+ report["license"] = dependency.license_key
49
+ end
50
+
44
51
  true
45
52
  end
46
53
  end
@@ -69,7 +69,9 @@ module Licensed
69
69
 
70
70
  # Is the given dependency reviewed?
71
71
  def reviewed?(dependency)
72
- Array(self["reviewed"][dependency["type"]]).include?(dependency["name"])
72
+ Array(self["reviewed"][dependency["type"]]).any? do |pattern|
73
+ File.fnmatch?(pattern, dependency["name"], File::FNM_PATHNAME | File::FNM_CASEFOLD)
74
+ end
73
75
  end
74
76
 
75
77
  # Is the given dependency ignored?
@@ -158,19 +160,22 @@ module Licensed
158
160
  def self.expand_app_source_path(app_config)
159
161
  return app_config if app_config["source_path"].to_s.empty?
160
162
 
163
+ # check if the source path maps to an existing directory
161
164
  source_path = File.expand_path(app_config["source_path"], AppConfiguration.root_for(app_config))
165
+ return app_config if Dir.exist?(source_path)
166
+
167
+ # try to expand the source path for glob patterns
162
168
  expanded_source_paths = Dir.glob(source_path).select { |p| File.directory?(p) }
163
- # return the original configuration if glob didn't result in multiple paths
164
- return app_config if expanded_source_paths.size <= 1
169
+ configs = expanded_source_paths.map { |path| app_config.merge("source_path" => path) }
165
170
 
166
- # map the expanded paths to new application configurations
167
- expanded_source_paths.map do |path|
168
- config = app_config.merge("source_path" => path)
171
+ # if no directories are found for the source path, return the original config
172
+ return app_config if configs.size == 0
169
173
 
170
- # update configured values for name and cache_path for uniqueness.
171
- # this is only needed when values are explicitly set, AppConfiguration
172
- # will handle configurations that don't have these explicitly set
173
- dir_name = File.basename(path)
174
+ # update configured values for name and cache_path for uniqueness.
175
+ # this is only needed when values are explicitly set, AppConfiguration
176
+ # will handle configurations that don't have these explicitly set
177
+ configs.each do |config|
178
+ dir_name = File.basename(config["source_path"])
174
179
  config["name"] = "#{config["name"]}-#{dir_name}" if config["name"]
175
180
 
176
181
  # if a cache_path is set and is not marked as shared, append the app name
@@ -178,9 +183,9 @@ module Licensed
178
183
  if config["cache_path"] && config["shared_cache"] != true
179
184
  config["cache_path"] = File.join(config["cache_path"], dir_name)
180
185
  end
181
-
182
- config
183
186
  end
187
+
188
+ configs
184
189
  end
185
190
 
186
191
  # Find a default configuration file in the given directory.
@@ -142,6 +142,7 @@ module Licensed
142
142
  def generated_license_contents
143
143
  return unless license
144
144
  return if license.key == "other"
145
+ return if license.text.nil?
145
146
 
146
147
  # strip copyright clauses and any extra newlines
147
148
  # many package managers don't provide enough information to
@@ -75,7 +75,9 @@ module Licensed
75
75
  def report_dependency(dependency)
76
76
  super do |report|
77
77
  result = yield report
78
- shell.info " #{dependency.name} (#{dependency.version})"
78
+ info = "#{dependency.name} (#{dependency.version})"
79
+ info = "#{info}: #{report["license"]}" if report["license"]
80
+ shell.info " #{info}"
79
81
 
80
82
  result
81
83
  end
@@ -9,11 +9,12 @@ module Licensed
9
9
  def self.execute(cmd, *args, allow_failure: false, env: {})
10
10
  stdout, stderr, status = Open3.capture3(env, cmd, *args)
11
11
 
12
- if status.success? || allow_failure
13
- stdout.strip
14
- else
15
- raise Error.new([cmd, *args], status.exitstatus, stderr)
12
+ if !status.success? && !allow_failure
13
+ raise Error.new([cmd, *args], status.exitstatus, encode_content(stderr))
16
14
  end
15
+
16
+ # ensure that returned data is properly encoded
17
+ encode_content(stdout.strip)
17
18
  end
18
19
 
19
20
  # Executes a command and returns a boolean value indicating if the command
@@ -55,5 +56,21 @@ module Licensed
55
56
  end.join(" ")
56
57
  end
57
58
  end
59
+
60
+ private
61
+
62
+ ENCODING = Encoding::UTF_8
63
+ ENCODING_OPTIONS = {
64
+ invalid: :replace,
65
+ undef: :replace,
66
+ replace: "",
67
+ univeral_newline: true
68
+ }.freeze
69
+
70
+ # Ensure that content that is returned from shell commands is in a usable
71
+ # encoding for the rest of the application
72
+ def self.encode_content(content)
73
+ content.encode(ENCODING, **ENCODING_OPTIONS)
74
+ end
58
75
  end
59
76
  end
@@ -15,8 +15,7 @@ module Licensed
15
15
  def enumerate_dependencies
16
16
  with_configured_gopath do
17
17
  packages.map do |package|
18
- import_path = non_vendored_path(package["ImportPath"], root_package["ImportPath"])
19
- import_path ||= package["ImportPath"]
18
+ import_path = non_vendored_import_path(package)
20
19
  error = package.dig("Error", "Err") if package["Error"]
21
20
 
22
21
  Dependency.new(
@@ -81,34 +80,26 @@ module Licensed
81
80
  # return true if package self-identifies
82
81
  return true if package["Standard"]
83
82
 
84
- import_path = package["ImportPath"]
83
+ import_path = non_vendored_import_path(package)
85
84
  return false unless import_path
86
85
 
87
- # true if go standard packages includes the import path as given
88
- return true if go_std_packages.include?(import_path)
89
- return true if go_std_packages.include?("vendor/#{import_path}")
90
- return true if go_std_packages.include?(import_path.sub("golang.org", "internal"))
91
-
92
- # additional checks are only for vendored dependencies - return false
93
- # if package isn't vendored
94
- non_vendored_import_path = non_vendored_path(import_path, root_package["ImportPath"])
95
- return false unless non_vendored_import_path
96
-
97
- # return true if any of the go standard packages matches against
98
- # the non-vendored import path
99
- return true if go_std_packages.include?(non_vendored_import_path)
100
- return true if go_std_packages.include?(non_vendored_import_path.sub("golang.org", "internal"))
101
-
102
- # modify the import path to look like the import path `go list` returns for vendored std packages
103
- vendor_path = import_path.sub("#{root_package["ImportPath"]}/", "")
104
- go_std_packages.include?(vendor_path) || go_std_packages.include?(vendor_path.sub("golang.org", "golang_org"))
86
+ # check different variations of the import path to match against
87
+ # what's returned from `go list std`
88
+ [
89
+ import_path,
90
+ import_path.sub("golang.org", "internal"),
91
+ import_path.sub("golang.org", "golang_org"),
92
+ ].any? do |path|
93
+ # true if go standard packages includes the path or "vendor/<path>"
94
+ go_std_packages.include?(path) || go_std_packages.include?("vendor/#{path}")
95
+ end
105
96
  end
106
97
 
107
98
  # Returns whether the package is local to the current project
108
99
  def local_package?(package)
109
- return false unless package && package["ImportPath"]
110
- import_path = package["ImportPath"]
111
- import_path.start_with?(root_package["ImportPath"]) && !import_path.include?("vendor/")
100
+ return false unless package && package["Dir"]
101
+ return false unless File.fnmatch?("#{config.root.to_s}*", package["Dir"])
102
+ vendored_path_parts(package).nil?
112
103
  end
113
104
 
114
105
  # Returns the version for a given package
@@ -155,36 +146,45 @@ module Licensed
155
146
 
156
147
  # search root choices:
157
148
  # 1. module directory if using go modules and directory is available
158
- # 2. vendor folder if package is vendored
159
- # 3. package root value if available
160
- # 4. GOPATH if the package directory is under the gopath
161
- # 5. nil
162
149
  module_dir = package.dig("Module", "Dir")
163
150
  return module_dir if module_dir
164
- return package["Dir"].match("^(.*/vendor)/.*$")[1] if vendored_path?(package["Dir"], config.root)
151
+
152
+ # 2. vendor folder if package is vendored
153
+ parts = vendored_path_parts(package)
154
+ return parts[:vendor_path] if parts
155
+
156
+ # 3. package root value if available
165
157
  return package["Root"] if package["Root"]
158
+
159
+ # 4. GOPATH if the package directory is under the gopath
166
160
  return gopath if package["Dir"]&.start_with?(gopath)
161
+
162
+ # 5. nil
167
163
  nil
168
164
  end
169
165
 
170
- # Returns whether a package is vendored or not based on a base path and
171
- # whether the path contains a vendor component
166
+ # If the package is vendored, returns a Match object containing named
167
+ # :vendor_path and :import_path match groups based on the packages "Dir" value
168
+ #
169
+ # If the package is not vendored, returns nil
172
170
  #
173
- # path - Package path to test
174
- # base - The base path that the input must start with
175
- def vendored_path?(path, base)
176
- return false if path.nil? || base.nil?
177
- path.start_with?(base.to_s) && path.include?("vendor/")
171
+ # package - Package to get vendored path information for
172
+ def vendored_path_parts(package)
173
+ return if package.nil? || package["Dir"].nil?
174
+ package["Dir"].match(/^(?<vendor_path>#{config.root}(\/.+)*\/[^\/]*vendor[^\/]*)\/(?<import_path>.+)$/i)
178
175
  end
179
176
 
180
- # Returns the path parameter without the vendor component if one is found
177
+ # Returns the non-vendored portion of the package import path if vendored,
178
+ # otherwise returns the package's import path as given
181
179
  #
182
- # path - Package path with vendor component
183
- # base - The base path that the input must start with
184
- def non_vendored_path(path, base)
185
- return unless path
186
- return unless vendored_path?(path, base)
187
- path.split("vendor/")[1]
180
+ # package - Package to get the non-vendored import path for
181
+ def non_vendored_import_path(package)
182
+ return if package.nil?
183
+ parts = vendored_path_parts(package)
184
+ return parts[:import_path] if parts
185
+
186
+ # if a package isn't vendored, return the packages "ImportPath"
187
+ package["ImportPath"]
188
188
  end
189
189
 
190
190
  # Returns a hash of information about the package with a given import path
@@ -36,7 +36,7 @@ module Licensed
36
36
  def packages
37
37
  return [] if yarn_package_tree.nil?
38
38
  all_dependencies = {}
39
- recursive_dependencies(config.pwd, yarn_package_tree).each do |name, results|
39
+ recursive_dependencies(yarn_package_tree).each do |name, results|
40
40
  results.uniq! { |package| package["version"] }
41
41
  if results.size == 1
42
42
  # if there is only one package for a name, reference it by name
@@ -55,26 +55,34 @@ module Licensed
55
55
 
56
56
  # Recursively parse dependency JSON data. Returns a hash mapping the
57
57
  # package name to it's metadata
58
- def recursive_dependencies(path, dependencies, result = {})
58
+ def recursive_dependencies(dependencies, result = {})
59
59
  dependencies.each do |dependency|
60
60
  # "shadow" indicate a dependency requirement only, not a
61
61
  # resolved package identifier
62
62
  next if dependency["shadow"]
63
63
  name, _, version = dependency["name"].rpartition("@")
64
64
 
65
- # the dependency should be found under the parent's "node_modules" path
66
- dependency_path = path.join("node_modules", name)
67
65
  (result[name] ||= []) << {
68
66
  "id" => dependency["name"],
69
67
  "name" => name,
70
68
  "version" => version,
71
- "path" => dependency_path
69
+ "path" => dependency_paths[dependency["name"]]
72
70
  }
73
- recursive_dependencies(dependency_path, dependency["children"], result)
71
+ recursive_dependencies(dependency["children"], result)
74
72
  end
75
73
  result
76
74
  end
77
75
 
76
+ # Returns a hash that maps all dependency names to their location on disk
77
+ # by parsing every package.json file under node_modules.
78
+ def dependency_paths
79
+ @dependency_paths ||= Dir.glob(config.pwd.join("node_modules/**/package.json")).each_with_object({}) do |file, hsh|
80
+ dirname = File.dirname(file)
81
+ json = JSON.parse(File.read(file))
82
+ hsh["#{json["name"]}@#{json["version"]}"] = dirname
83
+ end
84
+ end
85
+
78
86
  # Finds and returns the yarn package tree listing from `yarn list` output
79
87
  def yarn_package_tree
80
88
  return @yarn_package_tree if defined?(@yarn_package_tree)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Licensed
3
- VERSION = "2.13.0".freeze
3
+ VERSION = "2.14.4".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
@@ -34,6 +34,9 @@ build_linux_local() {
34
34
  sudo apt-get update
35
35
  sudo apt-get install -y --no-install-recommends cmake make gcc pkg-config squashfs-tools curl bison git rsync
36
36
 
37
+ sudo gem update --system
38
+ sudo gem update bundler
39
+
37
40
  RUBYC="$BASE_DIR/bin/rubyc-linux"
38
41
  if [ ! -f "$RUBYC" ]; then
39
42
  mkdir -p "$(dirname "$RUBYC")"
@@ -42,6 +45,7 @@ build_linux_local() {
42
45
  fi
43
46
 
44
47
  export CPPFLAGS="-P"
48
+ export SSL_CERT_DIR="/etc/ssl/certs"
45
49
  export RUBYC
46
50
  "$BASE_DIR"/script/packages/build
47
51
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: licensed
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.0
4
+ version: 2.14.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-24 00:00:00.000000000 Z
11
+ date: 2021-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee