Skip to content

Commit 44249dc

Browse files
SimenBtargos
authored andcommitted
feat: add support for yarn installations (#560)
1 parent 86d525c commit 44249dc

21 files changed

+479
-119
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ This is for adding a module to be included in the default `citgm-all` runs.
5252
* Module source code must be on Github.
5353
* Published versions must include a tag on Github
5454
* The test process must be executable with only the commands
55-
`npm install && npm test` using the tarball downloaded from the Github tag
55+
`npm install && npm test` or (`yarn install && yarn test`) using the tarball downloaded from the Github tag
5656
mentioned above
5757
* The tests pass on supported major release lines
5858
* The maintainers of the module remain responsive when there are problems

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Options:
112112
--includeTags tag1 tag2 Only test modules from the lookup that contain a matching tag field
113113
--excludeTags tag1 tag2 Specify which tags to skip from the lookup (takes priority over includeTags)
114114
Module names are automatically added as tags.
115+
-y, --yarn Install and test the project using yarn instead of npm
115116
```
116117

117118
When using a JSON config file, the properties need to be the same as the
@@ -140,6 +141,7 @@ For syntax, see [lookup.json](./lib/lookup.json), the available attributes are:
140141
"maintainers": ["user1", "user2"] - List of module maintainers to be contacted with issues
141142
"tags": ["tag1", "tag2"] Specify which tags apply to the module
142143
"ignoreGitHead": Ignore the gitHead field if it exists and fallback to using github tags
144+
"yarn": Install and test the project using yarn instead of npm
143145
```
144146

145147
If you want to pass options to npm, eg `--registry`, you can usually define an

bin/citgm-all.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const options = {
7171
timeoutLength: app.timeout,
7272
tmpDir: app.tmpDir,
7373
customTest: app.customTest,
74+
yarn: app.yarn,
7475
includeTags: app.includeTags || [],
7576
excludeTags: app.excludeTags || []
7677
};

bin/citgm.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ const options = {
4848
timeoutLength: app.timeout,
4949
sha: app.sha,
5050
tmpDir: app.tmpDir,
51-
customTest: app.customTest
51+
customTest: app.customTest,
52+
yarn: app.yarn
5253
};
5354

5455
if (!citgm.windows) {

lib/citgm.js

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let which = require('which'); // Mocked in tests
1010
const grabModuleData = require('./grab-module-data');
1111
const grabProject = require('./grab-project');
1212
const lookup = require('./lookup');
13-
const npm = require('./npm');
13+
const packageManager = require('./package-manager');
1414
const tempDirectory = require('./temp-directory');
1515
const unpack = require('./unpack');
1616

@@ -29,14 +29,28 @@ exports.windows = windows;
2929
* 5. Output the results.
3030
**/
3131

32-
function find(app, context, next) {
33-
which(app, function(err, resolved) {
32+
function findNode(context, next) {
33+
which('node', function(err, resolved) {
3434
if (err) {
35-
next(Error(app + ' not found in path!'));
35+
next(err);
3636
return;
3737
}
38-
context.emit('data', 'verbose', context.module.name + ' using-' + app,
39-
resolved);
38+
context.emit('data', 'verbose', context.module.name + ' using-node',
39+
resolved);
40+
next(null, context);
41+
});
42+
}
43+
44+
function findPackageManagers(context, next) {
45+
packageManager.getPackageManagers((err, res) => {
46+
if (err) {
47+
next(err);
48+
return;
49+
}
50+
51+
context.npmPath = res.npm;
52+
context.yarnPath = res.yarn;
53+
4054
next(null, context);
4155
});
4256
}
@@ -46,13 +60,13 @@ function init(context, next) {
4660
if (!windows) {
4761
if (context.options.uid)
4862
context.emit('data', 'verbose', context.module.name + ' using-uid',
49-
context.options.uid);
63+
context.options.uid);
5064
if (context.options.gid)
5165
context.emit('data', 'verbose', context.module.name + ' using-gid',
52-
context.options.gid);
66+
context.options.gid);
5367
}
5468
context.emit('data', 'silly', context.module.name + ' init-detail',
55-
context.module);
69+
context.module);
5670
next(null, context); // Inject the context
5771
}
5872

@@ -98,15 +112,15 @@ Tester.prototype.run = function() {
98112

99113
async.waterfall([
100114
init.bind(null, this),
101-
find.bind(null, 'node'),
102-
find.bind(null, 'npm'),
115+
findNode,
116+
findPackageManagers,
103117
tempDirectory.create,
104118
grabModuleData,
105119
lookup,
106120
grabProject,
107121
unpack,
108-
npm.install,
109-
npm.test
122+
packageManager.install,
123+
packageManager.test
110124
], (err) => {
111125
if (!this.cleanexit) {
112126
const payload = {
@@ -136,7 +150,7 @@ Tester.prototype.run = function() {
136150
});
137151
};
138152

139-
Tester.prototype.cleanup = function () {
153+
Tester.prototype.cleanup = function() {
140154
this.cleanexit = true;
141155
const payload = {
142156
name: this.module.name || this.module.raw,

lib/common-args.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ module.exports = function commonArgs (app) {
7575
description: 'Set timeout for npm install',
7676
default: 1000 * 60 * 10
7777
})
78+
.option('yarn', {
79+
alias: 'y',
80+
type: 'boolean',
81+
description: 'Install and test the project using yarn instead of npm',
82+
default: false
83+
})
7884
.example('citgm-all --customTest /path/to/customTest.js',
7985
'Runs a custom node test script instead of "npm test"');
8086

lib/lookup.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ function resolve(context, next) {
114114
if (rep.tags) {
115115
context.module.tags = rep.tags;
116116
}
117+
if (rep.yarn) {
118+
context.module.useYarn = true;
119+
}
117120
context.module.flaky = context.options.failFlaky ?
118121
false : isMatch(rep.flaky);
119122
context.module.expectFail = context.options.expectFail ?

lib/npm/index.js

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const which = require('which');
5+
const npmWhich = require('npm-which')(__dirname);
6+
7+
const windows = (process.platform === 'win32');
8+
9+
module.exports = function getExecutable(binaryName, next) {
10+
if (binaryName === 'yarn') {
11+
// Use `npm-which` for yarn to get the locally version
12+
npmWhich(binaryName, next);
13+
14+
return;
15+
}
16+
17+
which(binaryName, (err, packageManagerBin) => {
18+
if (err) {
19+
next(err);
20+
return;
21+
}
22+
23+
if (windows) {
24+
packageManagerBin = path.join(path.dirname(packageManagerBin),
25+
'node_modules', 'npm', 'bin', 'npm-cli.js');
26+
}
27+
28+
next(null, packageManagerBin);
29+
});
30+
};

lib/package-manager/index.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
const async = require('async');
4+
5+
const install = require('./install');
6+
const test = require('./test');
7+
const getExecutable = require('./get-executable');
8+
9+
function pkgInstall(context, next) {
10+
if (context.options.yarn || context.module.useYarn) {
11+
install('yarn', context, next);
12+
} else {
13+
install('npm', context, next);
14+
}
15+
}
16+
17+
function pkgTest(context, next) {
18+
if (context.options.yarn || context.module.useYarn) {
19+
test('yarn', context, next);
20+
} else {
21+
test('npm', context, next);
22+
}
23+
}
24+
25+
function getPackageManagers(next) {
26+
async.parallel([
27+
getExecutable.bind(null, 'npm'),
28+
getExecutable.bind(null, 'yarn')
29+
], (err, res) => {
30+
if (err) {
31+
next(err);
32+
return;
33+
}
34+
35+
next(null, { npm: res[0], yarn: res[1] });
36+
});
37+
}
38+
39+
module.exports = {
40+
install: pkgInstall,
41+
test: pkgTest,
42+
getPackageManagers: getPackageManagers
43+
};

0 commit comments

Comments
 (0)