licensed 2.14.0 → 2.15.0

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: b246cf67fe29bfe3612770c81b44006cdc185e2875deba36aa339b7f8be6d654
4
- data.tar.gz: 47e90e173cd914d214c270db673c1ffdff61f155853fec18da41837cebe7740b
3
+ metadata.gz: 6e90a33d845fe81078014cc53dd61cc5044fc908df4fe65e3c3ce05e11884e3f
4
+ data.tar.gz: b0c1f03b192d70ec84d27f6b614d7874f32238a98a606f44e777cd1ee2e436ce
5
5
  SHA512:
6
- metadata.gz: 8e651c1ce72c6802b7f13e813ea4227c8dbeb53058deb8f68f1c8eabbcf4b9c4b9bd4a130b2d00b4238e14577f0a341d55fabac5aa72d0c3d0195a4b75bd1c86
7
- data.tar.gz: b07832f775f62da3fef628bf3ca9769e6f33e9d32338ffe468dad212f27d65d2be455e57ac73786930017d55308cd5222f2280f2944c832a1f32fa5c8a3557bb
6
+ metadata.gz: d57bca03f12516e4802c50f4ac5483966659debe879f43f54ddec8d17a6ea05e88048693288a67e73ee68992981d127205025a16eb7fec7ae165554c3ea52d79
7
+ data.tar.gz: 74d3df3dbdd3f52f7c22d2ca006cb0893f8ec32873bab9b7d56998ad4c1ade63080f608498561834273c23a0e8b8e29fbad0b39a5942951c75b0b04350b8532a
@@ -3,96 +3,192 @@ name: Build and publish release assets
3
3
  on:
4
4
  release:
5
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
6
14
 
7
15
  jobs:
8
- package_linux:
16
+ vars:
17
+ name: "Gather values for remainder of steps"
9
18
  runs-on: ubuntu-latest
19
+ outputs:
20
+ version: ${{ steps.get_version.outputs.result }}
21
+ upload_url: ${{ steps.get_url.outputs.result }}
22
+ ref: ${{ steps.get_ref.outputs.result }}
23
+ steps:
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
83
+
84
+ package_linux:
85
+ needs: vars
86
+ runs-on: ubuntu-18.04
10
87
  steps:
11
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
+
12
95
  - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
96
+ uses: ruby/setup-ruby@v1
14
97
  with:
15
- ruby-version: 2.6.x
98
+ ruby-version: 2.6
16
99
 
17
100
  - name: Build package
18
101
  run: script/packages/linux
19
102
  env:
20
- VERSION: ${{github.event.release.tag_name}}
103
+ VERSION: ${{needs.vars.outputs.version}}
21
104
 
22
105
  - uses: actions/upload-artifact@v2
23
106
  with:
24
- name: ${{github.event.release.tag_name}}-linux
25
- path: pkg/${{github.event.release.tag_name}}/licensed-${{github.event.release.tag_name}}-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
26
109
 
27
110
  package_mac:
111
+ needs: vars
28
112
  runs-on: macOS-latest
29
113
  steps:
30
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
+
31
121
  - name: Set up Ruby 2.6
32
- uses: actions/setup-ruby@v1
122
+ uses: ruby/setup-ruby@v1
33
123
  with:
34
- ruby-version: 2.6.x
124
+ ruby-version: 2.6
35
125
 
36
126
  - name: Build package
37
127
  run: script/packages/mac
38
128
  env:
39
- VERSION: ${{github.event.release.tag_name}}
129
+ VERSION: ${{needs.vars.outputs.version}}
40
130
 
41
131
  - uses: actions/upload-artifact@v2
42
132
  with:
43
- name: ${{github.event.release.tag_name}}-darwin
44
- path: pkg/${{github.event.release.tag_name}}/licensed-${{github.event.release.tag_name}}-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
45
135
 
46
136
  build_gem:
137
+ needs: vars
47
138
  runs-on: ubuntu-latest
48
139
  steps:
49
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
+
50
145
  - name: Set up Ruby 2.6
51
- uses: actions/setup-ruby@v1
146
+ uses: ruby/setup-ruby@v1
52
147
  with:
53
- ruby-version: 2.6.x
148
+ ruby-version: 2.6
54
149
 
55
150
  - name: Build gem
56
- run: gem build licensed.gemspec -o licensed-${{github.event.release.tag_name}}.gem
151
+ run: gem build licensed.gemspec -o licensed-${{needs.vars.outputs.version}}.gem
57
152
 
58
153
  - uses: actions/upload-artifact@v2
59
154
  with:
60
- name: ${{github.event.release.tag_name}}-gem
61
- path: licensed-${{github.event.release.tag_name}}.gem
155
+ name: ${{needs.vars.outputs.version}}-gem
156
+ path: licensed-${{needs.vars.outputs.version}}.gem
62
157
 
63
158
  upload_packages:
159
+ if: ${{ needs.vars.outputs.upload_url != '' }}
64
160
  runs-on: ubuntu-latest
65
- needs: [package_linux, package_mac, build_gem]
161
+ needs: [vars, package_linux, package_mac, build_gem]
66
162
 
67
163
  steps:
68
164
  - name: Set up Ruby 2.6
69
- uses: actions/setup-ruby@v1
165
+ uses: ruby/setup-ruby@v1
70
166
  with:
71
- ruby-version: 2.6.x
167
+ ruby-version: 2.6
72
168
 
73
169
  - name: Download linux package
74
170
  uses: actions/download-artifact@v2
75
171
  with:
76
- name: ${{github.event.release.tag_name}}-linux
172
+ name: ${{needs.vars.outputs.version}}-linux
77
173
 
78
174
  - name: Download macOS package
79
175
  uses: actions/download-artifact@v2
80
176
  with:
81
- name: ${{github.event.release.tag_name}}-darwin
177
+ name: ${{needs.vars.outputs.version}}-darwin
82
178
 
83
179
  - name: Download gem
84
180
  uses: actions/download-artifact@v2
85
181
  with:
86
- name: ${{github.event.release.tag_name}}-gem
182
+ name: ${{needs.vars.outputs.version}}-gem
87
183
 
88
184
  - name: Publish linux package
89
185
  uses: actions/upload-release-asset@v1
90
186
  env:
91
187
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
92
188
  with:
93
- upload_url: ${{ github.event.release.upload_url }}
94
- asset_path: ./licensed-${{github.event.release.tag_name}}-linux-x64.tar.gz
95
- asset_name: licensed-${{github.event.release.tag_name}}-linux-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
96
192
  asset_content_type: application/gzip
97
193
 
98
194
  - name: Publish mac package
@@ -100,9 +196,9 @@ jobs:
100
196
  env:
101
197
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102
198
  with:
103
- upload_url: ${{ github.event.release.upload_url }}
104
- asset_path: ./licensed-${{github.event.release.tag_name}}-darwin-x64.tar.gz
105
- asset_name: licensed-${{github.event.release.tag_name}}-darwin-x64.tar.gz
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
106
202
  asset_content_type: application/gzip
107
203
 
108
204
  - name: Publish gem to RubyGems
@@ -114,4 +210,4 @@ jobs:
114
210
  gem push $GEM
115
211
  env:
116
212
  RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
117
- GEM: licensed-${{github.event.release.tag_name}}.gem
213
+ GEM: licensed-${{needs.vars.outputs.version}}.gem
@@ -8,15 +8,15 @@ jobs:
8
8
  steps:
9
9
  - uses: actions/checkout@v2
10
10
  - name: Setup node
11
- uses: actions/setup-node@v1
11
+ uses: actions/setup-node@v2
12
12
  with:
13
13
  node-version: 8
14
14
  - name: Install Bower
15
15
  run: npm install -g bower
16
16
  - name: Set up Ruby
17
- uses: actions/setup-ruby@v1
17
+ uses: ruby/setup-ruby@v1
18
18
  with:
19
- ruby-version: 2.6.x
19
+ ruby-version: 2.6
20
20
  - run: bundle lock
21
21
  - uses: actions/cache@v1
22
22
  with:
@@ -37,9 +37,9 @@ jobs:
37
37
  steps:
38
38
  - uses: actions/checkout@v2
39
39
  - name: Set up Ruby
40
- uses: actions/setup-ruby@v1
40
+ uses: ruby/setup-ruby@v1
41
41
  with:
42
- ruby-version: 2.6.x
42
+ ruby-version: 2.6
43
43
  - name: Set up Bundler
44
44
  run: |
45
45
  yes | gem uninstall bundler --all
@@ -60,16 +60,16 @@ jobs:
60
60
  runs-on: ubuntu-latest
61
61
  strategy:
62
62
  matrix:
63
- ghc: [ '8.2.2', '8.6.5' ]
64
- cabal: [ '2.2', '2.4', '3.0', 'latest' ]
63
+ ghc: [ '8.2', '8.6', '8.8', '8.10' ]
64
+ cabal: [ '2.4', '3.0', '3.2' ]
65
65
  steps:
66
66
  - uses: actions/checkout@v2
67
67
  - name: Set up Ruby
68
- uses: actions/setup-ruby@v1
68
+ uses: ruby/setup-ruby@v1
69
69
  with:
70
- ruby-version: 2.6.x
70
+ ruby-version: 2.6
71
71
  - name: Setup Haskell
72
- uses: actions/setup-haskell@v1
72
+ uses: haskell/actions/setup@v1
73
73
  with:
74
74
  ghc-version: ${{ matrix.ghc }}
75
75
  cabal-version: ${{ matrix.cabal }}
@@ -89,17 +89,17 @@ jobs:
89
89
  runs-on: ubuntu-latest
90
90
  strategy:
91
91
  matrix:
92
- php: [ '5.6', '7.1', '7.2', '7.3' ]
92
+ php: [ '7.3', '7.4' ]
93
93
  steps:
94
94
  - uses: actions/checkout@v2
95
95
  - name: Setup php
96
- uses: nanasess/setup-php@v3.0.4
96
+ uses: nanasess/setup-php@v3.0.6
97
97
  with:
98
98
  php-version: ${{ matrix.php }}
99
99
  - name: Set up Ruby
100
- uses: actions/setup-ruby@v1
100
+ uses: ruby/setup-ruby@v1
101
101
  with:
102
- ruby-version: 2.6.x
102
+ ruby-version: 2.6
103
103
  - run: bundle lock
104
104
  - uses: actions/cache@v1
105
105
  with:
@@ -116,11 +116,11 @@ jobs:
116
116
  runs-on: ubuntu-latest
117
117
  strategy:
118
118
  matrix:
119
- ruby: [ 2.4.x, 2.5.x, 2.6.x, 2.7.x ]
119
+ ruby: [ 2.5, 2.6, 2.7 ]
120
120
  steps:
121
121
  - uses: actions/checkout@v2
122
122
  - name: Set up Ruby
123
- uses: actions/setup-ruby@v1
123
+ uses: ruby/setup-ruby@v1
124
124
  with:
125
125
  ruby-version: ${{matrix.ruby}}
126
126
  - name: Set up Bundler
@@ -146,9 +146,9 @@ jobs:
146
146
  with:
147
147
  go-version: 1.10.x
148
148
  - name: Set up Ruby
149
- uses: actions/setup-ruby@v1
149
+ uses: ruby/setup-ruby@v1
150
150
  with:
151
- ruby-version: 2.6.x
151
+ ruby-version: 2.6
152
152
  - run: bundle lock
153
153
  - uses: actions/cache@v1
154
154
  with:
@@ -173,9 +173,9 @@ jobs:
173
173
  with:
174
174
  go-version: ${{ matrix.go }}
175
175
  - name: Set up Ruby
176
- uses: actions/setup-ruby@v1
176
+ uses: ruby/setup-ruby@v1
177
177
  with:
178
- ruby-version: 2.6.x
178
+ ruby-version: 2.6
179
179
  - run: bundle lock
180
180
  - uses: actions/cache@v1
181
181
  with:
@@ -193,9 +193,9 @@ jobs:
193
193
  steps:
194
194
  - uses: actions/checkout@v2
195
195
  - name: Set up Ruby
196
- uses: actions/setup-ruby@v1
196
+ uses: ruby/setup-ruby@v1
197
197
  with:
198
- ruby-version: 2.6.x
198
+ ruby-version: 2.6
199
199
  - run: bundle lock
200
200
  - uses: actions/cache@v1
201
201
  with:
@@ -213,9 +213,9 @@ jobs:
213
213
  steps:
214
214
  - uses: actions/checkout@v2
215
215
  - name: Set up Ruby
216
- uses: actions/setup-ruby@v1
216
+ uses: ruby/setup-ruby@v1
217
217
  with:
218
- ruby-version: 2.6.x
218
+ ruby-version: 2.6
219
219
  - run: bundle lock
220
220
  - uses: actions/cache@v1
221
221
  with:
@@ -230,18 +230,18 @@ jobs:
230
230
  runs-on: ubuntu-latest
231
231
  strategy:
232
232
  matrix:
233
- otp: [21.x, 22.x]
234
- elixir: [1.8.x, 1.9.x]
233
+ otp: [21.x, 22.x, 23.x]
234
+ elixir: [ 1.10.x, 1.11.x ]
235
235
  steps:
236
236
  - uses: actions/checkout@v2
237
- - uses: actions/setup-elixir@v1.0.0
237
+ - uses: erlef/setup-elixir@v1.6.0
238
238
  with:
239
239
  otp-version: ${{matrix.otp}}
240
240
  elixir-version: ${{matrix.elixir}}
241
241
  - name: Set up Ruby
242
- uses: actions/setup-ruby@v1
242
+ uses: ruby/setup-ruby@v1
243
243
  with:
244
- ruby-version: 2.6.x
244
+ ruby-version: 2.6
245
245
  - run: bundle lock
246
246
  - uses: actions/cache@v1
247
247
  with:
@@ -258,17 +258,17 @@ jobs:
258
258
  runs-on: ubuntu-latest
259
259
  strategy:
260
260
  matrix:
261
- node_version: [ 8, 10, 12 ]
261
+ node_version: [ 10, 12, 14, 15 ]
262
262
  steps:
263
263
  - uses: actions/checkout@v2
264
264
  - name: Setup node
265
- uses: actions/setup-node@v1
265
+ uses: actions/setup-node@v2
266
266
  with:
267
267
  node-version: ${{ matrix.node_version }}
268
268
  - name: Set up Ruby
269
- uses: actions/setup-ruby@v1
269
+ uses: ruby/setup-ruby@v1
270
270
  with:
271
- ruby-version: 2.6.x
271
+ ruby-version: 2.6
272
272
  - run: bundle lock
273
273
  - uses: actions/cache@v1
274
274
  with:
@@ -290,9 +290,9 @@ jobs:
290
290
  with:
291
291
  dotnet-version: 3.1.202
292
292
  - name: Set up Ruby
293
- uses: actions/setup-ruby@v1
293
+ uses: ruby/setup-ruby@v1
294
294
  with:
295
- ruby-version: 2.6.x
295
+ ruby-version: 2.6
296
296
  - run: bundle lock
297
297
  - uses: actions/cache@v1
298
298
  with:
@@ -318,9 +318,9 @@ jobs:
318
318
  python-version: ${{ matrix.python }}
319
319
  architecture: x64
320
320
  - name: Set up Ruby
321
- uses: actions/setup-ruby@v1
321
+ uses: ruby/setup-ruby@v1
322
322
  with:
323
- ruby-version: 2.6.x
323
+ ruby-version: 2.6
324
324
  - run: bundle lock
325
325
  - uses: actions/cache@v1
326
326
  with:
@@ -345,9 +345,9 @@ jobs:
345
345
  python-version: '3.x'
346
346
  architecture: x64
347
347
  - name: Set up Ruby
348
- uses: actions/setup-ruby@v1
348
+ uses: ruby/setup-ruby@v1
349
349
  with:
350
- ruby-version: 2.6.x
350
+ ruby-version: 2.6
351
351
  - run: bundle lock
352
352
  - uses: actions/cache@v1
353
353
  with:
@@ -371,7 +371,7 @@ jobs:
371
371
  steps:
372
372
  - uses: actions/checkout@v2
373
373
  - name: Setup node
374
- uses: actions/setup-node@v1
374
+ uses: actions/setup-node@v2
375
375
  with:
376
376
  node-version: 12
377
377
  - name: Install Yarn
@@ -379,9 +379,9 @@ jobs:
379
379
  env:
380
380
  YARN_VERSION: ${{ matrix.yarn_version }}
381
381
  - name: Set up Ruby
382
- uses: actions/setup-ruby@v1
382
+ uses: ruby/setup-ruby@v1
383
383
  with:
384
- ruby-version: 2.6.x
384
+ ruby-version: 2.6
385
385
  - run: bundle lock
386
386
  - uses: actions/cache@v1
387
387
  with:
data/.gitignore CHANGED
@@ -17,6 +17,7 @@ test/fixtures/bower/bower_components
17
17
 
18
18
  test/fixtures/npm/node_modules
19
19
  test/fixtures/npm/package-lock.json
20
+ test/fixtures/npm/package.json
20
21
 
21
22
  test/fixtures/go/src/*
22
23
  test/fixtures/go/pkg
data/CHANGELOG.md CHANGED
@@ -6,10 +6,45 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 2.15.0
10
+ 2021-03-24
11
+
12
+ ### Added
13
+ - Support for npm 7 (https://github.com/github/licensed/pull/341)
14
+
15
+ ### Fixed
16
+ - Files in the manifest source will be found correctly for apps that are not at the repository root (https://github.com/github/licensed/pull/345)
17
+
18
+ ## 2.14.4
19
+ 2021-02-09
20
+
21
+ ### Added
22
+ - `list` and `cache` commands optionally print output in JSON or YML formats using the `--format/-f` flag (https://github.com/github/licensed/pull/334)
23
+ - `list` command will include detected license keys using the `--licenses/-l` flag (https://github.com/github/licensed/pull/334)
24
+
25
+ ## 2.14.3
26
+ 2020-12-11
27
+
28
+ ### Fixed
29
+ - 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)
30
+
31
+ ## 2.14.2
32
+ 2020-11-20
33
+
34
+ ### Fixed
35
+ - Yarn source correctly finds dependency paths on disk (https://github.com/github/licensed/pull/326)
36
+ - Go source better handles finding dependencies that have been vendored (https://github.com/github/licensed/pull/323)
37
+
38
+ ## 2.14.1
39
+ 2020-10-09
40
+
41
+ ### Fixed
42
+ - Shell command output is encoded to UTF8 (https://github.com/github/licensed/pull/319)
43
+
9
44
  ## 2.14.0
10
45
  2020-10-04
11
46
 
12
- ### Addded
47
+ ### Added
13
48
  - `reviewed` dependencies can use glob pattern matching (https://github.com/github/licensed/pull/313)
14
49
 
15
50
  ### Fixed
@@ -360,4 +395,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
360
395
 
361
396
  Initial release :tada:
362
397
 
363
- [Unreleased]: https://github.com/github/licensed/compare/2.14.0...HEAD
398
+ [Unreleased]: https://github.com/github/licensed/compare/2.15.0...HEAD
data/README.md CHANGED
@@ -110,7 +110,7 @@ Dependencies will be automatically detected for all of the following sources by
110
110
  1. [Gradle](./docs/sources/gradle.md)
111
111
  1. [Manifest lists (manifests)](./docs/sources/manifests.md)
112
112
  1. [Mix](./docs/sources/mix.md)
113
- 1. [NPM](./docs/sources/npm.md)
113
+ 1. [npm](./docs/sources/npm.md)
114
114
  1. [NuGet](./docs/sources/nuget.md)
115
115
  1. [Pip](./docs/sources/pip.md)
116
116
  1. [Pipenv](./docs/sources/pipenv.md)
@@ -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"
data/docs/sources/npm.md CHANGED
@@ -1,4 +1,4 @@
1
- # NPM
1
+ # npm
2
2
 
3
3
  The npm source will detect dependencies `package.json` is found at an apps `source_path`. It uses `npm list` to enumerate dependencies and metadata.
4
4
 
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"
@@ -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
@@ -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
@@ -222,14 +222,25 @@ module Licensed
222
222
 
223
223
  # Returns a package info structure with an error set
224
224
  def missing_package(id)
225
- name, _, version = if id.index(/\s/).nil?
226
- id.rpartition("-") # e.g. to match the right-most dash from ipid fused-effects-1.0.0.0
227
- else
228
- id.partition(/\s/) # e.g. to match the left-most space from constraint fused-effects > 1.0.0.0
229
- end
230
-
225
+ name, version = package_id_name_version(id)
231
226
  { "name" => name, "version" => version, "error" => "package not found" }
232
227
  end
228
+
229
+ # Parses the name and version pieces from an id or package requirement string
230
+ def package_id_name_version(id)
231
+ name, version = id.split(" ", 2)
232
+ return [name, version] if version
233
+
234
+ # split by dashes, find the rightmost thing that looks like an
235
+ parts = id.split("-")
236
+ version_start_index = parts.rindex { |part| part.match?(/^[\d\.]+$/) }
237
+ return [id, nil] if version_start_index.nil?
238
+
239
+ [
240
+ parts[0...version_start_index].join("-"),
241
+ parts[version_start_index..-1].join("-")
242
+ ]
243
+ end
233
244
  end
234
245
  end
235
246
  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
@@ -170,7 +170,7 @@ module Licensed
170
170
  def all_files
171
171
  # remove files if they are tracked but don't exist on the file system
172
172
  @all_files ||= Set.new(Licensed::Git.files || [])
173
- .delete_if { |f| !File.exist?(f) }
173
+ .delete_if { |f| !File.exist?(File.join(Licensed::Git.repository_root, f)) }
174
174
  end
175
175
 
176
176
  class Dependency < Licensed::Dependency
@@ -4,6 +4,25 @@ require "json"
4
4
  module Licensed
5
5
  module Sources
6
6
  class NPM < Source
7
+ class Dependency < ::Licensed::Dependency
8
+ # override license_metadata to pull homepage and summary information
9
+ # from a packages package.json file, if it exists
10
+ # this accounts for the lack of this information in npm 7's `npm list` output
11
+ def license_metadata
12
+ data = super
13
+ return data if !data["homepage"].to_s.empty? && !data["summary"].to_s.empty?
14
+
15
+ package_json_path = File.join(path, "package.json")
16
+ return data unless File.exist?(package_json_path)
17
+
18
+ package_json = JSON.parse(File.read(package_json_path))
19
+ data["homepage"] = package_json["homepage"]
20
+ data["summary"] = package_json["description"]
21
+
22
+ data
23
+ end
24
+ end
25
+
7
26
  def self.type
8
27
  "npm"
9
28
  end
@@ -50,6 +69,7 @@ module Licensed
50
69
  dependencies.each do |name, dependency|
51
70
  next if dependency["peerMissing"]
52
71
  next if yarn_lock_present && dependency["missing"]
72
+ dependency["name"] = name
53
73
  (result[name] ||= []) << dependency
54
74
  recursive_dependencies(dependency["dependencies"] || {}, result)
55
75
  end
@@ -59,22 +79,50 @@ module Licensed
59
79
  # Returns parsed package metadata returned from `npm list`
60
80
  def package_metadata
61
81
  return @package_metadata if defined?(@package_metadata)
82
+ @package_metadata = JSON.parse(package_metadata_command)
83
+ rescue JSON::ParserError => e
84
+ message = "Licensed was unable to parse the output from 'npm list'. JSON Error: #{e.message}"
85
+ npm_error = package_metadata_error
86
+ message = "#{message}. npm Error: #{npm_error}" if npm_error
87
+ raise Licensed::Sources::Source::Error, message
88
+ end
62
89
 
63
- @package_metadata = begin
64
- JSON.parse(package_metadata_command)
65
- rescue JSON::ParserError => e
66
- raise Licensed::Sources::Source::Error,
67
- "Licensed was unable to parse the output from 'npm list'. Please run 'npm list --json --long' and check for errors. Error: #{e.message}"
68
- end
90
+ # Returns an error, if one exists, from running `npm list` to get package metadata
91
+ def package_metadata_error
92
+ Licensed::Shell.execute("npm", "list", *package_metadata_args)
93
+ return ""
94
+ rescue Licensed::Shell::Error => e
95
+ return e.message
69
96
  end
70
97
 
71
98
  # Returns the output from running `npm list` to get package metadata
72
99
  def package_metadata_command
73
100
  args = %w(--json --long)
74
- args << "--production" unless include_non_production?
101
+ args.concat(package_metadata_args)
102
+
75
103
  Licensed::Shell.execute("npm", "list", *args, allow_failure: true)
76
104
  end
77
105
 
106
+ # Returns an array of arguments that should be used for all `npm list`
107
+ # calls, regardless of how the output is formatted
108
+ def package_metadata_args
109
+ args = []
110
+ args << "--production" unless include_non_production?
111
+
112
+ # on npm 7+, the --all argument is necessary to evaluate the project's
113
+ # full dependency tree
114
+ args << "--all" if npm_version >= Gem::Version.new("7.0.0")
115
+
116
+ return args
117
+ end
118
+
119
+ # Returns the currently installed version of npm as a Gem::Version object
120
+ def npm_version
121
+ @npm_version ||= begin
122
+ Gem::Version.new(Licensed::Shell.execute("npm", "-v").strip)
123
+ end
124
+ end
125
+
78
126
  # Returns true if a yarn.lock file exists in the current directory
79
127
  def yarn_lock_present
80
128
  @yarn_lock_present ||= File.exist?(config.pwd.join("yarn.lock"))
@@ -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.14.0".freeze
3
+ VERSION = "2.15.0".freeze
4
4
 
5
5
  def self.previous_major_versions
6
6
  major_version = Gem::Version.new(Licensed::VERSION).segments.first
@@ -51,8 +51,11 @@ cd $COPY_DIR
51
51
  trap "git checkout $CURRENT_BRANCH" EXIT
52
52
  fi
53
53
 
54
+ # get the openssl dir to use when building based on ruby's default ssl cert dir
55
+ OPENSSL_DIR="$(cd "$(ruby -e 'require "net/https"; puts OpenSSL::X509::DEFAULT_CERT_DIR')/.." && pwd)"
56
+
54
57
  # build the licensed rubyc executable
55
- "$RUBYC" --clean-tmpdir -o "$BUILD_DIR/licensed" "$COPY_DIR/exe/licensed"
58
+ "$RUBYC" --openssl-dir "$OPENSSL_DIR" --clean-tmpdir -o "$BUILD_DIR/licensed" "$COPY_DIR/exe/licensed"
56
59
  chmod +x $BUILD_DIR/licensed
57
60
  )
58
61
 
@@ -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
  }
data/script/packages/mac CHANGED
@@ -28,6 +28,9 @@ brew update
28
28
  brew list "squashfs" &>/dev/null || brew install "squashfs"
29
29
  brew list "pkg-config" &>/dev/null || brew install "pkg-config"
30
30
 
31
+ gem update --system
32
+ gem update bundler
33
+
31
34
  if [ ! -f "$RUBYC" ]; then
32
35
  mkdir -p "$(dirname "$RUBYC")"
33
36
  curl -L https://github.com/kontena/ruby-packer/releases/download/2.6.0-0.6.0/rubyc-2.6.0-0.6.0-osx-amd64.gz | gunzip > "$RUBYC"
@@ -10,8 +10,25 @@ fi
10
10
  BASE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
11
11
  cd $BASE_PATH/test/fixtures/npm
12
12
 
13
+ FORCE=""
13
14
  if [ "$1" == "-f" ]; then
14
- find . -not -regex "\.*" -and -not -name "package\.json" -print0 | xargs -0 rm -rf
15
+ FORCE=1
16
+ fi
17
+
18
+ NPM_MAJOR_VERSION="$(npm -v | cut -d'.' -f1)"
19
+ if [ "$NPM_MAJOR_VERSION" -ge "7" ]; then
20
+ PACKAGE_JSON_SRC="package.json.npm7"
21
+ else
22
+ PACKAGE_JSON_SRC="package.json.npm6"
23
+ fi
24
+
25
+ if [ ! -f "package.json" ] || [ "$(cat package.json | md5sum )" != "$(cat "$PACKAGE_JSON_SRC" | md5sum)" ]; then
26
+ FORCE=1
27
+ cp -f "$PACKAGE_JSON_SRC" package.json
28
+ fi
29
+
30
+ if [ -n "$FORCE" ]; then
31
+ find . -not -regex "\.*" -and -not -name "package\.json*" -print0 | xargs -0 rm -rf
15
32
  fi
16
33
 
17
34
  npm install
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.14.0
4
+ version: 2.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-04 00:00:00.000000000 Z
11
+ date: 2021-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: licensee