@moinulmoin/eden 0.8.0 → 0.9.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/README.md +3 -3
- package/dist/eve-control-plane.js +18 -1
- package/dist/eve-packaging.d.ts +25 -5
- package/dist/eve-packaging.js +228 -6
- package/dist/eve-runtime-config.js +8 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,15 +12,15 @@ If you already have an Eve project, start with `eden deploy`.
|
|
|
12
12
|
Use any one of these package managers:
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
|
-
npm install --global @moinulmoin/eden@0.
|
|
15
|
+
npm install --global @moinulmoin/eden@0.9.0
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
|
-
pnpm add --global @moinulmoin/eden@0.
|
|
19
|
+
pnpm add --global @moinulmoin/eden@0.9.0
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
```sh
|
|
23
|
-
bun add --global @moinulmoin/eden@0.
|
|
23
|
+
bun add --global @moinulmoin/eden@0.9.0
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Then confirm the CLI is available:
|
|
@@ -8,7 +8,7 @@ import { execFile, spawn, } from "node:child_process";
|
|
|
8
8
|
import { fileURLToPath, } from "node:url";
|
|
9
9
|
import { promisify, } from "node:util";
|
|
10
10
|
import { EveCliError, EVE_NAME_PATTERN, } from "./eve.js";
|
|
11
|
-
import { buildEveProjectSnapshot, createDockerEveProjectBuilder, revalidateEveProjectCandidateInputs, EvePackagingError, IMAGE_ID_PATTERN, } from "./eve-packaging.js";
|
|
11
|
+
import { buildEveProjectSnapshot, checkEveSandboxProvider, createDockerEveProjectBuilder, revalidateEveProjectCandidateInputs, EvePackagingError, IMAGE_ID_PATTERN, } from "./eve-packaging.js";
|
|
12
12
|
import { buildEveRuntimeImage, discardEveRuntimeImage, revalidateEveRuntimeCandidate, validateEveHostRequirements, } from "./eve-runtime-image.js";
|
|
13
13
|
import { EveRuntimeConfigError, prepareEveRuntimeInjection, redactEveRuntimeOutput, } from "./eve-runtime-config.js";
|
|
14
14
|
import { createEveHostConfig, generateEveHostWorkerSource, parseEveScheduleCron, resolveStableWorkersDevOrigin, } from "@moinulmoin/eden-runtime-cloudflare";
|
|
@@ -65,6 +65,7 @@ function mapPackagingCheck(value) {
|
|
|
65
65
|
case "DOCKER_PLATFORM_BLOCKED":
|
|
66
66
|
return "VAL-BUILD-005";
|
|
67
67
|
case "EVE_SANDBOX_RESUME_PATCH":
|
|
68
|
+
case "EVE_SANDBOX_PROVIDER":
|
|
68
69
|
return value.id;
|
|
69
70
|
default:
|
|
70
71
|
return `EVE-${value.id}`;
|
|
@@ -2053,6 +2054,22 @@ async function collectEvePreflight(request, options) {
|
|
|
2053
2054
|
runtimeConfig,
|
|
2054
2055
|
};
|
|
2055
2056
|
}
|
|
2057
|
+
const sandboxProvider = await checkEveSandboxProvider(request.projectRoot);
|
|
2058
|
+
if (sandboxProvider !== undefined) {
|
|
2059
|
+
checks.push(check(sandboxProvider.code, "failed", sandboxProvider.message, sandboxProvider.remediation));
|
|
2060
|
+
return {
|
|
2061
|
+
result: {
|
|
2062
|
+
command: request.command === "deploy" ? "eve deploy" : "eve preflight",
|
|
2063
|
+
ok: false,
|
|
2064
|
+
environment: request.environment,
|
|
2065
|
+
name: request.name,
|
|
2066
|
+
checks,
|
|
2067
|
+
warnings,
|
|
2068
|
+
candidate: null,
|
|
2069
|
+
},
|
|
2070
|
+
runtimeConfig,
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2056
2073
|
warnings.push(...await collectEveSetupWarnings(request.projectRoot));
|
|
2057
2074
|
eveProgress(options, "packaging project — snapshot, frozen install, eve build");
|
|
2058
2075
|
const nodeImage = options.nodeImage ?? DEFAULT_EVE_NODE_IMAGE;
|
package/dist/eve-packaging.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type EveRuntimeInputIdentity } from "./eve-runtime-config.js";
|
|
2
|
-
export type EvePackagingCode = "ROOT_INVALID" | "UNSUPPORTED_TOOLCHAIN" | "DEPENDENCY_AMBIGUITY" | "SOURCE_RACE" | "EVE_BUILD_FAILED" | "UNSUPPORTED_EVE_OUTPUT" | "RUNTIME_CLOSURE_INCOMPLETE" | "SECRET_EXCLUSION_FAILED" | "DOCKER_PLATFORM_BLOCKED" | "UNSUPPORTED_HOST_REQUIREMENT" | "EVE_HEALTH_FAILED" | "WORLD_MIGRATION_FAILED" | "CLEANUP_UNVERIFIED";
|
|
2
|
+
export type EvePackagingCode = "ROOT_INVALID" | "UNSUPPORTED_TOOLCHAIN" | "DEPENDENCY_AMBIGUITY" | "SOURCE_RACE" | "EVE_BUILD_FAILED" | "EVE_SANDBOX_PROVIDER" | "UNSUPPORTED_EVE_OUTPUT" | "RUNTIME_CLOSURE_INCOMPLETE" | "SECRET_EXCLUSION_FAILED" | "DOCKER_PLATFORM_BLOCKED" | "UNSUPPORTED_HOST_REQUIREMENT" | "EVE_HEALTH_FAILED" | "WORLD_MIGRATION_FAILED" | "CLEANUP_UNVERIFIED";
|
|
3
3
|
export interface EveRuntimeConfigExclusion {
|
|
4
4
|
/**
|
|
5
5
|
* This path is opaque. The packaging worker only uses its lexical identity
|
|
@@ -228,9 +228,10 @@ export interface EveProjectPackagingResult {
|
|
|
228
228
|
readonly checks: readonly EvePackagingCheck[];
|
|
229
229
|
/**
|
|
230
230
|
* Outcome of the builder's temporary eve#4440 sandbox-resume patch:
|
|
231
|
-
* `applied` when the shipped just-bash binding carries it, `
|
|
232
|
-
*
|
|
233
|
-
*
|
|
231
|
+
* `applied` when the shipped just-bash binding carries it, `fixed` when the
|
|
232
|
+
* installed Eve already includes the upstream fix, `skipped` when the
|
|
233
|
+
* binding is a version Eden does not know, `absent` when this Eve build has
|
|
234
|
+
* no just-bash binding or packaging never reached the image.
|
|
234
235
|
*/
|
|
235
236
|
readonly sandboxResumePatch: EveSandboxResumePatchStatus;
|
|
236
237
|
readonly candidateImageId: string | null;
|
|
@@ -272,6 +273,25 @@ export declare const EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256 = "0ba0ac3a237c99af2f
|
|
|
272
273
|
export declare const EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256 = "ab8b1ad7398af8f6fd2a1e91eb0d1ff8d2b9b9afe1836234f36ce0e896791c45";
|
|
273
274
|
/** Marker the patched binding always contains; proves the patch shipped. */
|
|
274
275
|
export declare const EVE_SANDBOX_RESUME_PATCH_SIGNATURE = "edenRefreshJustBashSessionSkills";
|
|
276
|
+
/**
|
|
277
|
+
* First Eve release whose just-bash provider keeps a session's files across
|
|
278
|
+
* template changes (vercel/eve#5132), so the patch is not needed from here on.
|
|
279
|
+
*/
|
|
280
|
+
export declare const EVE_SANDBOX_RESUME_FIXED_VERSION = "0.83.0";
|
|
281
|
+
/**
|
|
282
|
+
* True when an installed Eve version already ships the eve#4440 fix. A
|
|
283
|
+
* prerelease of the fixed version sorts before it (semver), so it may predate
|
|
284
|
+
* the fix and keeps the patch.
|
|
285
|
+
*/
|
|
286
|
+
export declare function eveIncludesSandboxResumeFix(version: unknown): boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Early, source-level rejection of sandbox setups that cannot work in Eden's
|
|
289
|
+
* isolated builder: a native provider named in the sandbox module, or, on Eve
|
|
290
|
+
* 0.83.0 and later, DefaultSandbox (no module, or one that names it without
|
|
291
|
+
* JustBash). Anything it cannot recognize is left to
|
|
292
|
+
* checkPreparedJustBashTemplate, which inspects what `eve build` produced.
|
|
293
|
+
*/
|
|
294
|
+
export declare function checkEveSandboxProvider(projectRoot: string, resolvedVersion?: string): Promise<EvePackagingError | undefined>;
|
|
275
295
|
/** The exact `resume()` implementation in Eve 0.68.0, 0.71.2, 0.72.1, and 0.79.1. */
|
|
276
296
|
export declare const EVE_JUST_BASH_RESUME_ORIGINAL = "async resume(e,n,r){let i=requirePreparedJustBashArtifact(n),a=requireJustBashSessionState(r),o=createSandboxProviderIdentity({artifact:i,version:1}),s=sessionRootPath(e,i);if(a.generation!==o||a.rootPath!==s)throw Error(`just-bash session state is incompatible with this environment.`);if(!await pathExists(a.rootPath))throw Error(`just-bash session root \"${a.rootPath}\" no longer exists.`);return await openHandle(e,a.rootPath,t)}";
|
|
277
297
|
/**
|
|
@@ -305,7 +325,7 @@ export declare const EVE_SANDBOX_RESUME_PATCH_HELPERS = "async function edenRefr
|
|
|
305
325
|
*/
|
|
306
326
|
export declare const EVE_SANDBOX_RESUME_PATCH_SCRIPT: string;
|
|
307
327
|
/** Outcome of the builder's sandbox-resume patch for the packaged image. */
|
|
308
|
-
export type EveSandboxResumePatchStatus = "applied" | "skipped" | "absent";
|
|
328
|
+
export type EveSandboxResumePatchStatus = "applied" | "fixed" | "skipped" | "absent";
|
|
309
329
|
export declare function sha256(value: string | Buffer): string;
|
|
310
330
|
export declare function jsonBytes(value: unknown): Buffer;
|
|
311
331
|
export declare function isWithin(root: string, candidate: string): boolean;
|
package/dist/eve-packaging.js
CHANGED
|
@@ -48,6 +48,150 @@ export const EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256 = "0ba0ac3a237c99af2f67a6028f
|
|
|
48
48
|
export const EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256 = "ab8b1ad7398af8f6fd2a1e91eb0d1ff8d2b9b9afe1836234f36ce0e896791c45";
|
|
49
49
|
/** Marker the patched binding always contains; proves the patch shipped. */
|
|
50
50
|
export const EVE_SANDBOX_RESUME_PATCH_SIGNATURE = "edenRefreshJustBashSessionSkills";
|
|
51
|
+
/**
|
|
52
|
+
* First Eve release whose just-bash provider keeps a session's files across
|
|
53
|
+
* template changes (vercel/eve#5132), so the patch is not needed from here on.
|
|
54
|
+
*/
|
|
55
|
+
export const EVE_SANDBOX_RESUME_FIXED_VERSION = "0.83.0";
|
|
56
|
+
/** `major.minor.patch` of a version string; prerelease and build suffixes are dropped. */
|
|
57
|
+
function parseEveRelease(version) {
|
|
58
|
+
const match = typeof version === "string"
|
|
59
|
+
? /^(\d+)\.(\d+)\.(\d+)/u.exec(version)
|
|
60
|
+
: null;
|
|
61
|
+
return match === null
|
|
62
|
+
? null
|
|
63
|
+
: [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* True when an installed Eve version already ships the eve#4440 fix. A
|
|
67
|
+
* prerelease of the fixed version sorts before it (semver), so it may predate
|
|
68
|
+
* the fix and keeps the patch.
|
|
69
|
+
*/
|
|
70
|
+
export function eveIncludesSandboxResumeFix(version) {
|
|
71
|
+
const installed = parseEveRelease(version);
|
|
72
|
+
const fixed = parseEveRelease(EVE_SANDBOX_RESUME_FIXED_VERSION);
|
|
73
|
+
if (installed === null || fixed === null)
|
|
74
|
+
return false;
|
|
75
|
+
for (let index = 0; index < 3; index += 1) {
|
|
76
|
+
if (installed[index] !== fixed[index]) {
|
|
77
|
+
return (installed[index] ?? 0) > (fixed[index] ?? 0);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return typeof version === "string" && !/^\d+\.\d+\.\d+-/u.test(version);
|
|
81
|
+
}
|
|
82
|
+
/** Eve 0.83.0 and later no longer fall back to just-bash in production builds. */
|
|
83
|
+
function eveRequiresExplicitJustBash(version) {
|
|
84
|
+
const release = parseEveRelease(version);
|
|
85
|
+
return release !== null && (release[0] > 0 || release[1] >= 83);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Eve reads its sandbox module from either path, with any source extension.
|
|
89
|
+
* When `agent/sandbox/` exists only the nested module counts: Eve 0.83–0.86
|
|
90
|
+
* silently ignores `agent/sandbox.ts` and 0.87+ fails the build.
|
|
91
|
+
*/
|
|
92
|
+
const EVE_SANDBOX_MODULE_PATHS = ["agent/sandbox", "agent/sandbox/sandbox"].flatMap((base) => ["ts", "mts", "cts", "tsx", "js", "mjs", "cjs", "jsx"].map((extension) => `${base}.${extension}`));
|
|
93
|
+
function justBashRemediation(command, path) {
|
|
94
|
+
return `Run ${command} (production dependency), then create or replace ${path} with:\nimport { defineSandbox } from 'eve/sandbox';\nimport { JustBashSandbox } from 'eve/sandbox/just-bash';\nexport const environment = JustBashSandbox.environment();\nexport default defineSandbox(() => environment.open());\nCommit the module, package.json, and updated lockfile, then retry eden preflight. See docs/deploy.md. Do not set EVE_DEV.`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Early, source-level rejection of sandbox setups that cannot work in Eden's
|
|
98
|
+
* isolated builder: a native provider named in the sandbox module, or, on Eve
|
|
99
|
+
* 0.83.0 and later, DefaultSandbox (no module, or one that names it without
|
|
100
|
+
* JustBash). Anything it cannot recognize is left to
|
|
101
|
+
* checkPreparedJustBashTemplate, which inspects what `eve build` produced.
|
|
102
|
+
*/
|
|
103
|
+
export async function checkEveSandboxProvider(projectRoot, resolvedVersion) {
|
|
104
|
+
const source = async (path) => readFile(join(projectRoot, path), "utf8").catch(() => "");
|
|
105
|
+
const json = async (path) => {
|
|
106
|
+
try {
|
|
107
|
+
const value = JSON.parse(await source(path));
|
|
108
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
109
|
+
? value
|
|
110
|
+
: {};
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const manifest = await json("package.json");
|
|
117
|
+
const dependencies = manifest.dependencies;
|
|
118
|
+
const lock = await json("package-lock.json");
|
|
119
|
+
const packages = lock.packages;
|
|
120
|
+
const pnpmLock = await source("pnpm-lock.yaml");
|
|
121
|
+
const pnpmVersion = /^\s{6}eve:\s*\r?\n\s{8}specifier:[^\n]*\r?\n\s{8}version:\s*['"]?(\d+\.\d+\.\d+(?:-[^('"\s]+)?)/mu
|
|
122
|
+
.exec(pnpmLock)?.[1];
|
|
123
|
+
const installed = await json("node_modules/eve/package.json");
|
|
124
|
+
const declared = typeof dependencies?.eve === "string"
|
|
125
|
+
? /^[~^]?(\d+\.\d+\.\d+)/u.exec(dependencies.eve)?.[1]
|
|
126
|
+
: undefined;
|
|
127
|
+
const version = resolvedVersion ?? packages?.["node_modules/eve"]?.version ??
|
|
128
|
+
pnpmVersion ?? installed.version ?? declared;
|
|
129
|
+
const requiresExplicit = eveRequiresExplicitJustBash(version);
|
|
130
|
+
const sandboxDirectory = (await lstat(join(projectRoot, "agent/sandbox")).catch(() => undefined))
|
|
131
|
+
?.isDirectory() === true;
|
|
132
|
+
let path;
|
|
133
|
+
for (const candidate of EVE_SANDBOX_MODULE_PATHS) {
|
|
134
|
+
if ((await lstat(join(projectRoot, candidate)).catch(() => undefined))?.isFile() === true) {
|
|
135
|
+
path = candidate;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const module = path === undefined
|
|
140
|
+
? ""
|
|
141
|
+
: (await source(path)).replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/gu, "");
|
|
142
|
+
const otherProvider = /\b(DefaultSandbox|DockerSandbox|VercelSandbox|VmSandbox|VMSandbox)\b/u
|
|
143
|
+
.exec(module)?.[1];
|
|
144
|
+
const justBash = /import\s*\{[^}]*?\bJustBashSandbox(?:\s+as\s+(\w+))?\s*(?:,|\})[^;]*?from\s*["']eve\/sandbox\/just-bash["']/u
|
|
145
|
+
.exec(module);
|
|
146
|
+
const binding = justBash?.[1] ?? "JustBashSandbox";
|
|
147
|
+
const explicit = justBash !== null &&
|
|
148
|
+
new RegExp(`\\b${binding}\\s*\\.\\s*environment\\s*\\(`, "u").test(module);
|
|
149
|
+
const native = otherProvider !== undefined && otherProvider !== "DefaultSandbox";
|
|
150
|
+
const usesDefault = path === undefined || (otherProvider === "DefaultSandbox" && !explicit);
|
|
151
|
+
const shadowed = requiresExplicit && sandboxDirectory && path?.startsWith("agent/sandbox.") === true;
|
|
152
|
+
if (!native && !shadowed && !(requiresExplicit && usesDefault))
|
|
153
|
+
return undefined;
|
|
154
|
+
const target = shadowed || (path === undefined && sandboxDirectory)
|
|
155
|
+
? "agent/sandbox/sandbox.ts"
|
|
156
|
+
: path ?? "agent/sandbox.ts";
|
|
157
|
+
const command = typeof manifest.packageManager === "string" &&
|
|
158
|
+
manifest.packageManager.startsWith("pnpm@")
|
|
159
|
+
? "pnpm add just-bash"
|
|
160
|
+
: "npm install just-bash";
|
|
161
|
+
return new EvePackagingError({
|
|
162
|
+
code: "EVE_SANDBOX_PROVIDER",
|
|
163
|
+
subject: target,
|
|
164
|
+
reason: shadowed
|
|
165
|
+
? `${String(path)} sits beside the agent/sandbox/ directory, where Eve ${String(version)} reads only agent/sandbox/sandbox.ts: Eve 0.83–0.86 ignores ${String(path)} and falls back to DefaultSandbox, and 0.87 and later fail the build.`
|
|
166
|
+
: native
|
|
167
|
+
? `${target} selects ${otherProvider}, which Eden does not support; use explicit JustBash instead.`
|
|
168
|
+
: path === undefined
|
|
169
|
+
? `Eve ${String(version)} has no sandbox module, so it uses DefaultSandbox, which has no provider in Eden's isolated builder: production builds no longer fall back to just-bash.`
|
|
170
|
+
: `${target} selects DefaultSandbox, which has no provider in Eden's isolated builder on Eve ${String(version)}: production builds no longer fall back to just-bash.`,
|
|
171
|
+
remediation: shadowed
|
|
172
|
+
? `Move ${String(path)} to agent/sandbox/sandbox.ts (delete it instead if agent/sandbox/sandbox.ts already exists), then retry eden preflight.`
|
|
173
|
+
: justBashRemediation(command, target),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Ground truth after `eve build`: on Eve 0.83.0 and later an agent whose
|
|
178
|
+
* sandbox resolved to no provider prepares no template and would fail to open
|
|
179
|
+
* its sandbox on Cloudflare, however its sandbox module is written.
|
|
180
|
+
*/
|
|
181
|
+
async function checkPreparedJustBashTemplate(snapshotRoot, version) {
|
|
182
|
+
if (!eveRequiresExplicitJustBash(version))
|
|
183
|
+
return undefined;
|
|
184
|
+
const templatesPath = `${EVE_SANDBOX_CACHE_ROOT}/just-bash/templates`;
|
|
185
|
+
const templates = await readdir(join(snapshotRoot, templatesPath)).catch(() => []);
|
|
186
|
+
if (templates.length > 0)
|
|
187
|
+
return undefined;
|
|
188
|
+
return new EvePackagingError({
|
|
189
|
+
code: "EVE_SANDBOX_PROVIDER",
|
|
190
|
+
subject: templatesPath,
|
|
191
|
+
reason: `Eve ${version} built no just-bash sandbox template, so the agent's sandbox would fail to open on Cloudflare; its sandbox module does not resolve to JustBash.`,
|
|
192
|
+
remediation: justBashRemediation("npm install just-bash (or pnpm add just-bash)", "agent/sandbox.ts (agent/sandbox/sandbox.ts when agent/sandbox/ exists)"),
|
|
193
|
+
});
|
|
194
|
+
}
|
|
51
195
|
/** Path of the just-bash binding inside the resolved Eve package root. */
|
|
52
196
|
const EVE_JUST_BASH_BINDING_PATH = "dist/src/execution/sandbox/bindings/just-bash.js";
|
|
53
197
|
/** The exact `resume()` implementation in Eve 0.68.0, 0.71.2, 0.72.1, and 0.79.1. */
|
|
@@ -107,9 +251,23 @@ const KNOWN_PATCHES = ${JSON.stringify({
|
|
|
107
251
|
const SIGNATURE = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_SIGNATURE)};
|
|
108
252
|
const BINDING_PATH = ${JSON.stringify(EVE_JUST_BASH_BINDING_PATH)};
|
|
109
253
|
const HELPERS = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_HELPERS)};
|
|
254
|
+
const FIXED_VERSION = ${JSON.stringify(EVE_SANDBOX_RESUME_FIXED_VERSION)};
|
|
110
255
|
function finish(outcome, detail) {
|
|
111
256
|
console.log("eden-eve-sandbox-resume-patch: " + outcome + " (" + detail + ")");
|
|
112
257
|
}
|
|
258
|
+
function parseRelease(version) {
|
|
259
|
+
const match = typeof version === "string" ? /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(version) : null;
|
|
260
|
+
return match === null ? null : [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
261
|
+
}
|
|
262
|
+
function includesFix(version) {
|
|
263
|
+
const installed = parseRelease(version);
|
|
264
|
+
const fixed = parseRelease(FIXED_VERSION);
|
|
265
|
+
if (installed === null || fixed === null) return false;
|
|
266
|
+
for (let index = 0; index < 3; index += 1) {
|
|
267
|
+
if (installed[index] !== fixed[index]) return installed[index] > fixed[index];
|
|
268
|
+
}
|
|
269
|
+
return !/^\\d+\\.\\d+\\.\\d+-/.test(version);
|
|
270
|
+
}
|
|
113
271
|
let packageJsonPath;
|
|
114
272
|
try {
|
|
115
273
|
packageJsonPath = fs.realpathSync("node_modules/eve/package.json");
|
|
@@ -125,6 +283,16 @@ try {
|
|
|
125
283
|
finish("absent", "this eve build has no just-bash binding");
|
|
126
284
|
process.exit(0);
|
|
127
285
|
}
|
|
286
|
+
let eveVersion;
|
|
287
|
+
try {
|
|
288
|
+
eveVersion = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
|
|
289
|
+
} catch {
|
|
290
|
+
eveVersion = undefined;
|
|
291
|
+
}
|
|
292
|
+
if (!source.includes(SIGNATURE) && includesFix(eveVersion)) {
|
|
293
|
+
finish("fixed", "eve " + eveVersion + " includes the upstream fix for eve#4440");
|
|
294
|
+
process.exit(0);
|
|
295
|
+
}
|
|
128
296
|
if (source.includes(SIGNATURE)) {
|
|
129
297
|
finish("applied", "already patched");
|
|
130
298
|
process.exit(0);
|
|
@@ -1475,6 +1643,14 @@ async function scanGeneratedSandboxCache(snapshotRoot) {
|
|
|
1475
1643
|
const relativePath = relativeDirectory.length === 0
|
|
1476
1644
|
? entry.name
|
|
1477
1645
|
: `${relativeDirectory}/${entry.name}`;
|
|
1646
|
+
if (relativeDirectory === "" && entry.name !== "just-bash") {
|
|
1647
|
+
throw new EvePackagingError({
|
|
1648
|
+
code: "EVE_SANDBOX_PROVIDER",
|
|
1649
|
+
subject: `${EVE_SANDBOX_CACHE_ROOT}/${entry.name}`,
|
|
1650
|
+
reason: `The Eve build prepared a ${entry.name} sandbox template; Eden supports only just-bash templates.`,
|
|
1651
|
+
remediation: "Replace the sandbox module with the explicit JustBash environment in docs/deploy.md, run npm install just-bash (or pnpm add just-bash), commit the module and lockfile, then retry eden preflight without EVE_DEV.",
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1478
1654
|
const candidate = join(directory, entry.name);
|
|
1479
1655
|
if (entry.isSymbolicLink()) {
|
|
1480
1656
|
throw new EvePackagingError({
|
|
@@ -1691,20 +1867,39 @@ function classifyNpmInstallFailure(stderr) {
|
|
|
1691
1867
|
remediation: "Fix the reported npm failure; regenerate package-lock.json with the selected exact npm version if it is out of sync. Use public registry dependencies without .npmrc credentials or dependency build scripts.",
|
|
1692
1868
|
});
|
|
1693
1869
|
}
|
|
1870
|
+
/**
|
|
1871
|
+
* The failing BuildKit step's own output (`#<step> <seconds> <line>`), last 20
|
|
1872
|
+
* lines, so Eve's error reaches the user instead of a generic build failure.
|
|
1873
|
+
*/
|
|
1874
|
+
function failingDockerStepOutput(stderr) {
|
|
1875
|
+
const step = [...stderr.matchAll(/^#(\d+) ERROR:/gmu)].at(-1)?.[1];
|
|
1876
|
+
if (step === undefined)
|
|
1877
|
+
return undefined;
|
|
1878
|
+
const lines = [...stderr.matchAll(new RegExp(`^#${step} \\d+\\.\\d+ (.*)$`, "gmu"))]
|
|
1879
|
+
.map((match) => (match[1] ?? "").trimEnd())
|
|
1880
|
+
.filter((line) => line.length > 0)
|
|
1881
|
+
.slice(-20);
|
|
1882
|
+
if (lines.length === 0)
|
|
1883
|
+
return undefined;
|
|
1884
|
+
const output = lines.join("\n");
|
|
1885
|
+
return output.length > 2000 ? `…${output.slice(-2000)}` : output;
|
|
1886
|
+
}
|
|
1694
1887
|
function classifyEveBuildFailure(stderr) {
|
|
1888
|
+
const output = failingDockerStepOutput(stderr);
|
|
1889
|
+
const reported = output === undefined ? "" : `\nEve reported:\n${output}`;
|
|
1695
1890
|
if (/\bjust-bash\b/u.test(stderr)) {
|
|
1696
1891
|
return new EvePackagingError({
|
|
1697
1892
|
code: "EVE_BUILD_FAILED",
|
|
1698
1893
|
subject: "eve build",
|
|
1699
|
-
reason:
|
|
1894
|
+
reason: `The project-local Eve build failed inside the isolated Linux/amd64 builder because Eve's default sandbox needs just-bash where no Docker daemon or /dev/kvm exists.${reported}`,
|
|
1700
1895
|
remediation: "Declare just-bash as a production dependency of the Eve project, regenerate its package-manager lockfile, and retry.",
|
|
1701
1896
|
});
|
|
1702
1897
|
}
|
|
1703
1898
|
return new EvePackagingError({
|
|
1704
1899
|
code: "EVE_BUILD_FAILED",
|
|
1705
1900
|
subject: "eve build",
|
|
1706
|
-
reason:
|
|
1707
|
-
remediation: "Fix the
|
|
1901
|
+
reason: `The project-local Eve build failed inside the isolated Linux/amd64 builder.${reported}`,
|
|
1902
|
+
remediation: "Fix the error Eve reported (run eve build locally to reproduce it) and retry.",
|
|
1708
1903
|
});
|
|
1709
1904
|
}
|
|
1710
1905
|
function classifyDockerBuildFailure(error) {
|
|
@@ -1818,9 +2013,18 @@ async function detectEveSandboxResumePatch(snapshotRoot) {
|
|
|
1818
2013
|
try {
|
|
1819
2014
|
const packageJsonPath = await realpath(join(snapshotRoot, "node_modules/eve/package.json"));
|
|
1820
2015
|
const binding = await readFile(join(dirname(packageJsonPath), EVE_JUST_BASH_BINDING_PATH), "utf8");
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
2016
|
+
if (binding.includes(EVE_SANDBOX_RESUME_PATCH_SIGNATURE))
|
|
2017
|
+
return "applied";
|
|
2018
|
+
const version = await readFile(packageJsonPath, "utf8")
|
|
2019
|
+
.then((text) => {
|
|
2020
|
+
const manifest = JSON.parse(text);
|
|
2021
|
+
return typeof manifest === "object" && manifest !== null &&
|
|
2022
|
+
"version" in manifest
|
|
2023
|
+
? manifest.version
|
|
2024
|
+
: undefined;
|
|
2025
|
+
})
|
|
2026
|
+
.catch(() => undefined);
|
|
2027
|
+
return eveIncludesSandboxResumeFix(version) ? "fixed" : "skipped";
|
|
1824
2028
|
}
|
|
1825
2029
|
catch {
|
|
1826
2030
|
return "absent";
|
|
@@ -2028,6 +2232,9 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2028
2232
|
const afterCopyRace = await sourceRaceErrorIfChanged(roots.canonicalRoot, initialInputs, initialRuntimeInputIdentity, options.runtimeConfig, resolve(options.artifactRoot), roots.requestedRoot);
|
|
2029
2233
|
if (afterCopyRace !== undefined)
|
|
2030
2234
|
return blockedResult(afterCopyRace, { writtenPaths });
|
|
2235
|
+
const sandboxProvider = await checkEveSandboxProvider(snapshotRoot);
|
|
2236
|
+
if (sandboxProvider !== undefined)
|
|
2237
|
+
throw sandboxProvider;
|
|
2031
2238
|
const nodeImage = options.nodeImage ?? options.builder.nodeImage;
|
|
2032
2239
|
let actualDockerfilePath;
|
|
2033
2240
|
if (nodeImage !== undefined) {
|
|
@@ -2094,9 +2301,15 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2094
2301
|
return blockedResult(cleanupError ?? dependencyError, { writtenPaths });
|
|
2095
2302
|
}
|
|
2096
2303
|
const eve = await resolveProjectLocalEve(snapshotRoot);
|
|
2304
|
+
const sandboxProviderAfterBuild = await checkEveSandboxProvider(snapshotRoot, eve.version);
|
|
2305
|
+
if (sandboxProviderAfterBuild !== undefined)
|
|
2306
|
+
throw sandboxProviderAfterBuild;
|
|
2097
2307
|
const sandboxResumePatch = await detectEveSandboxResumePatch(snapshotRoot);
|
|
2098
2308
|
const output = await scanGeneratedOutput(snapshotRoot);
|
|
2099
2309
|
const sandboxCache = await scanGeneratedSandboxCache(snapshotRoot);
|
|
2310
|
+
const preparedTemplate = await checkPreparedJustBashTemplate(snapshotRoot, eve.version);
|
|
2311
|
+
if (preparedTemplate !== undefined)
|
|
2312
|
+
throw preparedTemplate;
|
|
2100
2313
|
await assertGeneratedTreesExcludeSecrets(snapshotRoot);
|
|
2101
2314
|
const snapshotSourceDigest = await snapshotDigest(snapshotRoot);
|
|
2102
2315
|
const runtimeManifestPath = join(generationRoot, "runtime-manifest.json");
|
|
@@ -2277,6 +2490,15 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
2277
2490
|
remediation: null,
|
|
2278
2491
|
}]
|
|
2279
2492
|
: []),
|
|
2493
|
+
...(sandboxResumePatch === "fixed"
|
|
2494
|
+
? [{
|
|
2495
|
+
id: "EVE_SANDBOX_RESUME_PATCH",
|
|
2496
|
+
status: "pass",
|
|
2497
|
+
subject: "eve-sandbox-resume",
|
|
2498
|
+
reason: `not needed: Eve ${EVE_SANDBOX_RESUME_FIXED_VERSION} and later include the fix for eve#4440`,
|
|
2499
|
+
remediation: null,
|
|
2500
|
+
}]
|
|
2501
|
+
: []),
|
|
2280
2502
|
],
|
|
2281
2503
|
sandboxResumePatch,
|
|
2282
2504
|
candidateImageId: buildResult.imageId ?? null,
|
|
@@ -196,11 +196,18 @@ function parseEnvironmentText(text) {
|
|
|
196
196
|
}
|
|
197
197
|
return Object.freeze(values);
|
|
198
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Values shorter than this are not masked: substring masking of `1`, `8`, or
|
|
201
|
+
* `eve` garbled every message and matched Eden's own random revision IDs,
|
|
202
|
+
* failing deploys. Credentials are longer; short values are still delivered
|
|
203
|
+
* only through the protected channels, just not masked if a tool echoes them.
|
|
204
|
+
*/
|
|
205
|
+
const MIN_REDACTED_RUNTIME_VALUE_LENGTH = 8;
|
|
199
206
|
class EveRuntimeRedactionRegistry {
|
|
200
207
|
handle = `eve-runtime-redaction-${randomUUID()}`;
|
|
201
208
|
values = new Set();
|
|
202
209
|
register(value) {
|
|
203
|
-
if (value.length
|
|
210
|
+
if (value.length >= MIN_REDACTED_RUNTIME_VALUE_LENGTH)
|
|
204
211
|
this.values.add(value);
|
|
205
212
|
}
|
|
206
213
|
redact(value) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moinulmoin/eden",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Deploy existing Eve projects to your own Cloudflare account.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"NOTICE"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@moinulmoin/eden-runtime-cloudflare": "0.
|
|
34
|
+
"@moinulmoin/eden-runtime-cloudflare": "0.9.0",
|
|
35
35
|
"wrangler": "4.147.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|