start-command 0.24.3 → 0.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/package.json +1 -1
- package/src/bin/cli.js +4 -0
- package/src/lib/docker-utils.js +16 -0
- package/src/lib/isolation.js +1 -1
- package/test/isolation.test.js +3 -1
- package/test/regression-84.test.js +46 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# start-command
|
|
2
2
|
|
|
3
|
+
## 0.24.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6f45c9c: fix: show helpful error message when Docker is not installed (issue #84)
|
|
8
|
+
|
|
9
|
+
When running `$ --isolated docker -- bash` and Docker is not installed on the
|
|
10
|
+
machine (not just "not running"), `start-command` now prints a clear error
|
|
11
|
+
message to stderr:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Error: Docker is not installed. Install Docker from https://docs.docker.com/get-docker/
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Previously the command exited silently with code 1, giving no indication of
|
|
18
|
+
why it failed. The user had to manually run `which docker` to discover that
|
|
19
|
+
Docker was not installed at all.
|
|
20
|
+
|
|
21
|
+
Also adds `isDockerInstalled()` to `docker-utils.js` to distinguish between
|
|
22
|
+
"Docker CLI not found" and "Docker CLI found but daemon not running", and
|
|
23
|
+
exposes it via the module exports for use in tests.
|
|
24
|
+
|
|
3
25
|
## 0.24.3
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/package.json
CHANGED
package/src/bin/cli.js
CHANGED
|
@@ -591,6 +591,10 @@ async function runWithIsolation(
|
|
|
591
591
|
result.exitCode !== undefined ? result.exitCode : result.success ? 0 : 1;
|
|
592
592
|
const endTime = getTimestamp();
|
|
593
593
|
|
|
594
|
+
// Print failure message to stderr so user sees why isolation failed (e.g. Docker not installed)
|
|
595
|
+
if (!result.success && result.message) {
|
|
596
|
+
console.error(`Error: ${result.message}`);
|
|
597
|
+
}
|
|
594
598
|
// Add result to log content
|
|
595
599
|
logContent += `${result.message}\n`;
|
|
596
600
|
logContent += createLogFooter(endTime, exitCode);
|
package/src/lib/docker-utils.js
CHANGED
|
@@ -151,6 +151,21 @@ function dockerPullImage(image) {
|
|
|
151
151
|
return { success, output };
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Check if the Docker CLI is installed (command exists, regardless of daemon state)
|
|
156
|
+
* @returns {boolean} True if the docker command is found on PATH
|
|
157
|
+
*/
|
|
158
|
+
function isDockerInstalled() {
|
|
159
|
+
try {
|
|
160
|
+
const isWindows = process.platform === 'win32';
|
|
161
|
+
const checkCmd = isWindows ? 'where' : 'which';
|
|
162
|
+
execSync(`${checkCmd} docker`, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
163
|
+
return true;
|
|
164
|
+
} catch {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
154
169
|
/**
|
|
155
170
|
* Check if Docker is available (command exists and daemon is running)
|
|
156
171
|
* @returns {boolean} True if Docker is available
|
|
@@ -203,6 +218,7 @@ module.exports = {
|
|
|
203
218
|
getDefaultDockerImage,
|
|
204
219
|
dockerImageExists,
|
|
205
220
|
dockerPullImage,
|
|
221
|
+
isDockerInstalled,
|
|
206
222
|
isDockerAvailable,
|
|
207
223
|
canRunLinuxDockerImages,
|
|
208
224
|
};
|
package/src/lib/isolation.js
CHANGED
|
@@ -723,7 +723,7 @@ function runInDocker(command, options = {}) {
|
|
|
723
723
|
success: false,
|
|
724
724
|
containerName: null,
|
|
725
725
|
message:
|
|
726
|
-
'
|
|
726
|
+
'Docker is not installed. Install Docker from https://docs.docker.com/get-docker/',
|
|
727
727
|
});
|
|
728
728
|
}
|
|
729
729
|
|
package/test/isolation.test.js
CHANGED
|
@@ -262,7 +262,9 @@ describe('Isolation Runner Error Handling', () => {
|
|
|
262
262
|
detached: true,
|
|
263
263
|
});
|
|
264
264
|
assert.strictEqual(result.success, false);
|
|
265
|
-
assert.ok(
|
|
265
|
+
assert.ok(
|
|
266
|
+
result.message.toLowerCase().includes('docker is not installed')
|
|
267
|
+
);
|
|
266
268
|
});
|
|
267
269
|
|
|
268
270
|
it('should require image option', async () => {
|
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
const { describe, it } = require('node:test');
|
|
27
27
|
const assert = require('assert');
|
|
28
28
|
const { isInteractiveShellCommand } = require('../src/lib/isolation');
|
|
29
|
-
const {
|
|
29
|
+
const {
|
|
30
|
+
isDockerAvailable,
|
|
31
|
+
isDockerInstalled,
|
|
32
|
+
} = require('../src/lib/docker-utils');
|
|
30
33
|
|
|
31
34
|
// Helper: mirrors the command-args construction logic used in
|
|
32
35
|
// runInDocker attached mode.
|
|
@@ -223,6 +226,48 @@ describe('Docker daemon availability check (issue #84)', () => {
|
|
|
223
226
|
});
|
|
224
227
|
});
|
|
225
228
|
|
|
229
|
+
describe('Docker not installed check (issue #84)', () => {
|
|
230
|
+
// Verifies that isDockerInstalled returns a boolean and that the error
|
|
231
|
+
// message shown when Docker is not installed is helpful and actionable.
|
|
232
|
+
// This covers the case reported in the latest comment: user ran
|
|
233
|
+
// `$ --isolated docker -- bash` and got a silent exit code 1 because
|
|
234
|
+
// Docker was not installed; no helpful error was shown.
|
|
235
|
+
|
|
236
|
+
it('isDockerInstalled should return a boolean', () => {
|
|
237
|
+
const result = isDockerInstalled();
|
|
238
|
+
assert.strictEqual(
|
|
239
|
+
typeof result,
|
|
240
|
+
'boolean',
|
|
241
|
+
'isDockerInstalled() must return a boolean'
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('runInDocker error message for missing docker binary should be actionable', () => {
|
|
246
|
+
// Mirrors the message in runInDocker when isDockerInstalled() returns false.
|
|
247
|
+
const message =
|
|
248
|
+
'Docker is not installed. Install Docker from https://docs.docker.com/get-docker/';
|
|
249
|
+
assert.ok(
|
|
250
|
+
message.toLowerCase().includes('not installed'),
|
|
251
|
+
'Message must indicate Docker is not installed'
|
|
252
|
+
);
|
|
253
|
+
assert.ok(
|
|
254
|
+
message.includes('https://docs.docker.com/get-docker/'),
|
|
255
|
+
'Message must include an installation URL'
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('isDockerInstalled should return false consistently when docker binary is absent (mock)', () => {
|
|
260
|
+
// We test the logic directly: isDockerInstalled uses "which docker" (or "where" on Windows).
|
|
261
|
+
// This is a logic/contract test — isDockerInstalled must return false if the command fails.
|
|
262
|
+
// Real environment result is also checked above; here we verify the return type contract.
|
|
263
|
+
const installed = isDockerInstalled();
|
|
264
|
+
assert.ok(
|
|
265
|
+
installed === true || installed === false,
|
|
266
|
+
'isDockerInstalled() must return exactly true or false'
|
|
267
|
+
);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
226
271
|
describe('Post-fix regression hint: --norc suggestion (issue #84)', () => {
|
|
227
272
|
// These tests verify the hint logic that recommends --norc when a bare shell
|
|
228
273
|
// exits quickly with code 1 (e.g., broken .bashrc in konard/sandbox image).
|