start-command 0.22.0 → 0.23.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,23 @@
1
1
  # start-command
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b85d3cb: feat: Add shell auto-detection and --shell option for isolation environments
8
+
9
+ In docker and ssh isolation environments, the shell is now automatically
10
+ selected in order of preference: bash, zsh, sh (auto mode). A new `--shell`
11
+ option allows explicitly specifying the shell to use.
12
+ - Auto mode (default): probes the environment for the best available shell
13
+ - `--shell bash/zsh/sh`: forces a specific shell
14
+ - `--shell auto`: explicitly selects auto-detection mode
15
+
16
+ This enables tools like `nvm` to work correctly in Docker containers where
17
+ bash is available but sh does not source the necessary profile scripts.
18
+
19
+ Fixes #79
20
+
3
21
  ## 0.22.0
4
22
 
5
23
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "start-command",
3
- "version": "0.22.0",
3
+ "version": "0.23.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": {
package/src/bin/cli.js CHANGED
@@ -331,6 +331,7 @@ Options:
331
331
  --keep-user Keep isolated user after command completes
332
332
  --keep-alive, -k Keep isolation environment alive after command exits
333
333
  --auto-remove-docker-container Auto-remove docker container after exit
334
+ --shell <shell> Shell to use in isolation environments: auto, bash, zsh, sh (default: auto)
334
335
  --use-command-stream Use command-stream library for execution (experimental)
335
336
  --status <uuid> Show status of execution by UUID (--output-format: links-notation|json|text)
336
337
  --cleanup Clean up stale "executing" records (crashed/killed processes)
@@ -575,6 +576,7 @@ async function runWithIsolation(
575
576
  user: createdUser,
576
577
  keepAlive: options.keepAlive,
577
578
  autoRemoveDockerContainer: options.autoRemoveDockerContainer,
579
+ shell: options.shell,
578
580
  });
579
581
  } else if (createdUser) {
580
582
  // Run directly as the created user (no isolation environment)
@@ -824,4 +824,75 @@ describe('detectShellInEnvironment', () => {
824
824
  );
825
825
  console.log(` Detected shell in alpine:latest: ${result}`);
826
826
  });
827
+
828
+ it('should read shell preference from options.shell', () => {
829
+ // Test that detectShellInEnvironment respects options.shell field
830
+ const result = detectShellInEnvironment(
831
+ 'docker',
832
+ { image: 'alpine:latest', shell: 'bash' },
833
+ 'bash'
834
+ );
835
+ assert.strictEqual(result, 'bash');
836
+ });
837
+ });
838
+
839
+ describe('Shell option forwarding to isolation runners', () => {
840
+ // These tests verify that the shell option is properly forwarded
841
+ // through the call chain: cli.js -> runIsolated -> runInDocker/runInSsh
842
+
843
+ const { runInDocker, runInSsh } = require('../src/lib/isolation');
844
+
845
+ describe('runInDocker shell option', () => {
846
+ it('should accept shell option in options object', async () => {
847
+ if (!isCommandAvailable('docker')) {
848
+ console.log(' Skipping: docker not installed');
849
+ return;
850
+ }
851
+
852
+ // Test with explicit shell option - just verify the option is accepted
853
+ // and the function runs (it may fail if image is not available)
854
+ const result = await runInDocker('echo test', {
855
+ image: 'alpine:latest',
856
+ detached: true,
857
+ shell: 'sh',
858
+ });
859
+ // If docker is available, verify the result
860
+ console.log(` runInDocker with --shell sh result: ${result.success}`);
861
+ // The result can be success or failure depending on docker availability
862
+ // The important thing is no crash due to missing shell option
863
+ assert.ok(typeof result.success === 'boolean');
864
+ });
865
+ });
866
+
867
+ describe('runInSsh shell option', () => {
868
+ it('should accept shell option in options object', async () => {
869
+ // SSH requires endpoint, so without it we get expected error
870
+ const result = await runInSsh('echo test', {
871
+ detached: true,
872
+ shell: 'bash',
873
+ });
874
+ assert.strictEqual(result.success, false);
875
+ // Should fail with endpoint error, not shell option error
876
+ assert.ok(
877
+ result.message.includes('endpoint') ||
878
+ result.message.includes('--endpoint') ||
879
+ result.message.includes('SSH isolation requires')
880
+ );
881
+ });
882
+
883
+ it('should use auto mode when shell option is auto', async () => {
884
+ // Verify auto mode doesn't crash
885
+ const result = await runInSsh('echo test', {
886
+ detached: true,
887
+ shell: 'auto',
888
+ });
889
+ assert.strictEqual(result.success, false);
890
+ // Should fail with endpoint error in auto mode
891
+ assert.ok(
892
+ result.message.includes('endpoint') ||
893
+ result.message.includes('--endpoint') ||
894
+ result.message.includes('SSH isolation requires')
895
+ );
896
+ });
897
+ });
827
898
  });