• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

cameri / nostream / 25525980050

07 May 2026 10:40PM UTC coverage: 64.851% (-0.3%) from 65.132%
25525980050

Pull #596

github

web-flow
Merge 728f878d4 into f599b1da9
Pull Request #596: fix: docker availability precheck

1839 of 3174 branches covered (57.94%)

Branch coverage included in aggregate %.

1 of 30 new or added lines in 3 files covered. (3.33%)

2 existing lines in 2 files now uncovered.

4161 of 6078 relevant lines covered (68.46%)

19.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.8
/src/cli/utils/process.ts
1
import { spawn } from 'child_process'
2✔
2

3
export type RunOptions = {
4
  cwd?: string
5
  env?: NodeJS.ProcessEnv
6
  stdio?: 'inherit' | 'pipe'
7
  timeoutMs?: number
8
}
9

10
export type CommandResult =
11
  | { ok: true; code: number; stdout: string; stderr: string }
12
  | { ok: false; reason: 'not-found' | 'permission-denied' | 'spawn-error' | 'timeout' | 'signal'; stdout: string; stderr: string }
13

14
export const runCommand = (command: string, args: string[], options: RunOptions = {}): Promise<number> => {
2!
15
  return new Promise((resolve, reject) => {
×
16
    const child = spawn(command, args, {
×
17
      cwd: options.cwd,
18
      env: { ...process.env, ...(options.env ?? {}) },
×
19
      stdio: options.stdio ?? 'inherit',
×
20
      shell: false,
21
    })
22

23
    const timer =
24
      typeof options.timeoutMs === 'number'
×
25
        ? setTimeout(() => {
26
            child.kill('SIGTERM')
×
27
          }, options.timeoutMs)
28
        : undefined
29

30
    child.on('error', reject)
×
31
    child.on('close', (code) => {
×
32
      if (timer) {
×
33
        clearTimeout(timer)
×
34
      }
35

36
      resolve(code ?? 1)
×
37
    })
38
  })
39
}
40

41
export const runCommandWithOutput = (
2✔
42
  command: string,
43
  args: string[],
44
  options: RunOptions = {},
×
45
): Promise<CommandResult> => {
NEW
46
  return new Promise((resolve) => {
×
47
    let stdout = ''
×
48
    let stderr = ''
×
NEW
49
    let timedOut = false
×
NEW
50
    let settled = false
×
51

NEW
52
    const settle = (result: CommandResult) => {
×
NEW
53
      if (!settled) {
×
NEW
54
        settled = true
×
NEW
55
        resolve(result)
×
56
      }
57
    }
58

59
    const child = spawn(command, args, {
×
60
      cwd: options.cwd,
61
      env: { ...process.env, ...(options.env ?? {}) },
×
62
      stdio: 'pipe',
63
      shell: false,
64
    })
65

66
    const timer =
67
      typeof options.timeoutMs === 'number'
×
68
        ? setTimeout(() => {
NEW
69
            timedOut = true
×
UNCOV
70
            child.kill('SIGTERM')
×
71
          }, options.timeoutMs)
72
        : undefined
73

74
    child.stdout.on('data', (chunk) => {
×
75
      stdout += chunk.toString()
×
76
    })
77

78
    child.stderr.on('data', (chunk) => {
×
79
      stderr += chunk.toString()
×
80
    })
81

NEW
82
    child.on('error', (err: NodeJS.ErrnoException) => {
×
NEW
83
      if (timer) { clearTimeout(timer) }
×
NEW
84
      if (err.code === 'ENOENT') {
×
NEW
85
        settle({ ok: false, reason: 'not-found', stdout, stderr })
×
NEW
86
      } else if (err.code === 'EACCES') {
×
NEW
87
        settle({ ok: false, reason: 'permission-denied', stdout, stderr })
×
88
      } else {
NEW
89
        settle({ ok: false, reason: 'spawn-error', stdout, stderr })
×
90
      }
91
    })
92

NEW
93
    child.on('close', (code, signal) => {
×
NEW
94
      if (timer) { clearTimeout(timer) }
×
95

NEW
96
      if (timedOut) {
×
NEW
97
        settle({ ok: false, reason: 'timeout', stdout, stderr })
×
NEW
98
        return
×
99
      }
100

NEW
101
      if (signal !== null && code === null) {
×
NEW
102
        settle({ ok: false, reason: 'signal', stdout, stderr })
×
NEW
103
        return
×
104
      }
105

NEW
106
      settle({ ok: true, code: code ?? 1, stdout, stderr })
×
107
    })
108
  })
109
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc