start-command 0.17.4 → 0.18.0

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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # start-command
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c918e82: feat: Use OS-matched default Docker image when --image is not specified
8
+
9
+ When using `$ --isolated docker -- command`, instead of requiring the `--image` option,
10
+ the system now automatically selects an appropriate default Docker image based on the
11
+ host operating system:
12
+ - macOS/Windows: `alpine:latest` (lightweight, portable)
13
+ - Ubuntu: `ubuntu:latest`
14
+ - Debian: `debian:latest`
15
+ - Arch Linux: `archlinux:latest`
16
+ - Fedora: `fedora:latest`
17
+ - CentOS/RHEL: `centos:latest`
18
+ - Other Linux/Fallback: `alpine:latest`
19
+
20
+ This allows users to use Docker isolation with a simple command like:
21
+ `$ --isolated docker -- echo 'hi'`
22
+
23
+ Fixes #62
24
+
3
25
  ## 0.17.4
4
26
 
5
27
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-command",
3
- "version": "0.17.4",
3
+ "version": "0.18.0",
4
4
  "description": "Gamification of coding, execute any command with ability to auto-report issues on GitHub",
5
5
  "main": "src/bin/cli.js",
6
6
  "exports": {
@@ -10,7 +10,7 @@
10
10
  * --attached, -a Run in attached mode (foreground)
11
11
  * --detached, -d Run in detached mode (background)
12
12
  * --session, -s <name> Session name for isolation
13
- * --image <image> Docker image (required for docker isolation)
13
+ * --image <image> Docker image (optional, defaults to OS-matched image)
14
14
  * --endpoint <endpoint> SSH endpoint (required for ssh isolation, e.g., user@host)
15
15
  * --isolated-user, -u [username] Create isolated user with same permissions (auto-generated name if not specified)
16
16
  * --keep-user Keep isolated user after command completes (don't delete)
@@ -23,6 +23,8 @@
23
23
  * --cleanup-dry-run Show stale records that would be cleaned up (without actually cleaning)
24
24
  */
25
25
 
26
+ const { getDefaultDockerImage } = require('./docker-utils');
27
+
26
28
  // Debug mode from environment
27
29
  const DEBUG =
28
30
  process.env.START_DEBUG === '1' || process.env.START_DEBUG === 'true';
@@ -381,11 +383,9 @@ function validateOptions(options) {
381
383
  );
382
384
  }
383
385
 
384
- // Docker requires --image
386
+ // Docker uses --image or defaults to OS-matched image
385
387
  if (options.isolated === 'docker' && !options.image) {
386
- throw new Error(
387
- 'Docker isolation requires --image option to specify the container image'
388
- );
388
+ options.image = getDefaultDockerImage();
389
389
  }
390
390
 
391
391
  // SSH requires --endpoint
@@ -199,10 +199,26 @@ describe('parseArgs', () => {
199
199
  assert.strictEqual(result.wrapperOptions.image, 'alpine:latest');
200
200
  });
201
201
 
202
- it('should throw error for docker without image', () => {
203
- assert.throws(() => {
204
- parseArgs(['--isolated', 'docker', '--', 'npm', 'test']);
205
- }, /Docker isolation requires --image option/);
202
+ it('should use default OS-matched image for docker without --image', () => {
203
+ const result = parseArgs(['--isolated', 'docker', '--', 'npm', 'test']);
204
+ // Should have a default image set (OS-matched)
205
+ assert.ok(
206
+ result.wrapperOptions.image,
207
+ 'Expected default image to be set'
208
+ );
209
+ // Should be one of the known default images
210
+ const knownDefaults = [
211
+ 'alpine:latest',
212
+ 'ubuntu:latest',
213
+ 'debian:latest',
214
+ 'archlinux:latest',
215
+ 'fedora:latest',
216
+ 'centos:latest',
217
+ ];
218
+ assert.ok(
219
+ knownDefaults.includes(result.wrapperOptions.image),
220
+ `Expected image to be one of ${knownDefaults.join(', ')}, got ${result.wrapperOptions.image}`
221
+ );
206
222
  });
207
223
 
208
224
  it('should throw error for image with non-docker backend', () => {
@@ -714,13 +714,19 @@ describe('Isolation Runner with Available Backends', () => {
714
714
  });
715
715
 
716
716
  it('should pass options to backend', async () => {
717
- // Test docker without image - should fail with specific error
718
- const result = await runIsolated('docker', 'echo test', {});
719
- assert.strictEqual(result.success, false);
720
- // Either docker not installed or image required
721
- assert.ok(
722
- result.message.includes('docker') || result.message.includes('image')
723
- );
717
+ // Test docker with explicit image - should work if docker is installed
718
+ // or fail with docker-not-installed error (not image-required error)
719
+ const result = await runIsolated('docker', 'echo test', {
720
+ image: 'alpine:latest',
721
+ });
722
+ // If docker is not installed, we get a docker-related error
723
+ // If docker is installed, it might succeed or fail for other reasons
724
+ if (!result.success) {
725
+ assert.ok(
726
+ result.message.toLowerCase().includes('docker'),
727
+ `Expected docker-related error, got: ${result.message}`
728
+ );
729
+ }
724
730
  });
725
731
  });
726
732
  });