@samitouri / QOS-React / commits / 40addbd110

Run Flow for each renderer separately (#12846)

* Generate Flow config on install We'll need to do pre-renderer Flow passes with different configs. This is the first step to get it working. We only want the original version checked in. * Create multiple Flow configs from a template * Run Flow per renderer * Lint * Revert the environment consolidation I thought this would be a bit cleaner at first because we now have non-environment files in this directory. But Sebastian is changing these files at the same time so I want to avoid conflicts and keep the PR more tightly scoped. Undo. * Misc

Dan Abramov committed May 18, 2018 at 02:05 UTC 40addbd110335c8e900d30657fa82b06f2c89808
8 files changed +147 -47
.gitignore
+2 -1
@@ -1,5 +1,6 @@
1 .DS_STORE
2 node_modules
3 +scripts/flow/*/.flowconfig
4 *~
5 *.pyc
6 .grunt
@@ -21,4 +22,4 @@ chrome-user-data
22 *.iml
23 .vscode
24 *.swp
24 -*.swo
\ No newline at end of file
25 +*.swo
package.json
+1 -1
@@ -110,7 +110,7 @@
110 "linc": "node ./scripts/tasks/linc.js",
111 "lint": "node ./scripts/tasks/eslint.js",
112 "lint-build": "node ./scripts/rollup/validate/index.js",
113 - "postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json",
113 + "postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json && node ./scripts/flow/createFlowConfigs.js",
114 "debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source.js --runInBand",
115 "test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
116 "test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
scripts/flow/config/flowconfig renamed
+16 -15
@@ -1,25 +1,26 @@
1 [ignore]
2 -
3 -<PROJECT_ROOT>/fixtures/.*
4 -<PROJECT_ROOT>/build/.*
5 -<PROJECT_ROOT>/scripts/bench/.*
2 +.*/scripts/bench/.*
3
4 # These shims are copied into external projects:
8 -<PROJECT_ROOT>/scripts/rollup/shims/facebook-www/.*
9 -<PROJECT_ROOT>/scripts/rollup/shims/react-native/.*
5 +.*/rollup/shims/facebook-www/.*
6 +.*/rollup/shims/react-native/.*
7
11 -<PROJECT_ROOT>/.*/node_modules/y18n/.*
12 -<PROJECT_ROOT>/node_modules/chrome-devtools-frontend/.*
13 -<PROJECT_ROOT>/node_modules/devtools-timeline-model/.*
14 -<PROJECT_ROOT>/node_modules/create-react-class/.*
15 -<PROJECT_ROOT>/.*/__mocks__/.*
16 -<PROJECT_ROOT>/.*/__tests__/.*
8 +.*/node_modules/y18n/.*
9 +.*/node_modules/chrome-devtools-frontend/.*
10 +.*/node_modules/devtools-timeline-model/.*
11 +.*/node_modules/create-react-class/.*
12 +.*/__mocks__/.*
13 +.*/__tests__/.*
14
15 [include]
16 +../../../node_modules/
17 +../../../packages/
18 +../../../scripts/
19
20 [libs]
21 -./node_modules/fbjs/flow/lib/dev.js
22 -./scripts/flow
21 +../../../node_modules/fbjs/flow/lib/dev.js
22 +../environment.js
23 +../react-native-host-hooks.js
24
25 [lints]
26 untyped-type-import=error
@@ -42,4 +43,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
43 suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
44
45 [version]
45 -^0.61.0
46 +^0.61.0
\ No newline at end of file
scripts/flow/createFlowConfigs.js new
+44
@@ -0,0 +1,44 @@
1 +'use strict';
2 +
3 +const chalk = require('chalk');
4 +const fs = require('fs');
5 +const mkdirp = require('mkdirp');
6 +const {typedRenderers} = require('./typedRenderers');
7 +
8 +const config = fs.readFileSync(__dirname + '/config/flowconfig');
9 +
10 +function writeConfig(folder) {
11 + mkdirp.sync(folder);
12 +
13 + const disclaimer = `
14 +# ---------------------------------------------------------------#
15 +# NOTE: this file is generated. #
16 +# If you want to edit it, open ./scripts/flow/config/flowconfig. #
17 +# Then run Yarn for changes to take effect. #
18 +# ---------------------------------------------------------------#
19 + `.trim();
20 +
21 + const configFile = folder + '/.flowconfig';
22 + let oldConfig;
23 + try {
24 + oldConfig = fs.readFileSync(configFile).toString();
25 + } catch (err) {
26 + oldConfig = null;
27 + }
28 + const newConfig = `
29 +${disclaimer}
30 +${config}
31 +${disclaimer}
32 +`.trim();
33 +
34 + if (newConfig !== oldConfig) {
35 + fs.writeFileSync(configFile, newConfig);
36 + console.log(chalk.dim('Wrote a Flow config to ' + configFile));
37 + }
38 +}
39 +
40 +// Write multiple configs in different folders
41 +// so that we can run those checks in parallel if we want.
42 +typedRenderers.forEach(renderer => {
43 + writeConfig(__dirname + '/' + renderer);
44 +});
scripts/flow/runFlow.js new
+37
@@ -0,0 +1,37 @@
1 +'use strict';
2 +
3 +const chalk = require('chalk');
4 +const spawn = require('child_process').spawn;
5 +const extension = process.platform === 'win32' ? '.cmd' : '';
6 +
7 +require('./createFlowConfigs');
8 +
9 +async function runFlow(renderer, args) {
10 + return new Promise(resolve => {
11 + console.log(
12 + 'Running Flow for the ' + chalk.cyan(renderer) + ' renderer...',
13 + );
14 + spawn('../../../node_modules/.bin/flow' + extension, args, {
15 + // Allow colors to pass through:
16 + stdio: 'inherit',
17 + // Use a specific renderer config:
18 + cwd: process.cwd() + '/scripts/flow/' + renderer + '/',
19 + }).on('close', function(code) {
20 + if (code !== 0) {
21 + console.error(
22 + 'Flow failed for the ' + chalk.red(renderer) + ' renderer',
23 + );
24 + console.log();
25 + process.exit(code);
26 + } else {
27 + console.log(
28 + 'Flow passed for the ' + chalk.green(renderer) + ' renderer',
29 + );
30 + console.log();
31 + resolve();
32 + }
33 + });
34 + });
35 +}
36 +
37 +module.exports = runFlow;
scripts/flow/typedRenderers.js new
+3
@@ -0,0 +1,3 @@
1 +'use strict';
2 +
3 +exports.typedRenderers = ['dom', 'fabric', 'native', 'test'];
scripts/tasks/flow-ci.js
+11 -16
@@ -7,23 +7,18 @@
7
8 'use strict';
9
10 -const path = require('path');
11 -const spawn = require('child_process').spawn;
12 -
13 -const extension = process.platform === 'win32' ? '.cmd' : '';
10 +process.on('unhandledRejection', err => {
11 + throw err;
12 +});
13
15 -// This script forces a complete check.
16 -// Use it for the CI.
14 +const runFlow = require('../flow/runFlow');
15 +const {typedRenderers} = require('../flow/typedRenderers');
16
18 -spawn(path.join('node_modules', '.bin', 'flow' + extension), ['check', '.'], {
19 - // Allow colors to pass through
20 - stdio: 'inherit',
21 -}).on('close', function(code) {
22 - if (code !== 0) {
23 - console.error('Flow failed');
24 - } else {
25 - console.log('Flow passed');
17 +async function checkAll() {
18 + // eslint-disable-next-line no-for-of-loops/no-for-of-loops
19 + for (let renderer of typedRenderers) {
20 + await runFlow(renderer, ['check']);
21 }
22 +}
23
28 - process.exit(code);
29 -});
24 +checkAll();
scripts/tasks/flow.js
+33 -14
@@ -7,23 +7,42 @@
7
8 'use strict';
9
10 -const path = require('path');
11 -const spawn = require('child_process').spawn;
10 +process.on('unhandledRejection', err => {
11 + throw err;
12 +});
13
13 -const extension = process.platform === 'win32' ? '.cmd' : '';
14 +const chalk = require('chalk');
15 +const runFlow = require('../flow/runFlow');
16 +const {typedRenderers} = require('../flow/typedRenderers');
17
18 // This script is using `flow status` for a quick check with a server.
19 // Use it for local development.
20
18 -spawn(path.join('node_modules', '.bin', 'flow' + extension), ['status', '.'], {
19 - // Allow colors to pass through
20 - stdio: 'inherit',
21 -}).on('close', function(code) {
22 - if (code !== 0) {
23 - console.error('Flow failed');
24 - } else {
25 - console.log('Flow passed');
26 - }
21 +const primaryRenderer = process.argv[2];
22 +if (typedRenderers.indexOf(primaryRenderer) === -1) {
23 + console.log(
24 + 'The ' +
25 + chalk.red('yarn flow') +
26 + ' command now requires you to pick a primary renderer:'
27 + );
28 + console.log();
29 + typedRenderers.forEach(renderer => {
30 + console.log(' * ' + chalk.cyan('yarn flow ' + renderer));
31 + });
32 + console.log();
33 + console.log('If you are not sure, run ' + chalk.green('yarn flow dom') + '.');
34 + console.log(
35 + 'This will still typecheck non-DOM packages, although less precisely.'
36 + );
37 + console.log();
38 + console.log('Note that checks for all renderers will run on CI.');
39 + console.log(
40 + 'You can also do this locally with ' +
41 + chalk.cyan('yarn flow-ci') +
42 + ' but it will be slow.'
43 + );
44 + console.log();
45 + process.exit(1);
46 +}
47
28 - process.exit(code);
29 -});
48 +runFlow(primaryRenderer, ['status']);