Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/sim-setup/src/lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
composeServiceQuery,
composeServiceState,
type Install,
noInstallHint,
serviceStatusRows,
} from './lifecycle'

Expand Down Expand Up @@ -131,3 +132,19 @@ describe('status service rows', () => {
])
})
})

describe('no-install hint', () => {
it('blames Docker, not the install, when Docker is unreachable', () => {
const lines = noInstallHint({ dockerReachable: false, cwd: '/home/dev' })
expect(lines.join(' ')).toContain('Docker is not reachable')
expect(lines.join(' ')).not.toContain('npx sim-setup')
})

it('points an existing user at the sim/ folder or --dir before suggesting setup', () => {
const lines = noInstallHint({ dockerReachable: true, cwd: '/home/dev' })
expect(lines[0]).toContain('/home/dev')
expect(lines[1]).toContain('--dir')
expect(lines[2]).toContain('kubectl')
expect(lines[3]).toContain('npx sim-setup')
})
})
35 changes: 29 additions & 6 deletions packages/sim-setup/src/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,27 @@ function describeInstall(install: Install): string {
return `Kubernetes (context ${install.context}${scope})`
}

/**
* What to say when no install was found. "Run npx sim-setup" reads as "install
* again", which is wrong in the two common cases: Docker is down (a Compose
* stack is invisible, not missing), or the stack was taken `down` and the
* command runs outside its directory, where only `--dir` can find it.
*/
export function noInstallHint(options: { dockerReachable: boolean; cwd: string }): string[] {
if (!options.dockerReachable) {
return [
'Docker is not reachable, so a Compose install cannot be detected.',
'Start Docker (Docker Desktop or OrbStack, or the docker service on Linux), then re-run this command.',
]
}
return [
`No Sim install found from ${options.cwd}.`,
`Docker Compose install? Run this from the folder that contains your sim/ directory, or pass ${theme.command('--dir <path-to-sim>')}.`,
'Kubernetes install? Check that your current kubectl context is the one Sim was installed in.',
`New here? Run ${theme.command('npx sim-setup')}.`,
Comment thread
AYANscyy2 marked this conversation as resolved.
]
}

/** One install → use it; several → let the user pick; none → null. */
async function resolveInstall(installs: Install[]): Promise<Install | null> {
if (installs.length <= 1) return installs[0] ?? null
Expand Down Expand Up @@ -656,11 +677,13 @@ async function status(): Promise<void> {
console.log(` ${theme.muted('start Docker Desktop (or OrbStack), then re-run this.')}\n`)
}
if (installs.length === 0) {
console.log(
docker
? ` ${glyph.warn} No Sim install detected — run ${theme.command('npx sim-setup')}.`
: ` ${glyph.warn} No install detected, but that may just be Docker being down.`
)
if (!docker) {
console.log(` ${glyph.warn} No install detected, but that may just be Docker being down.`)
return
}
const [first, ...rest] = noInstallHint({ dockerReachable: true, cwd: process.cwd() })
console.log(` ${glyph.warn} ${first}`)
for (const line of rest) console.log(` ${theme.muted(line)}`)
return
}
for (const install of installs) console.log(` ${glyph.pass} ${describeInstall(install)}`)
Expand Down Expand Up @@ -696,7 +719,7 @@ export async function runLifecycle(command: LifecycleCommand): Promise<void> {

const install = await resolveInstall(installs)
if (!install) {
p.log.warn(`No Sim install detected. Run ${theme.command('npx sim-setup')} first.`)
p.log.warn(noInstallHint({ dockerReachable: dockerReachable(), cwd: process.cwd() }).join('\n'))
return
}
switch (command) {
Expand Down