Skip to content

Commit 1de296c

Browse files
committed
feat: dependency detection error reporting
1 parent 360b09b commit 1de296c

File tree

10 files changed

+135
-9
lines changed

10 files changed

+135
-9
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,16 @@ const result = {
126126
// will contain a list of unique versions for each dependency found in the dependency tree
127127
"versions": {
128128
"dependency-A": ["0.0.10", "1.2.5"],
129-
"dependency-B": ["0.5.3", "1.0.0"]
129+
"dependency-B": ["0.5.3", "1.0.0"],
130+
"dependency-C": ["7.8.9"]
131+
},
132+
133+
// will contain a list of errors that were encountered while resolving dependency support information
134+
"errors": {
135+
"dependency-C": {
136+
// the `message` will always be either a string or `null`
137+
"message": "Failed to download some information or something"
138+
}
130139
}
131140
}
132141
}

lib/deps.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const Path = require('path');
66
const Tmp = require('tmp');
77

88
const Package = require('./package');
9+
const Utils = require('./utils');
910

1011
const internals = {};
1112

@@ -106,16 +107,27 @@ exports.detect = async ({ packageJson, loadFile }, options) => {
106107
const versions = await internals.resolve({ packageJson, lockfile }, options);
107108

108109
const support = [];
110+
const errors = {};
111+
let hasErrors = false;
109112

110113
for (const packageName of Object.keys(versions).sort()) {
111114
try {
112115
const { result } = await Package.detect({ packageName });
113116
support.push(result);
114117
}
115118
catch (err) {
116-
console.warn(`Failed to detect support for ${packageName}: ${err && err.message}`);
119+
hasErrors = true;
120+
errors[packageName] = {
121+
message: Utils.getErrorMessage(err)
122+
};
117123
}
118124
}
119125

120-
return { support, versions };
126+
const result = { support, versions };
127+
128+
if (hasErrors) {
129+
result.errors = errors;
130+
}
131+
132+
return result;
121133
};

lib/utils.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,21 @@ const SimpleGit = require('simple-git/promise');
44

55
/* $lab:coverage:off$ */
66
// this is wrapped primarily to be able to stub it
7-
exports.simpleGit = (...args) => SimpleGit(...args);
7+
exports.simpleGit = (...args) => {
8+
9+
return SimpleGit(...args);
10+
};
811
/* $lab:coverage:on$ */
12+
13+
exports.getErrorMessage = (error) => {
14+
15+
if (typeof error === 'string') {
16+
return error;
17+
}
18+
19+
if (error && error.message) {
20+
return error.message;
21+
}
22+
23+
return null;
24+
};

test/fixtures/packuments/rimraf.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

test/index.js

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -948,15 +948,17 @@ describe('detect-node-support', () => {
948948
.returns('9cef39d21ad229dea4b10295f55b0d9a83800b23\tHEAD\n');
949949

950950
Nock('https://registry.npmjs.org')
951+
.persist()
951952
.get('/is-ci')
952-
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'deps-test', 'packuments', 'is-ci.json')))
953+
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'packuments', 'is-ci.json')))
953954
.get('/ci-info')
954-
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'deps-test', 'packuments', 'ci-info.json')))
955+
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'packuments', 'ci-info.json')))
955956
.get('/debug')
956-
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'deps-test', 'packuments', 'debug.json')))
957+
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'packuments', 'debug.json')))
957958
.get('/ms')
958-
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'deps-test', 'packuments', 'ms.json')))
959-
.persist();
959+
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'packuments', 'ms.json')))
960+
.get('/rimraf')
961+
.reply(200, Fs.readFileSync(Path.join(__dirname, 'fixtures', 'packuments', 'rimraf.json')));
960962

961963
Nock('https://raw.githubusercontent.com')
962964
.get('/watson/is-ci/HEAD/package.json')
@@ -974,6 +976,8 @@ describe('detect-node-support', () => {
974976
.get('/zeit/ms/HEAD/package.json')
975977
.reply(200, JSON.stringify({ name: 'ms', version: '2.1.2' }))
976978
.get('/zeit/ms/HEAD/.travis.yml')
979+
.reply(404)
980+
.get('/isaacs/rimraf/HEAD/package.json')
977981
.reply(404);
978982
});
979983

@@ -1272,6 +1276,52 @@ describe('detect-node-support', () => {
12721276
}
12731277
});
12741278
});
1279+
1280+
it('rethrows lock file parsing errors', async () => {
1281+
1282+
const path = await internals.prepareFixture({
1283+
packageJson: JSON.parse(Fs.readFileSync(Path.join(__dirname, 'fixtures', 'deps-test', 'package.json')).toString()),
1284+
packageLockJson: 'testing-single-version.yml'
1285+
});
1286+
1287+
await expect(NodeSupport.detect({ path }, { deps: true })).to.reject('Unexpected token l in JSON at position 0');
1288+
});
1289+
1290+
it('handles failures to load packages', async () => {
1291+
1292+
Sinon.stub(console, 'warn');
1293+
1294+
const path = await internals.prepareFixture({
1295+
packageJson: {
1296+
name: '@pkgjs/detect-node-support-deps-test',
1297+
version: '0.0.0-development',
1298+
dependencies: {
1299+
rimraf: '1.x'
1300+
}
1301+
}
1302+
});
1303+
1304+
const result = await NodeSupport.detect({ path }, { deps: true });
1305+
1306+
internals.assertCommit(result);
1307+
1308+
expect(result).to.equal({
1309+
name: '@pkgjs/detect-node-support-deps-test',
1310+
version: '0.0.0-development',
1311+
timestamp: 1580673602000,
1312+
dependencies: {
1313+
support: [],
1314+
versions: {
1315+
rimraf: ['1.0.9']
1316+
},
1317+
errors: {
1318+
rimraf: {
1319+
message: 'git://github.com/isaacs/rimraf.git does not contain a package.json'
1320+
}
1321+
}
1322+
}
1323+
});
1324+
});
12751325
});
12761326
});
12771327
});

test/utils.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const Utils = require('../lib/utils');
4+
5+
const { describe, it } = exports.lab = require('@hapi/lab').script();
6+
const { expect } = require('@hapi/code');
7+
8+
describe('Utils', () => {
9+
10+
describe('getErrorMessage()', () => {
11+
12+
it('returns error message when present', () => {
13+
14+
expect(Utils.getErrorMessage(new Error('Test error'))).to.equal('Test error');
15+
});
16+
17+
it('returns the string', () => {
18+
19+
expect(Utils.getErrorMessage('Test error')).to.equal('Test error');
20+
});
21+
22+
it('null for an object without a message', () => {
23+
24+
expect(Utils.getErrorMessage({})).to.equal(null);
25+
});
26+
27+
it('null for null', () => {
28+
29+
expect(Utils.getErrorMessage(null)).to.equal(null);
30+
});
31+
32+
33+
it('null for undefined', () => {
34+
35+
expect(Utils.getErrorMessage()).to.equal(null);
36+
});
37+
});
38+
});

0 commit comments

Comments
 (0)