-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Expand file tree
/
Copy pathdocker.ts
More file actions
68 lines (60 loc) · 2.19 KB
/
Copy pathdocker.ts
File metadata and controls
68 lines (60 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import { spawnSync } from 'node:child_process'
import { SetupError } from './errors.ts'
import { waitFor } from './probes.ts'
import * as p from './prompter.ts'
import { glyph, theme } from './theme.ts'
const INSTALL_HINTS = [
'install Docker Desktop: https://docker.com/products/docker-desktop',
`or OrbStack (lighter on macOS): ${theme.command('brew install orbstack')}`,
]
function daemonUp(): boolean {
return spawnSync('docker', ['info'], { stdio: 'ignore' }).status === 0
}
function installed(): boolean {
// Bun.which resolves PATH cross-platform (incl. PATHEXT on Windows); `which`
// is not a standard Windows command.
return Bun.which('docker') !== null
}
/**
* Returns whether the Docker daemon is available, offering to launch Docker
* Desktop (macOS) when it's installed but stopped. Never installs anything.
* With required=true, unavailability is a SetupError instead of false.
*/
export async function ensureDocker(required: boolean): Promise<boolean> {
if (daemonUp()) return true
if (!installed()) {
if (required) throw new SetupError('Docker is not installed.', INSTALL_HINTS)
return false
}
if (process.platform !== 'darwin') {
if (required) {
throw new SetupError('Docker is installed but the daemon is not running.', [
`start it: ${theme.command('sudo systemctl start docker')} (Linux)`,
])
}
return false
}
const launch = await p.confirm({
message: 'Docker is installed but not running — start Docker Desktop now?',
initialValue: true,
})
if (!launch) {
if (required) {
throw new SetupError('Docker is required for this mode.', [
'start Docker Desktop, then re-run the wizard',
])
}
return false
}
spawnSync('open', ['-a', 'Docker'], { stdio: 'ignore' })
const spin = p.spinner()
spin.start('Waiting for the Docker daemon…')
const up = await waitFor(async () => daemonUp(), 90_000, 2000)
spin.stop(up ? 'Docker is running' : `${glyph.fail} daemon did not come up`)
if (!up) {
throw new SetupError('Docker Desktop did not start within 90s.', [
'first-ever launch needs a GUI license acceptance — open Docker Desktop manually once, then re-run',
])
}
return true
}