@replayio/app-building 1.8.1 → 1.8.3
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/dist/container.js +3 -2
- package/dist/fly.js +64 -31
- package/package.json +1 -1
package/dist/container.js
CHANGED
|
@@ -119,8 +119,9 @@ export async function startContainer(config, repo) {
|
|
|
119
119
|
const containerEnv = buildContainerEnv(repo, config.envVars, extra);
|
|
120
120
|
// Build docker run args
|
|
121
121
|
const args = ["run", "-d", "--rm", "--name", containerName];
|
|
122
|
-
//
|
|
123
|
-
|
|
122
|
+
// Use explicit port mapping for macOS Docker Desktop compatibility
|
|
123
|
+
// (--network host only works on Linux)
|
|
124
|
+
args.push("-p", `${hostPort}:${hostPort}`);
|
|
124
125
|
for (const [k, v] of Object.entries(containerEnv)) {
|
|
125
126
|
args.push("--env", `${k}=${v}`);
|
|
126
127
|
}
|
package/dist/fly.js
CHANGED
|
@@ -85,36 +85,61 @@ export async function createMachine(app, token, image, env, name) {
|
|
|
85
85
|
// Create a volume for /repo storage
|
|
86
86
|
const volumeName = `repo_${name.replace(/-/g, "_")}`.slice(0, 30);
|
|
87
87
|
const volumeId = await createVolume(app, token, volumeName, 50);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
88
|
+
// Delete unattached volumes in parallel with creating the new machine.
|
|
89
|
+
const cleanupDone = listVolumes(app, token).then(vols => Promise.all(vols.map(async ({ id, attached_machine_id }) => {
|
|
90
|
+
if (attached_machine_id || id == volumeId)
|
|
91
|
+
return;
|
|
92
|
+
await deleteVolume(app, token, id).catch(() => { });
|
|
93
|
+
})));
|
|
94
|
+
const machineBody = JSON.stringify({
|
|
95
|
+
name,
|
|
96
|
+
config: {
|
|
97
|
+
image,
|
|
98
|
+
env,
|
|
99
|
+
auto_destroy: true,
|
|
100
|
+
restart: { policy: "no" },
|
|
101
|
+
guest: {
|
|
102
|
+
cpu_kind: "performance",
|
|
103
|
+
cpus: 16,
|
|
104
|
+
memory_mb: 32768,
|
|
105
|
+
},
|
|
106
|
+
mounts: [{ volume: volumeId, path: "/repo" }],
|
|
107
|
+
services: [
|
|
108
|
+
{
|
|
109
|
+
ports: [{ port: 443, handlers: ["tls", "http"] }],
|
|
110
|
+
protocol: "tcp",
|
|
111
|
+
internal_port: 3000,
|
|
112
|
+
autostart: false,
|
|
113
|
+
autostop: "off",
|
|
113
114
|
},
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
// Retry machine creation — volume may take a moment to become available
|
|
120
|
+
let lastErr;
|
|
121
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
122
|
+
try {
|
|
123
|
+
const res = await flyFetch(`/apps/${app}/machines`, token, {
|
|
124
|
+
method: "POST",
|
|
125
|
+
body: machineBody,
|
|
126
|
+
});
|
|
127
|
+
const data = (await res.json());
|
|
128
|
+
await cleanupDone;
|
|
129
|
+
return { machineId: data.id, volumeId };
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
133
|
+
if (msg.includes("volume not found") && attempt < 4) {
|
|
134
|
+
console.log(`Volume not yet available, retrying in 3s... (attempt ${attempt + 1})`);
|
|
135
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
136
|
+
lastErr = err;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
throw lastErr;
|
|
118
143
|
}
|
|
119
144
|
catch (err) {
|
|
120
145
|
// Clean up volume if machine creation fails
|
|
@@ -127,14 +152,22 @@ export async function createMachine(app, token, image, env, name) {
|
|
|
127
152
|
*/
|
|
128
153
|
export async function waitForMachine(app, token, machineId, timeoutMs = 180000) {
|
|
129
154
|
const start = Date.now();
|
|
155
|
+
let lastLogTime = 0;
|
|
130
156
|
while (Date.now() - start < timeoutMs) {
|
|
131
157
|
try {
|
|
132
158
|
await flyFetch(`/apps/${app}/machines/${machineId}/wait?state=started&timeout=60`, token);
|
|
133
159
|
return;
|
|
134
160
|
}
|
|
135
161
|
catch (e) {
|
|
136
|
-
const
|
|
137
|
-
|
|
162
|
+
const now = Date.now();
|
|
163
|
+
const elapsed = Math.round((now - start) / 1000);
|
|
164
|
+
// Only log at most once every 10 seconds
|
|
165
|
+
if (now - lastLogTime >= 10000) {
|
|
166
|
+
console.log(`Still waiting for machine to start (${elapsed}s elapsed): ${e instanceof Error ? e.message : e}`);
|
|
167
|
+
lastLogTime = now;
|
|
168
|
+
}
|
|
169
|
+
// Wait before retrying
|
|
170
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
138
171
|
}
|
|
139
172
|
}
|
|
140
173
|
throw new Error(`Machine ${machineId} did not reach started state within ${timeoutMs / 1000}s`);
|