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

ADD a CLI for bootstrapping #1216

Merged
merged 28 commits into from
Aug 23, 2017
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
369ac55
ADD a CLI for bootstrapping
ndelangen Jun 8, 2017
5726f13
Merge branch 'master' into improve-bootstrap-command
ndelangen Jun 9, 2017
27edf5e
Merge branch 'master' into improve-bootstrap-command
ndelangen Jul 23, 2017
4f4b9e4
set as default bootstrap command && add core as default
ndelangen Jul 23, 2017
9fafeab
CHANGE hoist-internals script to be less verbose
ndelangen Jul 23, 2017
86c25d6
Merge branch 'master' into improve-bootstrap-command
ndelangen Jul 23, 2017
6aad7a1
use `-- --flag` in docs & circleci
ndelangen Jul 24, 2017
8146294
Merge branch 'master' into improve-bootstrap-command
ndelangen Jul 24, 2017
31f83aa
Merge branch 'master' into improve-bootstrap-command
ndelangen Jul 26, 2017
1327e2d
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 19, 2017
02e0950
ADD build-packs
ndelangen Aug 19, 2017
540ec9a
DISABLE concurrency on lint-staged (I got problems with git lock files)
ndelangen Aug 19, 2017
c85776a
WIP
ndelangen Aug 20, 2017
de7777e
SWITCH to normal node for bootstrap script && CHANGE circleCI to use …
ndelangen Aug 20, 2017
ed0e61e
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 20, 2017
b215110
FIX circleCI.yml
ndelangen Aug 21, 2017
7940e62
REVERT incorrect changes on docs/pages
ndelangen Aug 21, 2017
879928d
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 23, 2017
1843196
ADD crna-kitchen-sink bootstrap command
ndelangen Aug 23, 2017
43b8753
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 23, 2017
9f30bbf
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 23, 2017
f84623d
ADD .vscode and .idea to gitignore, but whitelist them from being rem…
ndelangen Aug 23, 2017
6dd4ae7
Merge branch 'improve-bootstrap-command' of github.com:storybooks/sto…
ndelangen Aug 23, 2017
0723401
ADD -- --core to CONTRIBUTING.md
ndelangen Aug 23, 2017
7fd661c
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 23, 2017
30e7c37
ADD a confirmation step when doing the reset task, it will NOT ask wh…
ndelangen Aug 23, 2017
faec65e
Merge branch 'master' into improve-bootstrap-command
ndelangen Aug 23, 2017
55a2b9a
IMPROVE confirm message
ndelangen Aug 23, 2017
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
14 changes: 5 additions & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- run:
name: "Bootstrapping"
command: |
npm run bootstrap
npm run bootstrap -- --all
- save_cache:
key: package-dependencies-{{ checksum "package.json" }}
paths:
Expand All @@ -63,7 +63,7 @@ jobs:
- run:
name: "Bootstrapping"
command: |
npm run bootstrap
npm run bootstrap -- --core
- run:
name: "Build react kitchen-sink"
command: |
Expand All @@ -87,9 +87,7 @@ jobs:
- run:
name: "Bootstrapping packages"
command: |
npm run bootstrap
npm run build-packs
npm run bootstrap:react-native-vanilla
npm run bootstrap -- --core --reactnative
- run:
name: "Running react-native"
command: |
Expand All @@ -109,7 +107,7 @@ jobs:
- run:
name: "Bootstrapping"
command: |
npm run bootstrap:docs
npm run bootstrap -- --docs
- run:
name: "Running docs"
command: |
Expand Down Expand Up @@ -145,9 +143,7 @@ jobs:
- run:
name: "Bootstrapping"
command: |
npm run bootstrap
npm run build-packs
npm run bootstrap:react-native-vanilla
npm run bootstrap -- --core --reactnative
- run:
name: "Unit testing"
command: |
Expand Down
50 changes: 27 additions & 23 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,34 @@ No software is bug free. So, if you got an issue, follow these steps:

To test your project against the current latest version of storybook, you can clone the repository and link it with `npm`. Try following these steps:

1. Download the latest version of this project, and build it
1. Download the latest version of this project, and build it:

git clone https://github.com/storybooks/storybook.git
cd storybook
npm install
npm run bootstrap
```sh
git clone https://github.com/storybooks/storybook.git
cd storybook
npm install
npm run bootstrap
```

2. Link `storybook` and any other required dependencies
2. Link `storybook` and any other required dependencies:

cd app/react
npm link
```sh
cd app/react
npm link

cd <your-project>
npm link @storybook/react
cd <your-project>
npm link @storybook/react

# repeat with whichever other parts of the monorepo you are using.
# repeat with whichever other parts of the monorepo you are using.
```

### Reproductions

The best way to help figure out an issue you are having is to produce a minimal reproduction against the `master` branch.

A good way to do that is using the example `cra-kitchen-sink` app embedded in this repository:

```bash
```sh
# Download and build this repository:
git clone https://github.com/storybooks/storybook.git
cd storybook
Expand Down Expand Up @@ -115,15 +119,13 @@ If an issue is a `bug`, and it doesn't have a clear reproduction that you have p
### Closing issues

- Duplicate issues should be closed with a link to the original.

- Unreproducible issues should be closed if it's not possible to reproduce them (if the reporter drops offline, it is reasonable to wait 2 weeks before closing).

- Unreproducible issues should be closed if it's not possible to reproduce them (if the reporter drops offline,
it is reasonable to wait 2 weeks before closing).
- `bug`s should be labelled `merged` when merged, and be closed when the issue is fixed and released.

- `feature`s, `maintenance`s, `greenkeeper`s should be labelled `merged` when merged, and closed when released or if the feature is deemed not appropriate.

- `question / support`s should be closed when the question has been answered. If the questioner drops offline, a reasonable period to wait is two weeks.

- `feature`s, `maintenance`s, `greenkeeper`s should be labelled `merged` when merged,
and closed when released or if the feature is deemed not appropriate.
- `question / support`s should be closed when the question has been answered.
If the questioner drops offline, a reasonable period to wait is two weeks.
- `discussion`s should be closed at a maintainer's discretion.

## Development Guide
Expand All @@ -133,9 +135,11 @@ If an issue is a `bug`, and it doesn't have a clear reproduction that you have p
This project written in ES2016+ syntax so, we need to transpile it before use.
So run the following command:

npm run dev
```sh
npm run dev
```

This will watch files and transpile.
This will watch files and transpile in watch mode.

### Linking

Expand Down Expand Up @@ -194,7 +198,7 @@ git status
git clean -fdx && yarn

# build all the packages
npm run bootstrap
npm run bootstrap -- --all
```

From here there are different procedures for prerelease (e.g. alpha/beta/rc) and proper release.
Expand Down
34 changes: 20 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"url": "https://github.com/storybooks/storybook.git"
},
"scripts": {
"bootstrap": "lerna bootstrap --concurrency 1 --npm-client=\"yarn\" --hoist && node ./scripts/hoist-internals.js",
"bootstrap": "./scripts/bootstrap.js",
"bootstrap:core": "lerna bootstrap --concurrency 1 --npm-client=\"yarn\" --hoist && node ./scripts/hoist-internals.js",
"bootstrap:docs": "cd docs && yarn install",
"bootstrap:react-native-vanilla": "lerna exec --scope react-native-vanilla -- npm install",
"bootstrap:crna-kitchen-sink": "lerna exec --scope crna-kitchen-sink -- npm install",
Expand All @@ -22,7 +23,6 @@
"docs:deploy:manual": "cd docs && npm run deploy:manual",
"docs:dev": "cd docs && npm run dev",
"github-release": "github-release-from-changelog",
"import-repo": "lerna import",
"lint": "npm run lint:js . && npm run lint:md .",
"lint:js": "eslint --cache --cache-location=.cache/eslint --ext .js,.jsx,.json",
"lint:md": "remark",
Expand All @@ -41,6 +41,7 @@
"babel-preset-stage-0": "^6.24.1",
"chalk": "^2.0.1",
"codecov": "^2.2.0",
"commander": "^2.9.0",
"danger": "^1.0.0",
"enzyme": "^2.9.1",
"eslint": "^4.3.0",
Expand All @@ -55,6 +56,7 @@
"fs-extra": "^4.0.0",
"gh-pages": "^1.0.0",
"github-release-from-changelog": "^1.2.1",
"inquirer": "^3.1.0",
"glob": "^7.1.2",
"husky": "^0.14.3",
"jest": "^20.0.4",
Expand Down Expand Up @@ -85,18 +87,22 @@
"url": "https://opencollective.com/storybook"
},
"lint-staged": {
"*.js": [
"npm run lint:js -- --fix",
"git add"
],
"*.json": [
"npm run lint:js -- --fix",
"git add"
],
"*.md": [
"npm run lint:md -- -o",
"git add"
]
"linters": {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had trouble with lint-staged trying to git add multiple things in parallel, which fails because git's lockfile would exist.

I disabled concurrency for this reason. Depending on the amount of files in your stage, this will make the process a second or 2 slower, but git add is reliable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ndelangen seems like this is a separate PR?

"*.js": [
"npm run lint:js -- --fix",
"git add"
],
"*.json": [
"npm run lint:js -- --fix",
"git add"
],
"*.md": [
"npm run lint:md -- -o",
"git add"
]
},
"verbose": true,
"concurrent": false
},
"pr-log": {
"skipLabels": [
Expand Down
149 changes: 149 additions & 0 deletions scripts/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env node
const inquirer = require('inquirer');
const program = require('commander');
const childProcess = require('child_process');
const chalk = require('chalk');
const log = require('npmlog');

const { lstatSync, readdirSync } = require('fs');
const { join } = require('path');

const isTgz = source => lstatSync(source).isFile() && source.match(/.tgz$/);
const getDirectories = source => readdirSync(source).map(name => join(source, name)).filter(isTgz);

log.heading = 'storybook';
const prefix = 'bootstrap';

const spawn = command =>
childProcess.spawnSync(`${command}`, {
shell: true,
stdio: 'inherit',
});

const main = program
.version('3.0.0')
.option('--all', `Bootstrap everything ${chalk.gray('(all)')}`);

const createTask = ({ defaultValue, option, name, check = () => true, command, pre = [] }) => ({
value: false,
defaultValue: defaultValue || false,
option: option || undefined,
name: name || 'unnamed task',
check: check || (() => true),
command: () => {
// run all pre tasks
// eslint-disable-next-line no-use-before-define
pre.map(key => tasks[key]).forEach(task => {
if (!task.check()) {
task.command();
}
});

log.info(prefix, name);
command();
},
});

const tasks = {
reset: createTask({
name: `Clean and re-install root dependencies ${chalk.red('(reset)')}`,
defaultValue: false,
option: '--reset',
command: () => {
log.info(prefix, 'git clean');
spawn('git clean -fdx');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about just running lerna clean instead of git clean -fdx which is much more destructive?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be completely destructive to anything not managed by git. Anything added not known by or ignored by git should be removed. The desired end-result is as if you just cloned the repo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, git clean -fdx breaks my IDE setup each time

Copy link
Member Author

@ndelangen ndelangen Aug 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Hypnosphi Can you give me a list / regexp that you IDE adds that should NOT be cleaned away?
https://git-scm.com/docs/git-clean#git-clean--eltpatterngt

log.info(prefix, 'yarn install');
spawn('yarn install --no-lockfile');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no lockfile? i think yarn's lockfiles work pretty well cc @Hypnosphi

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're currently ignoring them, so not generating them in the first place is better.

Let's discuss enabling yarn lockfiles outside this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do it: #1703

},
}),
core: createTask({
name: `Core & Examples ${chalk.gray('(core)')}`,
defaultValue: true,
option: '--core',
command: () => {
spawn('yarn bootstrap:core');
},
}),
docs: createTask({
name: `Documentation ${chalk.gray('(docs)')}`,
defaultValue: false,
option: '--docs',
command: () => {
spawn('yarn bootstrap:docs');
},
}),
packs: createTask({
name: `Build tarballs of packages ${chalk.gray('(build-packs)')}`,
defaultValue: false,
option: '--packs',
command: () => {
spawn('yarn build-packs');
},
check: () => getDirectories(join(__dirname, '..', 'packs')).length > 0,
}),
'react-native-vanilla': createTask({
name: `React-Native example ${chalk.gray('(react-native-vanilla)')}`,
defaultValue: false,
option: '--reactnative',
pre: ['packs'],
command: () => {
spawn('yarn bootstrap:react-native-vanilla');
},
}),
'crna-kitchen-sink': createTask({
name: `React-Native-App example ${chalk.gray('(crna-kitchen-sink)')}`,
defaultValue: false,
option: '--reactnativeapp',
pre: ['packs'],
command: () => {
spawn('yarn bootstrap:crna-kitchen-sink');
},
}),
};

Object.keys(tasks)
.reduce((acc, key) => acc.option(tasks[key].option, tasks[key].name), main)
.parse(process.argv);

Object.keys(tasks).forEach(key => {
tasks[key].value = program[tasks[key].option.replace('--', '')] || program.all;
});

let selection;
if (!Object.keys(tasks).map(key => tasks[key].value).filter(Boolean).length) {
selection = inquirer
.prompt([
{
type: 'checkbox',
message: 'Select which packages to bootstrap',
name: 'todo',
choices: Object.keys(tasks).map(key => ({
name: tasks[key].name,
checked: tasks[key].defaultValue,
})),
},
])
.then(answers =>
answers.todo.map(name => tasks[Object.keys(tasks).find(i => tasks[i].name === name)])
);
} else {
selection = Promise.resolve(
Object.keys(tasks).map(key => tasks[key]).filter(item => item.value === true)
);
}

selection.then(list => {
if (list.length === 0) {
log.warn(prefix, 'Nothing to bootstrap');
} else {
list.forEach(key => {
key.command();
});
process.stdout.write('\x07');
try {
spawn('say "Bootstrapping sequence complete"');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWESOME 💯

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, I'm actually concerned this will be annoying to linux and windows users, will have to ask @usulpro maybe?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't it just fail silently on those platforms?

} catch (e) {
// discard error
}
}
});
4 changes: 2 additions & 2 deletions scripts/hoist-internals.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ const task = getLernaPackages()

task
.then(packages => {
log.info(prefix, packages.map(dir => dir.replace(cwd, '')).join(',\n'));
log.success(prefix, 'complete');
log.verbose(prefix, packages.map(dir => dir.replace(cwd, '')).join(',\n'));
log.success(prefix, `Hoisted ${packages.length} packages`);
})
.catch(error => {
log.error(prefix, 'failed', error);
Expand Down