licensed 2.14.1 → 2.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +125 -29
- data/.github/workflows/test.yml +42 -42
- data/.gitignore +1 -0
- data/CHANGELOG.md +38 -1
- data/README.md +1 -1
- data/docker/Dockerfile.build-linux +1 -0
- data/docs/sources/npm.md +1 -1
- data/lib/licensed/cli.rb +8 -2
- data/lib/licensed/commands/list.rb +7 -0
- data/lib/licensed/dependency.rb +1 -0
- data/lib/licensed/reporters/list_reporter.rb +3 -1
- data/lib/licensed/sources/cabal.rb +17 -6
- data/lib/licensed/sources/go.rb +43 -43
- data/lib/licensed/sources/manifest.rb +1 -1
- data/lib/licensed/sources/npm.rb +57 -7
- data/lib/licensed/sources/yarn.rb +14 -6
- data/lib/licensed/version.rb +1 -1
- data/script/packages/build +4 -1
- data/script/packages/linux +4 -0
- data/script/packages/mac +3 -0
- data/script/source-setup/npm +18 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdbf2bbf20f191470109be01b9ae1e284d99d1f078005c13e4a188c3f202926e
|
4
|
+
data.tar.gz: c32a7d0bc2488bd1f1217e3552268b96dc09c442195facf30378d0451f328145
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84aec8c6f41dd9549d6e18239344b5927abdea80de9238aa493bf3af9e4b89714e321a684534aab1fe14b1e0636aad49b00356486a4eccfd05dcff2fd51a99ec
|
7
|
+
data.tar.gz: 23f7f2b0f681e3f53ea56ae2b2e56306ca4beb377819e8ac5318f762147835c2c7eb6b24f844c03ebdb7598f4ba536da53b3c7707a01e898baf1d76b396c4dcb
|
@@ -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
|
-
|
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:
|
96
|
+
uses: ruby/setup-ruby@v1
|
14
97
|
with:
|
15
|
-
ruby-version: 2.6
|
98
|
+
ruby-version: 2.6
|
16
99
|
|
17
100
|
- name: Build package
|
18
101
|
run: script/packages/linux
|
19
102
|
env:
|
20
|
-
VERSION: ${{
|
103
|
+
VERSION: ${{needs.vars.outputs.version}}
|
21
104
|
|
22
105
|
- uses: actions/upload-artifact@v2
|
23
106
|
with:
|
24
|
-
name: ${{
|
25
|
-
path: pkg/${{
|
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:
|
122
|
+
uses: ruby/setup-ruby@v1
|
33
123
|
with:
|
34
|
-
ruby-version: 2.6
|
124
|
+
ruby-version: 2.6
|
35
125
|
|
36
126
|
- name: Build package
|
37
127
|
run: script/packages/mac
|
38
128
|
env:
|
39
|
-
VERSION: ${{
|
129
|
+
VERSION: ${{needs.vars.outputs.version}}
|
40
130
|
|
41
131
|
- uses: actions/upload-artifact@v2
|
42
132
|
with:
|
43
|
-
name: ${{
|
44
|
-
path: pkg/${{
|
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:
|
146
|
+
uses: ruby/setup-ruby@v1
|
52
147
|
with:
|
53
|
-
ruby-version: 2.6
|
148
|
+
ruby-version: 2.6
|
54
149
|
|
55
150
|
- name: Build gem
|
56
|
-
run: gem build licensed.gemspec -o licensed-${{
|
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: ${{
|
61
|
-
path: licensed-${{
|
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:
|
165
|
+
uses: ruby/setup-ruby@v1
|
70
166
|
with:
|
71
|
-
ruby-version: 2.6
|
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: ${{
|
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: ${{
|
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: ${{
|
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: ${{
|
94
|
-
asset_path: ./licensed-${{
|
95
|
-
asset_name: licensed-${{
|
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: ${{
|
104
|
-
asset_path: ./licensed-${{
|
105
|
-
asset_name: licensed-${{
|
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-${{
|
213
|
+
GEM: licensed-${{needs.vars.outputs.version}}.gem
|
data/.github/workflows/test.yml
CHANGED
@@ -8,15 +8,15 @@ jobs:
|
|
8
8
|
steps:
|
9
9
|
- uses: actions/checkout@v2
|
10
10
|
- name: Setup node
|
11
|
-
uses: actions/setup-node@
|
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:
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
18
|
with:
|
19
|
-
ruby-version: 2.6
|
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:
|
40
|
+
uses: ruby/setup-ruby@v1
|
41
41
|
with:
|
42
|
-
ruby-version: 2.6
|
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
|
64
|
-
cabal: [ '2.
|
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:
|
68
|
+
uses: ruby/setup-ruby@v1
|
69
69
|
with:
|
70
|
-
ruby-version: 2.6
|
70
|
+
ruby-version: 2.6
|
71
71
|
- name: Setup Haskell
|
72
|
-
uses: actions/setup
|
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: [ '
|
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.
|
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:
|
100
|
+
uses: ruby/setup-ruby@v1
|
101
101
|
with:
|
102
|
-
ruby-version: 2.6
|
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.
|
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:
|
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:
|
149
|
+
uses: ruby/setup-ruby@v1
|
150
150
|
with:
|
151
|
-
ruby-version: 2.6
|
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:
|
176
|
+
uses: ruby/setup-ruby@v1
|
177
177
|
with:
|
178
|
-
ruby-version: 2.6
|
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:
|
196
|
+
uses: ruby/setup-ruby@v1
|
197
197
|
with:
|
198
|
-
ruby-version: 2.6
|
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:
|
216
|
+
uses: ruby/setup-ruby@v1
|
217
217
|
with:
|
218
|
-
ruby-version: 2.6
|
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.
|
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:
|
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:
|
242
|
+
uses: ruby/setup-ruby@v1
|
243
243
|
with:
|
244
|
-
ruby-version: 2.6
|
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: [
|
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@
|
265
|
+
uses: actions/setup-node@v2
|
266
266
|
with:
|
267
267
|
node-version: ${{ matrix.node_version }}
|
268
268
|
- name: Set up Ruby
|
269
|
-
uses:
|
269
|
+
uses: ruby/setup-ruby@v1
|
270
270
|
with:
|
271
|
-
ruby-version: 2.6
|
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:
|
293
|
+
uses: ruby/setup-ruby@v1
|
294
294
|
with:
|
295
|
-
ruby-version: 2.6
|
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:
|
321
|
+
uses: ruby/setup-ruby@v1
|
322
322
|
with:
|
323
|
-
ruby-version: 2.6
|
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:
|
348
|
+
uses: ruby/setup-ruby@v1
|
349
349
|
with:
|
350
|
-
ruby-version: 2.6
|
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@
|
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:
|
382
|
+
uses: ruby/setup-ruby@v1
|
383
383
|
with:
|
384
|
-
ruby-version: 2.6
|
384
|
+
ruby-version: 2.6
|
385
385
|
- run: bundle lock
|
386
386
|
- uses: actions/cache@v1
|
387
387
|
with:
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,43 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## 2.15.1
|
10
|
+
|
11
|
+
2021-03-29
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
|
15
|
+
- The npm source will ignore dependencies that are marked as both extraneous and missing (https://github.com/github/licensed/pull/347)
|
16
|
+
|
17
|
+
## 2.15.0
|
18
|
+
2021-03-24
|
19
|
+
|
20
|
+
### Added
|
21
|
+
- Support for npm 7 (https://github.com/github/licensed/pull/341)
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
- 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)
|
25
|
+
|
26
|
+
## 2.14.4
|
27
|
+
2021-02-09
|
28
|
+
|
29
|
+
### Added
|
30
|
+
- `list` and `cache` commands optionally print output in JSON or YML formats using the `--format/-f` flag (https://github.com/github/licensed/pull/334)
|
31
|
+
- `list` command will include detected license keys using the `--licenses/-l` flag (https://github.com/github/licensed/pull/334)
|
32
|
+
|
33
|
+
## 2.14.3
|
34
|
+
2020-12-11
|
35
|
+
|
36
|
+
### Fixed
|
37
|
+
- 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)
|
38
|
+
|
39
|
+
## 2.14.2
|
40
|
+
2020-11-20
|
41
|
+
|
42
|
+
### Fixed
|
43
|
+
- Yarn source correctly finds dependency paths on disk (https://github.com/github/licensed/pull/326)
|
44
|
+
- Go source better handles finding dependencies that have been vendored (https://github.com/github/licensed/pull/323)
|
45
|
+
|
9
46
|
## 2.14.1
|
10
47
|
2020-10-09
|
11
48
|
|
@@ -366,4 +403,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
366
403
|
|
367
404
|
Initial release :tada:
|
368
405
|
|
369
|
-
[Unreleased]: https://github.com/github/licensed/compare/2.
|
406
|
+
[Unreleased]: https://github.com/github/licensed/compare/2.15.1...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. [
|
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)
|
data/docs/sources/npm.md
CHANGED
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
|
data/lib/licensed/dependency.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -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,
|
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
|
data/lib/licensed/sources/go.rb
CHANGED
@@ -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 =
|
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
|
83
|
+
import_path = non_vendored_import_path(package)
|
85
84
|
return false unless import_path
|
86
85
|
|
87
|
-
#
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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["
|
110
|
-
|
111
|
-
|
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
|
-
|
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
|
-
#
|
171
|
-
#
|
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
|
-
#
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
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
|
-
#
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
return
|
187
|
-
|
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
|
data/lib/licensed/sources/npm.rb
CHANGED
@@ -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,9 @@ 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
|
+
next if dependency["extraneous"] && dependency["missing"]
|
73
|
+
|
74
|
+
dependency["name"] = name
|
53
75
|
(result[name] ||= []) << dependency
|
54
76
|
recursive_dependencies(dependency["dependencies"] || {}, result)
|
55
77
|
end
|
@@ -59,22 +81,50 @@ module Licensed
|
|
59
81
|
# Returns parsed package metadata returned from `npm list`
|
60
82
|
def package_metadata
|
61
83
|
return @package_metadata if defined?(@package_metadata)
|
84
|
+
@package_metadata = JSON.parse(package_metadata_command)
|
85
|
+
rescue JSON::ParserError => e
|
86
|
+
message = "Licensed was unable to parse the output from 'npm list'. JSON Error: #{e.message}"
|
87
|
+
npm_error = package_metadata_error
|
88
|
+
message = "#{message}. npm Error: #{npm_error}" if npm_error
|
89
|
+
raise Licensed::Sources::Source::Error, message
|
90
|
+
end
|
62
91
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
92
|
+
# Returns an error, if one exists, from running `npm list` to get package metadata
|
93
|
+
def package_metadata_error
|
94
|
+
Licensed::Shell.execute("npm", "list", *package_metadata_args)
|
95
|
+
return ""
|
96
|
+
rescue Licensed::Shell::Error => e
|
97
|
+
return e.message
|
69
98
|
end
|
70
99
|
|
71
100
|
# Returns the output from running `npm list` to get package metadata
|
72
101
|
def package_metadata_command
|
73
102
|
args = %w(--json --long)
|
74
|
-
args
|
103
|
+
args.concat(package_metadata_args)
|
104
|
+
|
75
105
|
Licensed::Shell.execute("npm", "list", *args, allow_failure: true)
|
76
106
|
end
|
77
107
|
|
108
|
+
# Returns an array of arguments that should be used for all `npm list`
|
109
|
+
# calls, regardless of how the output is formatted
|
110
|
+
def package_metadata_args
|
111
|
+
args = []
|
112
|
+
args << "--production" unless include_non_production?
|
113
|
+
|
114
|
+
# on npm 7+, the --all argument is necessary to evaluate the project's
|
115
|
+
# full dependency tree
|
116
|
+
args << "--all" if npm_version >= Gem::Version.new("7.0.0")
|
117
|
+
|
118
|
+
return args
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the currently installed version of npm as a Gem::Version object
|
122
|
+
def npm_version
|
123
|
+
@npm_version ||= begin
|
124
|
+
Gem::Version.new(Licensed::Shell.execute("npm", "-v").strip)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
78
128
|
# Returns true if a yarn.lock file exists in the current directory
|
79
129
|
def yarn_lock_present
|
80
130
|
@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(
|
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(
|
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" =>
|
69
|
+
"path" => dependency_paths[dependency["name"]]
|
72
70
|
}
|
73
|
-
recursive_dependencies(
|
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)
|
data/lib/licensed/version.rb
CHANGED
data/script/packages/build
CHANGED
@@ -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
|
|
data/script/packages/linux
CHANGED
@@ -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"
|
data/script/source-setup/npm
CHANGED
@@ -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
|
-
|
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.
|
4
|
+
version: 2.15.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: licensee
|