1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | const childProcess = require('child_process')
|
7 | const flow = require('flow-bin')
|
8 | const fs = require('fs')
|
9 | const {join} = require('path')
|
10 |
|
11 | const execFile = (file, args) =>
|
12 | new Promise((resolve, reject) => {
|
13 | childProcess.execFile(
|
14 | file,
|
15 | args,
|
16 | {
|
17 | maxBuffer: Infinity
|
18 | },
|
19 | (error, stdout, stderr) => {
|
20 | if (error) {
|
21 | reject(error)
|
22 | } else {
|
23 | resolve({stdout, stderr})
|
24 | }
|
25 | }
|
26 | )
|
27 | })
|
28 |
|
29 | async function execFileJSON(file, args) {
|
30 | args.push('--json')
|
31 | const {stdout, stderr} = await execFile(file, args)
|
32 | if (stderr) {
|
33 | return JSON.parse(stderr)
|
34 | } else {
|
35 | return JSON.parse(stdout)
|
36 | }
|
37 | }
|
38 |
|
39 | function computeCoverage(covered, uncovered) {
|
40 | const total = covered + uncovered
|
41 | if (total) {
|
42 | return 100 * (covered / total)
|
43 | } else {
|
44 | return 100
|
45 | }
|
46 | }
|
47 |
|
48 | async function getCoverage(path) {
|
49 | const json = await execFileJSON(flow, ['coverage', path])
|
50 | if (json && json.expressions) {
|
51 | const uncoveredCount = json.expressions['uncovered_count']
|
52 | const coveredCount = json.expressions['covered_count']
|
53 | const covered = computeCoverage(coveredCount, uncoveredCount)
|
54 | return {path, uncoveredCount, coveredCount, covered}
|
55 | } else {
|
56 | return {path, uncoveredCount: 0, coveredCount: 0, covered: 0}
|
57 | }
|
58 | }
|
59 |
|
60 | async function startFlow() {
|
61 | try {
|
62 | await execFile(flow, ['start', '--wait'])
|
63 | } catch (error) {
|
64 | if (error.code === 11) {
|
65 |
|
66 | } else {
|
67 | throw error
|
68 | }
|
69 | }
|
70 | }
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | async function grepFlowFiles() {
|
82 | const {stdout} = await execFile('git', ['grep', '--null', '--name-only', '--', '@flow'])
|
83 | return stdout.split('\0').filter(path => path)
|
84 | }
|
85 |
|
86 | ;(async function() {
|
87 | let threshold = 0
|
88 |
|
89 | const packageJsonPath = join(process.cwd(), 'package.json')
|
90 | if (fs.existsSync(packageJsonPath)) {
|
91 | const packageJson = require(packageJsonPath)
|
92 | threshold = (packageJson.flow && packageJson.flow.coverageThreshold) || 0
|
93 | }
|
94 |
|
95 | await startFlow()
|
96 |
|
97 | const files = await grepFlowFiles()
|
98 |
|
99 | let totalCoveredCount = 0
|
100 | let totalUncoveredCount = 0
|
101 |
|
102 | for (const file of files) {
|
103 | const {path, covered, coveredCount, uncoveredCount} = await getCoverage(file)
|
104 | process.stdout.write(`${covered.toFixed()}\t${path}\n`)
|
105 | totalCoveredCount += coveredCount
|
106 | totalUncoveredCount += uncoveredCount
|
107 | }
|
108 |
|
109 | const totalCoverage = computeCoverage(totalCoveredCount, totalUncoveredCount)
|
110 |
|
111 | process.stdout.write(`${totalCoverage.toFixed()}\t(total)\n`)
|
112 | if (totalCoverage < threshold) {
|
113 | process.stderr.write(`expected at least ${threshold}% coverage, but was ${totalCoverage.toFixed()}%\n`)
|
114 | process.exit(1)
|
115 | }
|
116 | })().catch(error => {
|
117 | process.stderr.write(`${error}\n`)
|
118 | process.exit(2)
|
119 | })
|