-
-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feat] Adds support for Yarn/NPM workspaces
This PR adds support for workspaces to allow ember-try to run scenarios in monorepo based repositories quickly and efficiently. Workspaces are currently only supported by Yarn, but NPM has indicated that they [want to add support in the future](https://blog.npmjs.org/post/173239798780/beyond-npm6-the-future-of-the-npm-cli), and other tools for managing monorepos such as Lerna integrate nicely with workspaces, so it feels like the best way to add this type of support. To enable workspaces, users need to install `ember-cli` and `ember-try` in the top level monorepo package, add a `config/ember-try.js` file, and set `useWorkspaces` and `useYarn` to true in that config. This means that the adapter is limited to using one try config for _all_ of the packages in the repo. For most monorepo use cases this should be sufficient, and users can still add ember-try to individual packages if needed for unique per-package scenarios. The workspace adapter reuses the NPM adapter for each individual package. To do this, a new method needed to be exposed to allow depSets to be applied without running the install, since that needs to be done _once_ at the top level. An alternative would be to expose this as a task directly so it could be run as a command in each package, but that would be significantly more complicated.
- Loading branch information
Showing
9 changed files
with
396 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
'use strict'; | ||
|
||
const CoreObject = require('core-object'); | ||
const fs = require('fs-extra'); | ||
const RSVP = require('rsvp'); | ||
const path = require('path'); | ||
const extend = require('extend'); | ||
const debug = require('debug')('ember-try:dependency-manager-adapter:workspaces'); | ||
const walkSync = require('walk-sync'); | ||
|
||
const NpmAdapter = require('./npm'); | ||
|
||
module.exports = CoreObject.extend({ | ||
init() { | ||
this._super.apply(this, arguments); | ||
this.run = this.run || require('../utils/run'); | ||
|
||
if (!this.useYarnCommand) { | ||
throw new Error('workspaces are currently only supported by Yarn, you must set `useYarn` to true'); | ||
} | ||
}, | ||
|
||
packageJSON: 'package.json', | ||
|
||
setup(options) { | ||
if (!options) { | ||
options = {}; | ||
} | ||
|
||
let packageJSON = JSON.parse(fs.readFileSync(this.packageJSON)); | ||
let workspaceGlobs = packageJSON.workspaces; | ||
|
||
if (!workspaceGlobs || !workspaceGlobs.length) { | ||
throw new Error('you must define the `workspaces` property in package.json with at least one workspace to use workspaces with ember-try'); | ||
} | ||
|
||
// workspaces is a list of globs, loop over the list and find | ||
// all paths that contain a `package.json` file | ||
let workspacePaths = walkSync('.', { globs: workspaceGlobs }).filter(workspacePath => { | ||
let packageJSONPath = path.join(this.cwd, workspacePath, 'package.json'); | ||
return fs.existsSync(packageJSONPath); | ||
}); | ||
|
||
this._packageAdapters = workspacePaths.map(workspacePath => { | ||
return new NpmAdapter({ | ||
cwd: workspacePath, | ||
run: this.run, | ||
managerOptions: this.managerOptions, | ||
useYarnCommand: true, | ||
}); | ||
}); | ||
|
||
return RSVP.all(this._packageAdapters.map(adapter => adapter.setup(options))); | ||
}, | ||
|
||
changeToDependencySet(depSet) { | ||
this._packageAdapters.forEach(adapter => { | ||
adapter.applyDependencySet(depSet); | ||
}); | ||
|
||
return this._install().then(() => { | ||
let deps = extend({}, depSet.dependencies || {}, depSet.devDependencies || {}); | ||
let currentDeps = Object.keys(deps).map((dep) => { | ||
return { | ||
name: dep, | ||
versionExpected: deps[dep], | ||
versionSeen: this._findCurrentVersionOf(dep), | ||
packageManager: 'yarn', | ||
}; | ||
}); | ||
|
||
debug('Switched to dependencies: \n', currentDeps); | ||
|
||
return RSVP.Promise.resolve(currentDeps); | ||
}); | ||
}, | ||
|
||
cleanup() { | ||
return RSVP.all(this._packageAdapters.map(adapter => adapter.cleanup())); | ||
}, | ||
|
||
_install() { | ||
let mgrOptions = this.managerOptions || []; | ||
|
||
debug('Run yarn install with options %s', mgrOptions); | ||
|
||
if (mgrOptions.indexOf('--no-lockfile') === -1) { | ||
mgrOptions = mgrOptions.concat(['--no-lockfile']); | ||
} | ||
// npm warns on incompatible engines | ||
// yarn errors, not a good experience | ||
if (mgrOptions.indexOf('--ignore-engines') === -1) { | ||
mgrOptions = mgrOptions.concat(['--ignore-engines']); | ||
} | ||
|
||
return this.run('yarn', [].concat(['install'], mgrOptions), { cwd: this.cwd }); | ||
}, | ||
|
||
_findCurrentVersionOf(dep) { | ||
return this._packageAdapters[0]._findCurrentVersionOf(dep); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.