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']);