Skip to content

Commit 6b1d198

Browse files
feat: Warn when an updated dependency loses an attestation (renovatebot#37268)
1 parent 0b7c4d5 commit 6b1d198

File tree

8 files changed

+233
-7
lines changed

8 files changed

+233
-7
lines changed

lib/modules/datasource/npm/__snapshots__/index.spec.ts.snap

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ exports[`modules/datasource/npm/index > should fetch package info from custom re
66
"registryUrl": "https://npm.mycustomregistry.com",
77
"releases": [
88
{
9+
"attestation": false,
910
"dependencies": undefined,
1011
"devDependencies": undefined,
1112
"gitRef": undefined,
1213
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
1314
"version": "0.0.1",
1415
},
1516
{
17+
"attestation": false,
1618
"dependencies": undefined,
1719
"devDependencies": undefined,
1820
"gitRef": undefined,
@@ -33,13 +35,15 @@ exports[`modules/datasource/npm/index > should fetch package info from npm 1`] =
3335
"registryUrl": "https://registry.npmjs.org",
3436
"releases": [
3537
{
38+
"attestation": false,
3639
"dependencies": undefined,
3740
"devDependencies": undefined,
3841
"gitRef": undefined,
3942
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
4043
"version": "0.0.1",
4144
},
4245
{
46+
"attestation": false,
4347
"dependencies": undefined,
4448
"devDependencies": undefined,
4549
"gitRef": undefined,
@@ -61,13 +65,15 @@ exports[`modules/datasource/npm/index > should handle foobar 1`] = `
6165
"registryUrl": "https://registry.npmjs.org",
6266
"releases": [
6367
{
68+
"attestation": false,
6469
"dependencies": undefined,
6570
"devDependencies": undefined,
6671
"gitRef": undefined,
6772
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
6873
"version": "0.0.1",
6974
},
7075
{
76+
"attestation": false,
7177
"dependencies": undefined,
7278
"devDependencies": undefined,
7379
"gitRef": undefined,
@@ -89,13 +95,15 @@ exports[`modules/datasource/npm/index > should handle no time 1`] = `
8995
"registryUrl": "https://registry.npmjs.org",
9096
"releases": [
9197
{
98+
"attestation": false,
9299
"dependencies": undefined,
93100
"devDependencies": undefined,
94101
"gitRef": undefined,
95102
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
96103
"version": "0.0.1",
97104
},
98105
{
106+
"attestation": false,
99107
"dependencies": undefined,
100108
"devDependencies": undefined,
101109
"gitRef": undefined,
@@ -116,13 +124,15 @@ exports[`modules/datasource/npm/index > should not send an authorization header
116124
"registryUrl": "https://registry.npmjs.org",
117125
"releases": [
118126
{
127+
"attestation": false,
119128
"dependencies": undefined,
120129
"devDependencies": undefined,
121130
"gitRef": undefined,
122131
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
123132
"version": "0.0.1",
124133
},
125134
{
135+
"attestation": false,
126136
"dependencies": undefined,
127137
"devDependencies": undefined,
128138
"gitRef": undefined,
@@ -144,6 +154,7 @@ exports[`modules/datasource/npm/index > should parse repo url (string) 1`] = `
144154
"registryUrl": "https://registry.npmjs.org",
145155
"releases": [
146156
{
157+
"attestation": false,
147158
"dependencies": undefined,
148159
"devDependencies": undefined,
149160
"gitRef": undefined,
@@ -164,6 +175,7 @@ exports[`modules/datasource/npm/index > should parse repo url 1`] = `
164175
"registryUrl": "https://registry.npmjs.org",
165176
"releases": [
166177
{
178+
"attestation": false,
167179
"dependencies": undefined,
168180
"devDependencies": undefined,
169181
"gitRef": undefined,
@@ -184,13 +196,15 @@ exports[`modules/datasource/npm/index > should replace any environment variable
184196
"registryUrl": "https://registry.from-env.com",
185197
"releases": [
186198
{
199+
"attestation": false,
187200
"dependencies": undefined,
188201
"devDependencies": undefined,
189202
"gitRef": undefined,
190203
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
191204
"version": "0.0.1",
192205
},
193206
{
207+
"attestation": false,
194208
"dependencies": undefined,
195209
"devDependencies": undefined,
196210
"gitRef": undefined,
@@ -217,6 +231,7 @@ Marking the latest version of an npm package as deprecated results in the entire
217231
"registryUrl": "https://registry.npmjs.org",
218232
"releases": [
219233
{
234+
"attestation": false,
220235
"dependencies": undefined,
221236
"devDependencies": undefined,
222237
"gitRef": undefined,
@@ -225,6 +240,7 @@ Marking the latest version of an npm package as deprecated results in the entire
225240
"version": "0.0.1",
226241
},
227242
{
243+
"attestation": false,
228244
"dependencies": undefined,
229245
"devDependencies": undefined,
230246
"gitRef": undefined,
@@ -254,13 +270,15 @@ exports[`modules/datasource/npm/index > should send an authorization header if p
254270
"registryUrl": "https://registry.npmjs.org",
255271
"releases": [
256272
{
273+
"attestation": false,
257274
"dependencies": undefined,
258275
"devDependencies": undefined,
259276
"gitRef": undefined,
260277
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
261278
"version": "0.0.1",
262279
},
263280
{
281+
"attestation": false,
264282
"dependencies": undefined,
265283
"devDependencies": undefined,
266284
"gitRef": undefined,
@@ -282,13 +300,15 @@ exports[`modules/datasource/npm/index > should use default registry if missing f
282300
"registryUrl": "https://registry.npmjs.org",
283301
"releases": [
284302
{
303+
"attestation": false,
285304
"dependencies": undefined,
286305
"devDependencies": undefined,
287306
"gitRef": undefined,
288307
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
289308
"version": "0.0.1",
290309
},
291310
{
311+
"attestation": false,
292312
"dependencies": undefined,
293313
"devDependencies": undefined,
294314
"gitRef": undefined,
@@ -310,13 +330,15 @@ exports[`modules/datasource/npm/index > should use host rules by baseUrl if prov
310330
"registryUrl": "https://npm.mycustomregistry.com/_packaging/mycustomregistry/npm/registry",
311331
"releases": [
312332
{
333+
"attestation": false,
313334
"dependencies": undefined,
314335
"devDependencies": undefined,
315336
"gitRef": undefined,
316337
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
317338
"version": "0.0.1",
318339
},
319340
{
341+
"attestation": false,
320342
"dependencies": undefined,
321343
"devDependencies": undefined,
322344
"gitRef": undefined,
@@ -338,13 +360,15 @@ exports[`modules/datasource/npm/index > should use host rules by hostName if pro
338360
"registryUrl": "https://npm.mycustomregistry.com",
339361
"releases": [
340362
{
363+
"attestation": false,
341364
"dependencies": undefined,
342365
"devDependencies": undefined,
343366
"gitRef": undefined,
344367
"releaseTimestamp": "2018-05-06T05:21:53.000Z",
345368
"version": "0.0.1",
346369
},
347370
{
371+
"attestation": false,
348372
"dependencies": undefined,
349373
"devDependencies": undefined,
350374
"gitRef": undefined,

lib/modules/datasource/npm/get.spec.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,15 @@ describe('modules/datasource/npm/get', () => {
596596

597597
expect(dep).toEqual({
598598
registryUrl: 'https://example.com',
599-
releases: [{ version: '1.0.0' }],
599+
releases: [
600+
{
601+
attestation: false,
602+
dependencies: undefined,
603+
devDependencies: undefined,
604+
gitRef: undefined,
605+
version: '1.0.0',
606+
},
607+
],
600608
sourceDirectory: 'packages/foo',
601609
sourceUrl:
602610
'https://github.com/octocat/Hello-World/tree/master/packages/test',
@@ -622,7 +630,15 @@ describe('modules/datasource/npm/get', () => {
622630

623631
expect(dep).toEqual({
624632
registryUrl: 'https://example.com',
625-
releases: [{ version: '1.0.0' }],
633+
releases: [
634+
{
635+
attestation: false,
636+
dependencies: undefined,
637+
devDependencies: undefined,
638+
gitRef: undefined,
639+
version: '1.0.0',
640+
},
641+
],
626642
sourceDirectory: 'packages/foo',
627643
sourceUrl:
628644
'https://github.com/octocat/Hello-World/tree/master/packages/test',
@@ -648,7 +664,15 @@ describe('modules/datasource/npm/get', () => {
648664

649665
expect(dep).toEqual({
650666
registryUrl: 'https://example.com',
651-
releases: [{ version: '1.0.0' }],
667+
releases: [
668+
{
669+
attestation: false,
670+
dependencies: undefined,
671+
devDependencies: undefined,
672+
gitRef: undefined,
673+
version: '1.0.0',
674+
},
675+
],
652676
sourceDirectory: 'packages/foo',
653677
sourceUrl:
654678
'https://github.com/octocat/Hello-World/tree/master/packages/test',

lib/modules/datasource/npm/get.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import is from '@sindresorhus/is';
1+
import is, { isString } from '@sindresorhus/is';
22
import { z } from 'zod';
33
import { HOST_DISABLED } from '../../../constants/error-messages';
44
import { logger } from '../../../logger';
@@ -138,6 +138,7 @@ export async function getDependency(
138138
gitRef: res.versions?.[version].gitHead,
139139
dependencies: res.versions?.[version].dependencies,
140140
devDependencies: res.versions?.[version].devDependencies,
141+
attestation: isString(res.versions?.[version].dist?.attestations?.url),
141142
};
142143
const releaseTimestamp = asTimestamp(res.time?.[version]);
143144
if (releaseTimestamp) {

lib/modules/datasource/npm/index.spec.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,58 @@ describe('modules/datasource/npm/index', () => {
140140
expect(res?.deprecationMessage).toMatchSnapshot();
141141
});
142142

143+
it('should return attestation', async () => {
144+
const deprecatedPackage = {
145+
name: 'foobar',
146+
versions: {
147+
'0.0.1': {
148+
foo: 1,
149+
dist: {
150+
attestations: {
151+
url: 'https://registry.npmjs.org/-/npm/v1/attestations/foobar@0.0.1',
152+
},
153+
},
154+
},
155+
'0.0.2': {
156+
foo: 2,
157+
dist: {
158+
attestations: {
159+
url: 'https://registry.npmjs.org/-/npm/v1/attestations/foobar@0.0.2',
160+
},
161+
},
162+
},
163+
},
164+
repository: {
165+
type: 'git',
166+
url: 'git://github.com/renovateapp/dummy.git',
167+
},
168+
'dist-tags': {
169+
latest: '0.0.2',
170+
},
171+
time: {
172+
'0.0.1': '2018-05-06T07:21:53+02:00',
173+
'0.0.2': '2018-05-07T07:21:53+02:00',
174+
},
175+
};
176+
httpMock
177+
.scope('https://registry.npmjs.org')
178+
.get('/foobar')
179+
.reply(200, deprecatedPackage);
180+
const res = await getPkgReleases({ datasource, packageName: 'foobar' });
181+
expect(res).toMatchObject({
182+
releases: [
183+
{
184+
version: '0.0.1',
185+
attestation: true,
186+
},
187+
{
188+
version: '0.0.2',
189+
attestation: true,
190+
},
191+
],
192+
});
193+
});
194+
143195
it('should handle foobar', async () => {
144196
httpMock
145197
.scope('https://registry.npmjs.org')

lib/modules/datasource/npm/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ export interface NpmrcRules {
66
packageRules: PackageRule[];
77
}
88

9+
export interface NpmAttestations {
10+
url?: string;
11+
}
12+
13+
export interface NpmDistribution {
14+
attestations?: NpmAttestations;
15+
}
16+
917
export interface NpmResponseVersion {
1018
repository?: {
1119
url: string;
@@ -17,6 +25,7 @@ export interface NpmResponseVersion {
1725
dependencies?: Record<string, string>;
1826
devDependencies?: Record<string, string>;
1927
engines?: Record<string, string>;
28+
dist?: NpmDistribution;
2029
}
2130

2231
export interface NpmResponse {

lib/modules/datasource/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export interface Release {
7575
sourceDirectory?: string;
7676
currentAge?: string;
7777
isLatest?: boolean;
78+
attestation?: boolean;
7879
}
7980

8081
export interface ReleaseResult {

0 commit comments

Comments
 (0)