start-command 0.26.0 → 0.27.1
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 +17 -1
- package/README.md +1 -1
- package/bunfig.toml +2 -2
- package/eslint.config.mjs +1 -1
- package/package.json +2 -2
- package/src/bin/cli.js +30 -0
- package/src/lib/args-parser.js +72 -6
- package/src/lib/execution-control.js +317 -0
- package/src/lib/isolation.js +22 -4
- package/src/lib/status-formatter.js +46 -2
- package/src/lib/usage.js +5 -1
- package/test/args-parser-control.js +71 -0
- package/test/{args-parser.test.js → args-parser.js} +1 -1
- package/test/cli.js +260 -0
- package/test/create-github-release.mjs +118 -0
- package/test/docker-autoremove.js +175 -0
- package/test/execution-control.js +253 -0
- package/test/{isolation-cleanup.test.js → isolation-cleanup.js} +120 -109
- package/test/{isolation.test.js → isolation.js} +4 -2
- package/test/merge-changesets.mjs +154 -0
- package/test/publish-to-crates.mjs +194 -0
- package/test/release-name.mjs +117 -0
- package/test/{screen-integration.test.js → screen-integration.js} +1 -1
- package/test/{ssh-integration.test.js → ssh-integration.js} +1 -1
- package/test/{status-query.test.js → status-query.js} +2 -0
- package/test/{substitution.test.js → substitution.js} +1 -2
- package/test/{user-manager.test.js → user-manager.js} +17 -0
- package/test/cli.test.js +0 -218
- package/test/docker-autoremove.test.js +0 -164
- package/test/release-name.test.mjs +0 -34
- /package/test/{args-parser-shell.test.js → args-parser-shell.js} +0 -0
- /package/test/{echo-integration.test.js → echo-integration.js} +0 -0
- /package/test/{execution-store.test.js → execution-store.js} +0 -0
- /package/test/{failure-handler.test.js → failure-handler.js} +0 -0
- /package/test/{isolation-log-utils.test.js → isolation-log-utils.js} +0 -0
- /package/test/{isolation-stacking.test.js → isolation-stacking.js} +0 -0
- /package/test/{output-blocks.test.js → output-blocks.js} +0 -0
- /package/test/{public-exports.test.js → public-exports.js} +0 -0
- /package/test/{regression-84.test.js → regression-84.js} +0 -0
- /package/test/{regression-89.test.js → regression-89.js} +0 -0
- /package/test/{regression-91.test.js → regression-91.js} +0 -0
- /package/test/{sequence-parser.test.js → sequence-parser.js} +0 -0
- /package/test/{session-name-status.test.js → session-name-status.js} +0 -0
- /package/test/{version.test.js → version.js} +0 -0
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* Tests for Docker auto-remove container feature
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { describe, it } = require('node:test');
|
|
7
|
-
const assert = require('assert');
|
|
8
|
-
const { isCommandAvailable } = require('../src/lib/isolation');
|
|
9
|
-
const { runInDocker } = require('../src/lib/isolation');
|
|
10
|
-
const { execSync } = require('child_process');
|
|
11
|
-
|
|
12
|
-
// Helper to wait for a condition with timeout
|
|
13
|
-
async function waitFor(conditionFn, timeout = 5000, interval = 100) {
|
|
14
|
-
const startTime = Date.now();
|
|
15
|
-
while (Date.now() - startTime < timeout) {
|
|
16
|
-
if (conditionFn()) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
20
|
-
}
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Use the canRunLinuxDockerImages function from isolation module
|
|
25
|
-
// to properly detect if Linux containers can run (handles Windows containers mode)
|
|
26
|
-
const { canRunLinuxDockerImages } = require('../src/lib/isolation');
|
|
27
|
-
|
|
28
|
-
describe('Docker Auto-Remove Container Feature', () => {
|
|
29
|
-
// These tests verify the --auto-remove-docker-container option
|
|
30
|
-
// which automatically removes the container after exit (disabled by default)
|
|
31
|
-
|
|
32
|
-
describe('auto-remove enabled', () => {
|
|
33
|
-
it('should automatically remove container when autoRemoveDockerContainer is true', async () => {
|
|
34
|
-
if (!canRunLinuxDockerImages()) {
|
|
35
|
-
console.log(
|
|
36
|
-
' Skipping: docker not available, daemon not running, or Linux containers not supported'
|
|
37
|
-
);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const containerName = `test-autoremove-${Date.now()}`;
|
|
42
|
-
|
|
43
|
-
// Run command with autoRemoveDockerContainer enabled
|
|
44
|
-
const result = await runInDocker('echo "test" && sleep 0.5', {
|
|
45
|
-
image: 'alpine:latest',
|
|
46
|
-
session: containerName,
|
|
47
|
-
detached: true,
|
|
48
|
-
keepAlive: false,
|
|
49
|
-
autoRemoveDockerContainer: true,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
assert.strictEqual(result.success, true);
|
|
53
|
-
assert.ok(
|
|
54
|
-
result.message.includes('automatically removed'),
|
|
55
|
-
'Message should indicate auto-removal'
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
// Wait for container to finish and be removed
|
|
59
|
-
const containerRemoved = await waitFor(() => {
|
|
60
|
-
try {
|
|
61
|
-
execSync(`docker inspect -f '{{.State.Status}}' ${containerName}`, {
|
|
62
|
-
encoding: 'utf8',
|
|
63
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
64
|
-
});
|
|
65
|
-
return false; // Container still exists
|
|
66
|
-
} catch {
|
|
67
|
-
return true; // Container does not exist (removed)
|
|
68
|
-
}
|
|
69
|
-
}, 10000);
|
|
70
|
-
|
|
71
|
-
assert.ok(
|
|
72
|
-
containerRemoved,
|
|
73
|
-
'Container should be automatically removed after exit with --auto-remove-docker-container'
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
// Double-check with docker ps -a that container is completely removed
|
|
77
|
-
try {
|
|
78
|
-
const allContainers = execSync('docker ps -a', {
|
|
79
|
-
encoding: 'utf8',
|
|
80
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
81
|
-
});
|
|
82
|
-
assert.ok(
|
|
83
|
-
!allContainers.includes(containerName),
|
|
84
|
-
'Container should NOT appear in docker ps -a (completely removed)'
|
|
85
|
-
);
|
|
86
|
-
console.log(
|
|
87
|
-
' ✓ Docker container auto-removed after exit (filesystem not preserved)'
|
|
88
|
-
);
|
|
89
|
-
} catch (err) {
|
|
90
|
-
assert.fail(`Failed to verify container removal: ${err.message}`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// No cleanup needed - container should already be removed
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe('auto-remove disabled (default)', () => {
|
|
98
|
-
it('should preserve container filesystem by default (without autoRemoveDockerContainer)', async () => {
|
|
99
|
-
if (!canRunLinuxDockerImages()) {
|
|
100
|
-
console.log(
|
|
101
|
-
' Skipping: docker not available, daemon not running, or Linux containers not supported'
|
|
102
|
-
);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const containerName = `test-preserve-${Date.now()}`;
|
|
107
|
-
|
|
108
|
-
// Run command without autoRemoveDockerContainer
|
|
109
|
-
const result = await runInDocker('echo "test" && sleep 0.1', {
|
|
110
|
-
image: 'alpine:latest',
|
|
111
|
-
session: containerName,
|
|
112
|
-
detached: true,
|
|
113
|
-
keepAlive: false,
|
|
114
|
-
autoRemoveDockerContainer: false,
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
assert.strictEqual(result.success, true);
|
|
118
|
-
assert.ok(
|
|
119
|
-
result.message.includes('filesystem will be preserved'),
|
|
120
|
-
'Message should indicate filesystem preservation'
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
// Wait for container to exit
|
|
124
|
-
await waitFor(() => {
|
|
125
|
-
try {
|
|
126
|
-
const status = execSync(
|
|
127
|
-
`docker inspect -f '{{.State.Status}}' ${containerName}`,
|
|
128
|
-
{
|
|
129
|
-
encoding: 'utf8',
|
|
130
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
131
|
-
}
|
|
132
|
-
).trim();
|
|
133
|
-
return status === 'exited';
|
|
134
|
-
} catch {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
}, 10000);
|
|
138
|
-
|
|
139
|
-
// Container should still exist (in exited state)
|
|
140
|
-
try {
|
|
141
|
-
const allContainers = execSync('docker ps -a', {
|
|
142
|
-
encoding: 'utf8',
|
|
143
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
144
|
-
});
|
|
145
|
-
assert.ok(
|
|
146
|
-
allContainers.includes(containerName),
|
|
147
|
-
'Container should appear in docker ps -a (filesystem preserved)'
|
|
148
|
-
);
|
|
149
|
-
console.log(
|
|
150
|
-
' ✓ Docker container filesystem preserved by default (can be re-entered)'
|
|
151
|
-
);
|
|
152
|
-
} catch (err) {
|
|
153
|
-
assert.fail(`Failed to verify container preservation: ${err.message}`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Clean up
|
|
157
|
-
try {
|
|
158
|
-
execSync(`docker rm -f ${containerName}`, { stdio: 'ignore' });
|
|
159
|
-
} catch {
|
|
160
|
-
// Ignore cleanup errors
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test';
|
|
2
|
-
import { releaseName, releaseTag } from '../../scripts/release-name.mjs';
|
|
3
|
-
|
|
4
|
-
describe('releaseTag', () => {
|
|
5
|
-
it('uses plain "v${version}" when no prefix is given', () => {
|
|
6
|
-
expect(releaseTag('0.25.4')).toBe('v0.25.4');
|
|
7
|
-
expect(releaseTag('0.25.4', '')).toBe('v0.25.4');
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('prepends known language prefixes', () => {
|
|
11
|
-
expect(releaseTag('0.25.4', 'js-')).toBe('js-v0.25.4');
|
|
12
|
-
expect(releaseTag('0.14.0', 'rust-')).toBe('rust-v0.14.0');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('passes arbitrary prefixes through', () => {
|
|
16
|
-
expect(releaseTag('1.0.0', 'api-')).toBe('api-v1.0.0');
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('releaseName', () => {
|
|
21
|
-
it('returns bare version when prefix is empty (preserves pre-issue-108 behaviour)', () => {
|
|
22
|
-
expect(releaseName('0.25.4')).toBe('0.25.4');
|
|
23
|
-
expect(releaseName('0.25.4', '')).toBe('0.25.4');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('decorates known language prefixes with human titles', () => {
|
|
27
|
-
expect(releaseName('0.25.4', 'js-')).toBe('[JavaScript] 0.25.4');
|
|
28
|
-
expect(releaseName('0.14.0', 'rust-')).toBe('[Rust] 0.14.0');
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('falls back to "${prefix}${version}" for unknown prefixes', () => {
|
|
32
|
-
expect(releaseName('1.0.0', 'api-')).toBe('api-1.0.0');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|