sandboxbox 2.3.4 → 2.3.6
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/package.json +1 -1
- package/utils/commands/container.js +45 -14
- package/utils/podman.js +71 -131
package/package.json
CHANGED
@@ -16,19 +16,40 @@ export function buildCommand(dockerfilePath) {
|
|
16
16
|
|
17
17
|
const podmanPath = checkPodman();
|
18
18
|
if (!podmanPath) return false;
|
19
|
-
if (!setupBackendNonBlocking(podmanPath)) return false;
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
// Start backend setup but don't block on Windows/macOS
|
21
|
+
const backendReady = setupBackendNonBlocking(podmanPath);
|
22
|
+
if (process.platform === 'linux' && !backendReady) {
|
23
|
+
return false; // Only block on Linux for rootless service
|
24
|
+
}
|
25
|
+
|
26
|
+
// Retry container operation with backend readiness check
|
27
|
+
let retries = 0;
|
28
|
+
const maxRetries = process.platform === 'linux' ? 3 : 12; // More retries for Windows/macOS
|
29
|
+
|
30
|
+
while (retries < maxRetries) {
|
31
|
+
try {
|
32
|
+
execSync(`"${podmanPath}" build -f "${dockerfilePath}" -t sandboxbox:latest .`, {
|
33
|
+
stdio: 'inherit',
|
34
|
+
cwd: dirname(dockerfilePath),
|
35
|
+
shell: process.platform === 'win32',
|
36
|
+
timeout: 30000 // 30 second timeout
|
37
|
+
});
|
38
|
+
console.log(color('green', '\n✅ Container built successfully!'));
|
39
|
+
return true;
|
40
|
+
} catch (error) {
|
41
|
+
retries++;
|
42
|
+
if (retries < maxRetries && error.message.includes('Cannot connect to Podman')) {
|
43
|
+
console.log(color('yellow', ` Backend not ready yet (${retries}/${maxRetries}), waiting 15 seconds...`));
|
44
|
+
const start = Date.now();
|
45
|
+
while (Date.now() - start < 15000) {
|
46
|
+
// Wait 15 seconds
|
47
|
+
}
|
48
|
+
continue;
|
49
|
+
}
|
50
|
+
console.log(color('red', `\n❌ Build failed: ${error.message}`));
|
51
|
+
return false;
|
52
|
+
}
|
32
53
|
}
|
33
54
|
}
|
34
55
|
|
@@ -45,7 +66,12 @@ export function runCommand(projectDir, cmd = 'bash') {
|
|
45
66
|
|
46
67
|
const podmanPath = checkPodman();
|
47
68
|
if (!podmanPath) return false;
|
48
|
-
|
69
|
+
|
70
|
+
// Start backend setup but don't block on Windows/macOS
|
71
|
+
const backendReady = setupBackendNonBlocking(podmanPath);
|
72
|
+
if (process.platform === 'linux' && !backendReady) {
|
73
|
+
return false; // Only block on Linux for rootless service
|
74
|
+
}
|
49
75
|
|
50
76
|
try {
|
51
77
|
const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
|
@@ -78,7 +104,12 @@ export function shellCommand(projectDir) {
|
|
78
104
|
|
79
105
|
const podmanPath = checkPodman();
|
80
106
|
if (!podmanPath) return false;
|
81
|
-
|
107
|
+
|
108
|
+
// Start backend setup but don't block on Windows/macOS
|
109
|
+
const backendReady = setupBackendNonBlocking(podmanPath);
|
110
|
+
if (process.platform === 'linux' && !backendReady) {
|
111
|
+
return false; // Only block on Linux for rootless service
|
112
|
+
}
|
82
113
|
|
83
114
|
try {
|
84
115
|
const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
|
package/utils/podman.js
CHANGED
@@ -27,153 +27,93 @@ export function getPodmanPath() {
|
|
27
27
|
}
|
28
28
|
|
29
29
|
export function setupBackendNonBlocking(podmanPath) {
|
30
|
-
if (process.platform === 'linux')
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
try {
|
35
|
-
execSync(`"${podmanPath}" info`, execOptions);
|
36
|
-
return true;
|
37
|
-
} catch (infoError) {
|
38
|
-
if (!infoError.message.includes('Cannot connect to Podman')) {
|
39
|
-
return false;
|
40
|
-
}
|
41
|
-
|
42
|
-
console.log(color('yellow', '\n🔧 Initializing Podman backend (one-time setup, takes 2-3 minutes)...'));
|
43
|
-
|
30
|
+
if (process.platform === 'linux') {
|
31
|
+
// Linux can run true rootless Podman
|
32
|
+
const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
|
44
33
|
try {
|
45
|
-
|
46
|
-
|
34
|
+
execSync(`"${podmanPath}" info`, execOptions);
|
35
|
+
return true;
|
36
|
+
} catch (infoError) {
|
37
|
+
console.log(color('yellow', '\n🔧 Starting Podman rootless service...'));
|
38
|
+
// Try to start service automatically
|
47
39
|
try {
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
console.log(color('cyan', ` Found ${machines.length} existing machine(s)`));
|
54
|
-
} catch (machineListError) {
|
55
|
-
console.log(color('yellow', ' Could not list machines quickly, checking via info command...'));
|
56
|
-
// Try to detect if machine exists by checking for specific error messages
|
57
|
-
try {
|
58
|
-
execSync(`"${podmanPath}" info`, {
|
59
|
-
...execOptions,
|
60
|
-
timeout: 3000
|
61
|
-
});
|
62
|
-
console.log(color('green', ' Backend is already working!'));
|
63
|
-
return true;
|
64
|
-
} catch (infoError) {
|
65
|
-
if (infoError.message.includes('127.0.0.1')) {
|
66
|
-
console.log(color('cyan', ' Machine exists but not running, proceeding...'));
|
67
|
-
} else {
|
68
|
-
console.log(color('yellow', ' Assuming no machines exist'));
|
69
|
-
}
|
70
|
-
}
|
40
|
+
execSync('podman system service --time=0 &', { stdio: 'ignore', shell: true });
|
41
|
+
return true;
|
42
|
+
} catch (serviceError) {
|
43
|
+
console.log(color('cyan', ' Run: podman system service --time=0 &'));
|
44
|
+
return false;
|
71
45
|
}
|
46
|
+
}
|
47
|
+
}
|
72
48
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
? `"${podmanPath}" machine init --rootful=false`
|
77
|
-
: `"${podmanPath}" machine init`;
|
49
|
+
// Windows: Implement completely silent automated setup
|
50
|
+
if (process.platform === 'win32') {
|
51
|
+
const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
|
78
52
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
} catch (initError) {
|
86
|
-
const errorOutput = initError.stdout?.toString() + initError.stderr?.toString();
|
87
|
-
if (errorOutput?.includes('already exists') ||
|
88
|
-
errorOutput?.includes('VM already exists') ||
|
89
|
-
initError.message.includes('already exists')) {
|
90
|
-
console.log(color('cyan', ' Machine already exists, proceeding...'));
|
91
|
-
} else {
|
92
|
-
console.log(color('red', ` Error output: ${errorOutput}`));
|
93
|
-
throw initError;
|
94
|
-
}
|
95
|
-
}
|
96
|
-
} else {
|
97
|
-
console.log(color('cyan', ' Using existing machine'));
|
53
|
+
try {
|
54
|
+
execSync(`"${podmanPath}" info`, execOptions);
|
55
|
+
return true;
|
56
|
+
} catch (infoError) {
|
57
|
+
if (!infoError.message.includes('Cannot connect to Podman')) {
|
58
|
+
return false;
|
98
59
|
}
|
99
60
|
|
100
|
-
console.log(color('
|
101
|
-
try {
|
102
|
-
const statusOutput = execSync(`"${podmanPath}" machine list`, {
|
103
|
-
encoding: 'utf-8',
|
104
|
-
stdio: 'pipe',
|
105
|
-
shell: true,
|
106
|
-
timeout: 3000 // 3 seconds timeout
|
107
|
-
});
|
61
|
+
console.log(color('yellow', '\n🔧 Setting up Podman automatically (silent mode)...'));
|
108
62
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
}
|
115
|
-
} catch (statusError) {
|
116
|
-
console.log(color('cyan', ' Could not check status, attempting to start machine...'));
|
117
|
-
startMachineWithRetry();
|
118
|
-
}
|
63
|
+
// Start machine setup in background without blocking
|
64
|
+
setupMachineBackground(podmanPath);
|
65
|
+
return true; // Continue even if setup is in progress
|
66
|
+
}
|
67
|
+
}
|
119
68
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
while (Date.now() - start < 15000) {
|
124
|
-
// Wait 15 seconds for background start
|
125
|
-
}
|
69
|
+
// macOS: Similar automated approach
|
70
|
+
if (process.platform === 'darwin') {
|
71
|
+
const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
|
126
72
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
timeout: 5000 // 5 second timeout
|
133
|
-
});
|
134
|
-
console.log(color('green', ' Backend is ready!'));
|
135
|
-
} catch (verifyError) {
|
136
|
-
console.log(color('yellow', ' Backend still starting. This is normal for first-time setup.'));
|
137
|
-
console.log(color('cyan', ' If this persists, run manually:'));
|
138
|
-
const manualCmd = process.platform === 'win32'
|
139
|
-
? `"${podmanPath}" machine init --rootful=false && "${podmanPath}" machine start`
|
140
|
-
: `"${podmanPath}" machine init && "${podmanPath}" machine start`;
|
141
|
-
console.log(color('cyan', ` ${manualCmd}`));
|
142
|
-
console.log(color('yellow', ' Then try sandboxbox again.'));
|
73
|
+
try {
|
74
|
+
execSync(`"${podmanPath}" info`, execOptions);
|
75
|
+
return true;
|
76
|
+
} catch (infoError) {
|
77
|
+
if (!infoError.message.includes('Cannot connect to Podman')) {
|
143
78
|
return false;
|
144
79
|
}
|
145
80
|
|
146
|
-
console.log(color('
|
81
|
+
console.log(color('yellow', '\n🔧 Setting up Podman automatically...'));
|
82
|
+
setupMachineBackground(podmanPath);
|
147
83
|
return true;
|
148
|
-
|
149
|
-
function startMachineWithRetry() {
|
150
|
-
// Use completely silent background start
|
151
|
-
console.log(color('cyan', ' Starting Podman machine silently in background...'));
|
152
|
-
|
153
|
-
const startProcess = spawn(`"${podmanPath}" machine start`, {
|
154
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
155
|
-
shell: true,
|
156
|
-
detached: true
|
157
|
-
});
|
158
|
-
|
159
|
-
startProcess.unref(); // Completely detach from parent
|
160
|
-
console.log(color('yellow', ' Machine start initiated in background (may take 1-2 minutes)'));
|
161
|
-
}
|
162
|
-
} catch (setupError) {
|
163
|
-
if (setupError.signal === 'SIGTERM') {
|
164
|
-
console.log(color('red', '\n❌ Setup timed out. Please run manually:'));
|
165
|
-
} else {
|
166
|
-
console.log(color('red', `\n❌ Setup failed: ${setupError.message}`));
|
167
|
-
console.log(color('red', ` Error details: ${setupError.stack}`));
|
168
|
-
}
|
169
|
-
|
170
|
-
const manualCmd = process.platform === 'win32'
|
171
|
-
? `"${podmanPath}" machine init --rootful=false && "${podmanPath}" machine start`
|
172
|
-
: `"${podmanPath}" machine init && "${podmanPath}" machine start`;
|
173
|
-
console.log(color('cyan', ` Manual setup: ${manualCmd}`));
|
174
|
-
return false;
|
175
84
|
}
|
176
85
|
}
|
86
|
+
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
|
90
|
+
function setupMachineBackground(podmanPath) {
|
91
|
+
console.log(color('cyan', ' Starting machine setup in background...'));
|
92
|
+
|
93
|
+
const initCmd = process.platform === 'win32'
|
94
|
+
? `"${podmanPath}" machine init --rootful=false`
|
95
|
+
: `"${podmanPath}" machine init`;
|
96
|
+
|
97
|
+
const initProcess = spawn(initCmd, {
|
98
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
99
|
+
shell: true,
|
100
|
+
detached: true
|
101
|
+
});
|
102
|
+
|
103
|
+
initProcess.unref();
|
104
|
+
|
105
|
+
// Start machine after init completes (with delay)
|
106
|
+
setTimeout(() => {
|
107
|
+
const startProcess = spawn(`"${podmanPath}" machine start`, {
|
108
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
109
|
+
shell: true,
|
110
|
+
detached: true
|
111
|
+
});
|
112
|
+
startProcess.unref();
|
113
|
+
}, 30000); // Wait 30 seconds for init to complete
|
114
|
+
|
115
|
+
console.log(color('yellow', ' Setup initiated in background (may take 2-3 minutes)'));
|
116
|
+
console.log(color('cyan', ' Container operations will work when setup completes\n'));
|
177
117
|
}
|
178
118
|
|
179
119
|
export function checkBackend(podmanPath) {
|