Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure a custom blueprint will be used if it's not the default blueprint #1084

Merged
merged 48 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c13b9df
fix: ensure specified blueprint is installed
Dec 14, 2020
bb3ad41
test: fix test for install module changes
Dec 17, 2020
f32dd04
feat: support using yarn to install
Dec 22, 2020
b526d57
test: modify "can install an addon with a default bluepr..."
Dec 22, 2020
a74e0f6
fix: expand -D to --save-dev
Dec 22, 2020
cdb7e43
docs: update readme with mroe context and information on what's possible
Dec 22, 2020
6982022
docs: add back ember init comparison documentation
Dec 22, 2020
c12ad89
fix: replace run with spawn
Jan 5, 2021
d005d74
fix: pass correct params to spawn command for modifications
Jan 5, 2021
5276c1f
fix(install-and-generate-blueprint): pass correct param format for bi…
Jan 5, 2021
e64dcf3
Update README.md
gitstevenpham Jan 8, 2021
1bd50c0
docs: remove duplicated information about why its difference than emb…
Jan 8, 2021
8579ff6
fix: ensure default blueprints work for on disk blueprints
Jan 20, 2021
853dce5
fix: move hasYarn to its own module
Feb 11, 2021
604e9d3
fix: revert --blueprint change in ember-cli-update-test
Feb 11, 2021
79b57fb
test: add unit test for has-yarn
Feb 11, 2021
a337471
test: fix hasYarn test
Feb 11, 2021
59623c2
test: added unit tests for functions in install-and-generate-blueprin…
Feb 12, 2021
b46ef80
test: add test case for blueprint options
Feb 12, 2021
39de14d
test: add integration test case for install for custom-blueprint
Feb 12, 2021
6c5d4d8
test: add test case for integration of index
Feb 12, 2021
680eb67
chore: fix lint issues
Feb 12, 2021
8ada4ab
fix: hashYarn -> hasYarn and getProjectOptions export
Feb 15, 2021
4c19207
fix: remove fixturify and follow creeateTempDir convention
Feb 15, 2021
3e3ad30
fix: use sinon to mock functions
Feb 15, 2021
c1da963
fix: eslint fix
Feb 15, 2021
8024efa
test: add test cause for index command with new functionality
Feb 16, 2021
63f1e9c
test: use sinon for second test case for install-and--generate-bluepr…
Feb 16, 2021
595ed07
test: check calls after main function call
Feb 16, 2021
e4801d1
fix: add back test assert accidentally deleted
Feb 16, 2021
86dafaf
fix: pr comments
Feb 25, 2021
da143ac
refactor: move blueprint override check into its own module
Feb 25, 2021
e23cd0b
merged to master
Feb 25, 2021
167fe54
fix: linting fixes
Feb 25, 2021
88fd6d2
test: correct typoo in test name
Feb 26, 2021
cea7011
remove mocking from test
Mar 3, 2021
fafe03a
fix: hasYarn function async
Mar 3, 2021
9633f7b
addressing more pr comments
Mar 3, 2021
66d6532
move custom blueprint test to its own describe
Mar 3, 2021
47426bd
test: add test case with install flow with default blueprint
Mar 4, 2021
292446d
remove sinon stubbing in acceptance
Mar 4, 2021
1ba496c
switch to use npm helper
Mar 4, 2021
3ced520
remove sinon from install-test integration
Mar 4, 2021
36920ec
use loadSafeBlueprintFile
Mar 4, 2021
bbb89ed
fix final destination blueprint read
Mar 4, 2021
00d6590
clean up get-default-blueprint-name-override
Mar 10, 2021
3ab613e
move 2 test cases for get-default-blueprint-name-override to integration
Mar 10, 2021
9c2b730
final cleanup
Mar 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
![](https://github.com/ember-cli/ember-cli-update/workflows/CI/badge.svg)
[![Build status](https://ci.appveyor.com/api/projects/status/iguxxyxkiu9kyeyo/branch/master?svg=true)](https://ci.appveyor.com/project/embercli/ember-cli-update/branch/master)

Update [Ember CLI](https://ember-cli.com/) projects
Ember-cli-update helps you update the bootstrapped boilerplate files for [Ember CLI](https://ember-cli.com/) projects and addon blueprints for newer versions while trying to maintain your changes. It also facilitates codemods by fetching the list of codemods and instructions for your projects.
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved

Check out [the new guides](https://github.com/ember-cli/ember-cli-update/wiki).
The 2 use cases are:
1. Updating a project's boilerplate code from an older Ember version to a newer one like 3.4.0 to 3.20.0 for example. These are called base blueprints and there are 3 types officially provided by ember-cli: `app`, `addon`, and `glimmer`.
- This is different from the existing `ember init` command. That command tries to reset your project back to a brand new project. It removes all your changes and additions.
2. Updating boilerplate code for a blueprint from an Ember addon from an older version to a newer one. These are called custom blueprints.

You can run this either as a global executable available to all projects or an Ember CLI command in a single project.
Check out [the wiki guide](https://github.com/ember-cli/ember-cli-update/wiki) for more details.
This is different from the existing `ember init` command. That command tries to reset your project back to a brand new project. It removes all your changes and additions.
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved

Fetches list of codemods and instructions for your projects
You can run the CLI either as a global executable available to all projects or an Ember CLI command in a single project.

This attempts to be a thin wrapper of [boilerplate-update](https://github.com/kellyselden/boilerplate-update).
The CLI attempts to be a thin wrapper of [boilerplate-update](https://github.com/kellyselden/boilerplate-update).

## Installation

Expand All @@ -38,14 +42,37 @@ or if you installed as an Ember CLI command run

`ember update`

This will update your app or addon to the latest Ember CLI version. It does this by fetching the latest version and comparing it to your project's Ember CLI version. It then applies a diff of the changes from the latest version to your project. It will only modify the files if there are changes between your project's version and the latest version, and it will only change the section necessary, not the entire file.

This is different from the existing `ember init` command. That command tries to reset your project back to a brand new project. It removes all your changes and additions.
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved
An example output would be:

```bash
# In an ember project directory
> ember-cli-update
? Blueprint updates have been found. Which one would you like to update? (Use arrow keys)
❯ app, current: 3.7.0, latest: 3.23.0
ember-bootstrap, current: 2.8.0, latest: 4.5.0
ember-cli-mirage, current: 1.1.8, latest: 2.0.0
```

You'll be prompted to update to the latest version or a specific one.

You will probably encounter merge conflicts, in which the default behavior is to let you resolve conflicts on your own. You can supply the `--resolve-conflicts` option to run your system's git merge tool if any conflicts are found.

This tool can also run codemods for you. The option `--run-codemods` will figure out what codemods apply to your current version of Ember.js, and download and run them for you.

## How does it work?
Modern Emberjs projects have [`config/ember-cli-update.json`](https://github.com/ember-cli/ember-cli-update/wiki/Config-Schema) in the boilerplate template for `addon` and `app` types. This file tells this CLI what type of project is being updated and what custom blueprints from what package are installed and generated.

If this CLI is run on an older project, or the json file doesn't exist, it'll just prompt for ember-cli project boilerplate update (`addon`, `app`, or `glimmer`).

Generally, the CLI creates 2 new ember-cli projects with the current and specified versions in order to figure out the diff between the two and applies the diff to your project. It will only modify the files if there are changes between your project's version and the specified version, and it will only change the section necessary, not the entire file.

### ember-cli project (addon, app, and glimmer) boilerplate updates
When updating an ember-cli project, the CLI will create a new project (ember new) with the current version of your project and another one with the version specified.

### Custom blueprint
The CLI will create 2 new projects using the same version of the baseBlueprint (the `addon`, `app`, or `glimmer` type). For one of the projects, it will install the current version of the addon containing the desired blueprint and generate it. For the other, it will install the specified version and generate the blueprint.

## Examples

(These examples assume you are using the global command.)
Expand Down
5 changes: 5 additions & 0 deletions bin/commands/install.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
'use strict';

const args = require('../../src/args');
const install = require('../../src/install');

module.exports.command = 'install <addon>';

module.exports.describe = 'install an addon';

module.exports.builder = {
blueprint: args['blueprint']
};

module.exports.handler = async function handler(argv) {
try {
await install(argv);
Expand Down
2 changes: 1 addition & 1 deletion src/codemods.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const getBlueprintFilePath = require('./get-blueprint-file-path');
const chooseBlueprintUpdates = require('./choose-blueprint-updates');
const getBlueprintFromArgs = require('./get-blueprint-from-args');
const isDefaultBlueprint = require('./is-default-blueprint');
const getProjectOptions = require('./get-project-options');
const { getProjectOptions } = require('./get-project-options');
const loadDefaultBlueprintFromDisk = require('./load-default-blueprint-from-disk');

module.exports = async function codemods({
Expand Down
88 changes: 0 additions & 88 deletions src/ember-install-addon.js

This file was deleted.

24 changes: 18 additions & 6 deletions src/get-project-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ function getProjectType(checkForDep, keywords) {
throw new Error('Ember CLI project type could not be determined');
}

/**
* Check if there is a yarn.lock file to indicate if the project uses yarn as the package manager
*
* @param {string} projectRoot - Path to the project root to check for yarn usage
* @returns {Promise<boolean>}
*/
module.exports.hasYarn = async function hasYarn(projectRoot) {
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved
let isYarn = false;
try {
await fs.access(path.join(projectRoot, 'yarn.lock'), fs.constants.F_OK);
isYarn = true;
} catch (err) {}
return isYarn;
};


/**
* Determine what kind of ember flavor this project is and if it uses yarn or npm
*
Expand All @@ -43,7 +59,7 @@ function getProjectType(checkForDep, keywords) {
* @param {object} blueprint - Expected to contain `packageName` and `name`
* @returns {Promise<[string]|string[]>} - Array of strings containing keywords
*/
module.exports = async function getProjectOptions({
module.exports.getProjectOptions = async function getProjectOptions({
keywords,
dependencies,
devDependencies
Expand All @@ -64,11 +80,7 @@ module.exports = async function getProjectOptions({

let cwd = process.cwd();

let isYarn;
try {
await fs.access(path.join(cwd, 'yarn.lock'), fs.constants.F_OK);
isYarn = true;
} catch (err) {}
let isYarn = await module.exports.hasYarn(cwd);

if (isYarn) {
options.push('yarn');
Expand Down
31 changes: 22 additions & 9 deletions src/get-start-and-end-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ const execa = require('execa');
const { spawn } = require('./run');
const utils = require('./utils');
const isDefaultBlueprint = require('./is-default-blueprint');
const emberInstallAddon = require('./ember-install-addon');
const installAndGenerateBlueprint = require('./install-and-generate-blueprint');
const overwriteBlueprintFiles = require('./overwrite-blueprint-files');
const debug = require('./debug');
const npm = require('boilerplate-update/src/npm');
const mutatePackageJson = require('boilerplate-update/src/mutate-package-json');
const {
glimmerPackageName
} = require('./constants');
const { glimmerPackageName } = require('./constants');
const { hasYarn } = require('./get-project-options');

const nodeModulesIgnore = `

Expand Down Expand Up @@ -233,11 +232,13 @@ function createProject(runEmber) {
}

if (await isDefaultAddonBlueprint(blueprint)) {
let isYarnProject = await hasYarn(projectRoot);
await _runEmber(baseBlueprint);

await module.exports.installAddonBlueprint({
projectRoot,
blueprint
blueprint,
packageManager: isYarnProject ? 'yarn' : 'npm'
});
} else {
await _runEmber(blueprint);
Expand All @@ -255,19 +256,31 @@ function createProject(runEmber) {
};
}

/**
* Install packages from package.json then install the specified package and generate blueprint
*
* @param {string} projectRoot - Used as cwd for running npm commands as well directory to make file modifications
* @param {object} blueprint - Expected to have `packageName`, `version`, and `path` (nullable) attributes
* @param {string} packageManager - Expected to be either `npm` or `yarn`
* @returns {Promise<void>}
*/
module.exports.installAddonBlueprint = async function installAddonBlueprint({
projectRoot,
blueprint
blueprint,
packageManager = 'npm'
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved
}) {
// `not found: ember` without this
await spawn('npm', ['install'], { cwd: projectRoot });
await spawn(packageManager, ['install'], { cwd: projectRoot });

let { ps } = await emberInstallAddon({
let { ps } = await installAndGenerateBlueprint({
cwd: projectRoot,
packageName: blueprint.packageName,
version: blueprint.version,
blueprintPath: blueprint.path,
stdin: 'pipe'
blueprintName: blueprint.name,
blueprintOptions: blueprint.options || [],
gitstevenpham marked this conversation as resolved.
Show resolved Hide resolved
stdin: 'pipe',
packageManager
});

overwriteBlueprintFiles(ps);
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const getProjectOptions = require('./get-project-options');
const { getProjectOptions } = require('./get-project-options');
const getPackageName = require('./get-package-name');
const getVersions = require('./get-versions');
const _getTagVersion = require('./get-tag-version');
Expand Down
Loading