Skip to content

Commit 40addbd

Browse files
authored
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
1 parent 40ea053 commit 40addbd

File tree

8 files changed

+147
-47
lines changed

8 files changed

+147
-47
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.DS_STORE
22
node_modules
3+
scripts/flow/*/.flowconfig
34
*~
45
*.pyc
56
.grunt
@@ -21,4 +22,4 @@ chrome-user-data
2122
*.iml
2223
.vscode
2324
*.swp
24-
*.swo
25+
*.swo

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
"linc": "node ./scripts/tasks/linc.js",
111111
"lint": "node ./scripts/tasks/eslint.js",
112112
"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",
114114
"debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source.js --runInBand",
115115
"test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
116116
"test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
[ignore]
2-
3-
<PROJECT_ROOT>/fixtures/.*
4-
<PROJECT_ROOT>/build/.*
5-
<PROJECT_ROOT>/scripts/bench/.*
2+
.*/scripts/bench/.*
63

74
# 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/.*
107

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__/.*
1714

1815
[include]
16+
../../../node_modules/
17+
../../../packages/
18+
../../../scripts/
1919

2020
[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
2324

2425
[lints]
2526
untyped-type-import=error
@@ -42,4 +43,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
4243
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
4344

4445
[version]
45-
^0.61.0
46+
^0.61.0

scripts/flow/createFlowConfigs.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
exports.typedRenderers = ['dom', 'fabric', 'native', 'test'];

scripts/tasks/flow-ci.js

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,18 @@
77

88
'use strict';
99

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+
});
1413

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

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']);
2621
}
22+
}
2723

28-
process.exit(code);
29-
});
24+
checkAll();

scripts/tasks/flow.js

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,42 @@
77

88
'use strict';
99

10-
const path = require('path');
11-
const spawn = require('child_process').spawn;
10+
process.on('unhandledRejection', err => {
11+
throw err;
12+
});
1213

13-
const extension = process.platform === 'win32' ? '.cmd' : '';
14+
const chalk = require('chalk');
15+
const runFlow = require('../flow/runFlow');
16+
const {typedRenderers} = require('../flow/typedRenderers');
1417

1518
// This script is using `flow status` for a quick check with a server.
1619
// Use it for local development.
1720

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+
}
2747

28-
process.exit(code);
29-
});
48+
runFlow(primaryRenderer, ['status']);

0 commit comments

Comments
 (0)