From ed311d0cd4aeb44f6c6015a15bff1d2bdb6e3618 Mon Sep 17 00:00:00 2001 From: Richard Herrera Date: Thu, 30 Mar 2017 16:39:04 -0700 Subject: [PATCH 1/6] feat: Allow users to serve Storybook over HTTPS --- dist/server/index.js | 36 +++++++++++++++++++++++++++++++++--- src/server/index.js | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/dist/server/index.js b/dist/server/index.js index 3e97f6f72280..a8770b1da862 100755 --- a/dist/server/index.js +++ b/dist/server/index.js @@ -1,10 +1,16 @@ #!/usr/bin/env node 'use strict'; +var _server; + var _express = require('express'); var _express2 = _interopRequireDefault(_express); +var _https = require('https'); + +var _https2 = _interopRequireDefault(_https); + var _serveFavicon = require('serve-favicon'); var _serveFavicon2 = _interopRequireDefault(_serveFavicon); @@ -47,7 +53,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var logger = console; -_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); +_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Required with --https)').option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); logger.info(_chalk2.default.bold(_package2.default.name + ' v' + _package2.default.version + '\n')); @@ -84,6 +90,30 @@ if (_commander2.default.host) { } var app = (0, _express2.default)(); +var server = app; + +if (_commander2.default.https) { + if (!_commander2.default.sslCa) { + logger.error('Error: --ssl-ca is required with --https'); + process.exit(-1); + } + if (!_commander2.default.sslCert) { + logger.error('Error: --ssl-cert is required with --https'); + process.exit(-1); + } + if (!_commander2.default.sslKey) { + logger.error('Error: --ssl-key is required with --https'); + process.exit(-1); + } + + var sslOptions = { + ca: _fs2.default.readFileSync(_commander2.default.sslCa, 'utf-8'), + cert: _fs2.default.readFileSync(_commander2.default.sslCert, 'utf-8'), + key: _fs2.default.readFileSync(_commander2.default.sslKey, 'utf-8') + }; + + server = _https2.default.createServer(sslOptions, app); +} var hasCustomFavicon = false; @@ -126,11 +156,11 @@ process.env.STORYBOOK_GIT_BRANCH = process.env.STORYBOOK_GIT_BRANCH || exec('git // `getBaseConfig` function which is called inside the middleware app.use((0, _middleware2.default)(configDir)); -app.listen.apply(app, listenAddr.concat([function (error) { +(_server = server).listen.apply(_server, listenAddr.concat([function (error) { if (error) { throw error; } else { - var address = 'http://' + (_commander2.default.host || 'localhost') + ':' + _commander2.default.port + '/'; + var address = 'http' + (_commander2.default.https ? 's' : '') + '://' + (_commander2.default.host || 'localhost') + ':' + _commander2.default.port + '/'; logger.info('\nReact Storybook started on => ' + _chalk2.default.cyan(address) + '\n'); (0, _track_usage.track)(); } diff --git a/src/server/index.js b/src/server/index.js index be08194add7a..a102b799bad1 100755 --- a/src/server/index.js +++ b/src/server/index.js @@ -1,6 +1,7 @@ #!/usr/bin/env node import express from 'express'; +import https from 'https'; import favicon from 'serve-favicon'; import program from 'commander'; import path from 'path'; @@ -23,6 +24,10 @@ program .option('-s, --static-dir ', 'Directory where to load static files from') .option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from') .option('--dont-track', 'Do not send anonymous usage stats.') + .option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.') + .option('--ssl-ca ', 'Provide an SSL certificate authority. (Required with --https)') + .option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)') + .option('--ssl-key ', 'Provide an SSL key. (Required with --https)') .option('-d, --db-path [db-file]', 'DEPRECATED!') .option('--enable-db', 'DEPRECATED!') .parse(process.argv); @@ -66,6 +71,30 @@ if (program.host) { } const app = express(); +let server = app; + +if (program.https) { + if (!program.sslCa) { + logger.error('Error: --ssl-ca is required with --https'); + process.exit(-1); + } + if (!program.sslCert) { + logger.error('Error: --ssl-cert is required with --https'); + process.exit(-1); + } + if (!program.sslKey) { + logger.error('Error: --ssl-key is required with --https'); + process.exit(-1); + } + + const sslOptions = { + ca: fs.readFileSync(program.sslCa, 'utf-8'), + cert: fs.readFileSync(program.sslCert, 'utf-8'), + key: fs.readFileSync(program.sslKey, 'utf-8'), + }; + + server = https.createServer(sslOptions, app); +} let hasCustomFavicon = false; @@ -106,11 +135,11 @@ process.env.STORYBOOK_GIT_BRANCH = process.env.STORYBOOK_GIT_BRANCH || exec('git // `getBaseConfig` function which is called inside the middleware app.use(storybook(configDir)); -app.listen(...listenAddr, function (error) { +server.listen(...listenAddr, function (error) { if (error) { throw error; } else { - const address = `http://${program.host || 'localhost'}:${program.port}/`; + const address = `http${program.https ? 's' : ''}://${program.host || 'localhost'}:${program.port}/`; logger.info(`\nReact Storybook started on => ${chalk.cyan(address)}\n`); track(); } From 7885565111c663b4a2e4104b7354a63cd85774f1 Mon Sep 17 00:00:00 2001 From: Richard Herrera Date: Sun, 2 Apr 2017 09:44:50 -0700 Subject: [PATCH 2/6] refactor: provide ca value as Array Per the Node docs, the `ca` value should be an Array: https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener --- dist/server/index.js | 12 ++++++------ src/server/index.js | 8 ++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/dist/server/index.js b/dist/server/index.js index a8770b1da862..f6cde7cecf48 100755 --- a/dist/server/index.js +++ b/dist/server/index.js @@ -53,7 +53,9 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var logger = console; -_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Required with --https)').option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); +_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', function (val) { + return val.split(); +}).option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); logger.info(_chalk2.default.bold(_package2.default.name + ' v' + _package2.default.version + '\n')); @@ -93,10 +95,6 @@ var app = (0, _express2.default)(); var server = app; if (_commander2.default.https) { - if (!_commander2.default.sslCa) { - logger.error('Error: --ssl-ca is required with --https'); - process.exit(-1); - } if (!_commander2.default.sslCert) { logger.error('Error: --ssl-cert is required with --https'); process.exit(-1); @@ -107,7 +105,9 @@ if (_commander2.default.https) { } var sslOptions = { - ca: _fs2.default.readFileSync(_commander2.default.sslCa, 'utf-8'), + ca: _commander2.default.sslCa.map(function (ca) { + return _fs2.default.readFileSync(ca, 'utf-8'); + }), cert: _fs2.default.readFileSync(_commander2.default.sslCert, 'utf-8'), key: _fs2.default.readFileSync(_commander2.default.sslKey, 'utf-8') }; diff --git a/src/server/index.js b/src/server/index.js index a102b799bad1..2bff61a20847 100755 --- a/src/server/index.js +++ b/src/server/index.js @@ -25,7 +25,7 @@ program .option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from') .option('--dont-track', 'Do not send anonymous usage stats.') .option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.') - .option('--ssl-ca ', 'Provide an SSL certificate authority. (Required with --https)') + .option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', val => val.split()) .option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)') .option('--ssl-key ', 'Provide an SSL key. (Required with --https)') .option('-d, --db-path [db-file]', 'DEPRECATED!') @@ -74,10 +74,6 @@ const app = express(); let server = app; if (program.https) { - if (!program.sslCa) { - logger.error('Error: --ssl-ca is required with --https'); - process.exit(-1); - } if (!program.sslCert) { logger.error('Error: --ssl-cert is required with --https'); process.exit(-1); @@ -88,7 +84,7 @@ if (program.https) { } const sslOptions = { - ca: fs.readFileSync(program.sslCa, 'utf-8'), + ca: program.sslCa.map(ca => fs.readFileSync(ca, 'utf-8')), cert: fs.readFileSync(program.sslCert, 'utf-8'), key: fs.readFileSync(program.sslKey, 'utf-8'), }; From b52b51a7e515cb9bae99e6fe14f50e496bcd2acc Mon Sep 17 00:00:00 2001 From: Richard Herrera Date: Sun, 2 Apr 2017 10:34:54 -0700 Subject: [PATCH 3/6] refactor: handle optional sslCa argument --- dist/server/index.js | 7 ++----- src/server/index.js | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dist/server/index.js b/dist/server/index.js index f6cde7cecf48..64e5d4a223b7 100755 --- a/dist/server/index.js +++ b/dist/server/index.js @@ -52,10 +52,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var logger = console; - -_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', function (val) { - return val.split(); -}).option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); +_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', _utils.parseList).option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); logger.info(_chalk2.default.bold(_package2.default.name + ' v' + _package2.default.version + '\n')); @@ -105,7 +102,7 @@ if (_commander2.default.https) { } var sslOptions = { - ca: _commander2.default.sslCa.map(function (ca) { + ca: (_commander2.default.sslCa || []).map(function (ca) { return _fs2.default.readFileSync(ca, 'utf-8'); }), cert: _fs2.default.readFileSync(_commander2.default.sslCert, 'utf-8'), diff --git a/src/server/index.js b/src/server/index.js index 2bff61a20847..559ff99832f1 100755 --- a/src/server/index.js +++ b/src/server/index.js @@ -25,7 +25,7 @@ program .option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from') .option('--dont-track', 'Do not send anonymous usage stats.') .option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.') - .option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', val => val.split()) + .option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', parseList) .option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)') .option('--ssl-key ', 'Provide an SSL key. (Required with --https)') .option('-d, --db-path [db-file]', 'DEPRECATED!') @@ -84,7 +84,7 @@ if (program.https) { } const sslOptions = { - ca: program.sslCa.map(ca => fs.readFileSync(ca, 'utf-8')), + ca: (program.sslCa || []).map(ca => fs.readFileSync(ca, 'utf-8')), cert: fs.readFileSync(program.sslCert, 'utf-8'), key: fs.readFileSync(program.sslKey, 'utf-8'), }; From ad3ff2345d8f2858808517618058a6765fe68d84 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 5 Apr 2017 14:30:22 +1000 Subject: [PATCH 4/6] Issue Triage instructions --- CONTRIBUTING.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed1e3ceb0638..86c59f0031c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,6 +52,35 @@ We welcome your contributions. There are many ways you can help us. This is few Before you submit a new PR, make you to run `npm test`. Do not submit a PR if tests are failing. If you need any help, create an issue and ask. +## Issue Triage + +If you are looking for a way to help the project, triaging issues is a great place to start. Here's how you can help: + +### Responding to issues + +Issues that are tagged `question` or `requires-reproduction` are great places to help. If you can answer a question, it will help the asker as well as anyone searching. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using the [technique above](https://github.com/storybooks/react-storybook/blob/master/CONTRIBUTING.md#reproductions). + +### Triaging issues + +Once you've helped out on a few issues, if you'd like triage access, you can help label issues, and respond to reporters. New issues should be labelled as one of `bug`, `enhancement`, `question` or `discussion`. + +If an issue is a `bug`, if it doesn't have a clear reproduction that you have personally confirmed, mark it `requires-reproduction` and ask the author to try and create a reproduction, or have a go yourself, if you can. + +### 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 off line, it is reasonable to wait 2 weeks before closing). + +- `bug`s should be closed when the issue is fixed and merged to `master` + +- `enhancement`s should be closed when merged or if the feature is deemed to be not appropriate. + +- `question`s should be closed when the question has been answered. If the questioner drops off line, a reasonable period to wait is two weeks. + +- `discussion`s should be closed at a maintainer's discretion. + + ## Development Guide > If you want to work on a UI feature, refer to the [Storybook UI](https://github.com/kadirahq/storybook-ui) project. @@ -95,3 +124,4 @@ npm link @kadira/storybook ### Getting Changes After you've done any change, you need to run the `npm run storybook` command everytime to see those changes. + From 919155103855f623bb42f6fa81a0665013fa47ee Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 5 Apr 2017 15:30:42 +1000 Subject: [PATCH 5/6] Small changes as per @ndelangen --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86c59f0031c0..3994ec6c6cf1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,13 +58,13 @@ If you are looking for a way to help the project, triaging issues is a great pla ### Responding to issues -Issues that are tagged `question` or `requires-reproduction` are great places to help. If you can answer a question, it will help the asker as well as anyone searching. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using the [technique above](https://github.com/storybooks/react-storybook/blob/master/CONTRIBUTING.md#reproductions). +Issues that are tagged `question` or `requires-reproduction` are great places to help. If you can answer a question, it will help the asker as well as anyone searching. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using [this technique](https://github.com/storybooks/react-storybook/blob/master/CONTRIBUTING.md#reproductions). ### Triaging issues Once you've helped out on a few issues, if you'd like triage access, you can help label issues, and respond to reporters. New issues should be labelled as one of `bug`, `enhancement`, `question` or `discussion`. -If an issue is a `bug`, if it doesn't have a clear reproduction that you have personally confirmed, mark it `requires-reproduction` and ask the author to try and create a reproduction, or have a go yourself, if you can. +If an issue is a `bug`, and it doesn't have a clear reproduction that you have personally confirmed, label it `requires-reproduction` and ask the author to try and create a reproduction, or have a go yourself. ### Closing issues From 3629275142b52e689bd6af3daa1873fbe7096d01 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Mon, 10 Apr 2017 14:06:07 +1000 Subject: [PATCH 6/6] Update to reflect labels in use --- CONTRIBUTING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3994ec6c6cf1..bbd5a97ee98a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,25 +58,25 @@ If you are looking for a way to help the project, triaging issues is a great pla ### Responding to issues -Issues that are tagged `question` or `requires-reproduction` are great places to help. If you can answer a question, it will help the asker as well as anyone searching. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using [this technique](https://github.com/storybooks/react-storybook/blob/master/CONTRIBUTING.md#reproductions). +Issues that are tagged `question / support` or `needs reproduction` are great places to help. If you can answer a question, it will help the asker as well as anyone searching. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using [this technique](https://github.com/storybooks/react-storybook/blob/master/CONTRIBUTING.md#reproductions). ### Triaging issues -Once you've helped out on a few issues, if you'd like triage access, you can help label issues, and respond to reporters. New issues should be labelled as one of `bug`, `enhancement`, `question` or `discussion`. +Once you've helped out on a few issues, if you'd like triage access, you can help label issues, and respond to reporters. New issues should be labelled as one of `bug`, `new feature`, `question / support` or `discussion`. -If an issue is a `bug`, and it doesn't have a clear reproduction that you have personally confirmed, label it `requires-reproduction` and ask the author to try and create a reproduction, or have a go yourself. +If an issue is a `bug`, and it doesn't have a clear reproduction that you have personally confirmed, label it `needs reproduction` and ask the author to try and create a reproduction, or have a go yourself. ### 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 off line, 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 closed when the issue is fixed and merged to `master` -- `enhancement`s should be closed when merged or if the feature is deemed to be not appropriate. +- `new feature`s should be closed when merged or if the feature is deemed to be not appropriate. -- `question`s should be closed when the question has been answered. If the questioner drops off line, a reasonable period to wait is two weeks. +- `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.