Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/lib/onboard/experimental/hermes-portable-build-context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,18 @@ describe("Hermes portable staged build context", testTimeoutOptions(30_000), ()
const plan = createHermesPortableBuildContextPlan(ROOT, BUILD_SETTINGS);
const first = plan.materialize(contextInput());

expect(first.dockerfilePath).toBe(
path.join(first.buildContextPath, "agents/hermes/Dockerfile"),
);
expect(first.dockerfilePath).toBe(path.join(first.buildContextPath, "Dockerfile"));
const inferredContext = path.dirname(first.dockerfilePath);
expect(inferredContext).toBe(first.buildContextPath);
expect(
fs.existsSync(
path.join(
inferredContext,
"tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/mcp-tool-discovery/BUNDLED_PACKAGES.json",
),
),
).toBe(true);
expect(fs.existsSync(path.join(inferredContext, "agents/hermes/Dockerfile"))).toBe(false);
expect(plan.authority.sourceRevision).toMatch(/^[a-f0-9]{40,64}$/u);
expect(plan.authority.contextManifestSha256).toMatch(/^[a-f0-9]{64}$/u);
const stagedDockerfile = fs.readFileSync(first.dockerfilePath, "utf8");
Expand Down
26 changes: 18 additions & 8 deletions src/lib/onboard/experimental/hermes-portable-build-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const OPEN_READ_FLAGS =
fs.constants.O_RDONLY |
(typeof fs.constants.O_NOFOLLOW === "number" ? fs.constants.O_NOFOLLOW : 0) |
(typeof fs.constants.O_NONBLOCK === "number" ? fs.constants.O_NONBLOCK : 0);
const SOURCE_DOCKERFILE_RELATIVE_PATH = "agents/hermes/Dockerfile" as const;
const CONTEXT_DOCKERFILE_RELATIVE_PATH = "Dockerfile" as const;

const LOCAL_COPY_SOURCES = [
"agents/hermes/build-mcp-digest.py",
Expand Down Expand Up @@ -128,7 +130,7 @@ type DirectoryEvidence = {
export interface HermesPortableBuildContextAuthority {
readonly schemaVersion: typeof CONTEXT_SCHEMA_VERSION;
readonly sourceRevision: string;
readonly dockerfileRelativePath: "agents/hermes/Dockerfile";
readonly dockerfileRelativePath: typeof CONTEXT_DOCKERFILE_RELATIVE_PATH;
readonly sourceManifestSha256: string;
readonly contextManifestSha256: string;
}
Expand Down Expand Up @@ -640,7 +642,7 @@ function captureSourceEntries(
entries.push(entry);
};

visit("agents/hermes/Dockerfile");
visit(SOURCE_DOCKERFILE_RELATIVE_PATH);
for (const token of LOCAL_COPY_SOURCES) {
if (token.endsWith("/")) {
visit(token.slice(0, -1));
Expand Down Expand Up @@ -676,7 +678,7 @@ function sourceAuthority(
});
const contextManifestSha256 = canonicalDigest({
schemaVersion: CONTEXT_SCHEMA_VERSION,
dockerfileRelativePath: "agents/hermes/Dockerfile",
dockerfileRelativePath: CONTEXT_DOCKERFILE_RELATIVE_PATH,
entries: contextEntries.map((entry) => ({
kind: entry.kind,
relativePath: entry.relativePath,
Expand All @@ -687,7 +689,7 @@ function sourceAuthority(
return {
schemaVersion: CONTEXT_SCHEMA_VERSION,
sourceRevision: revision.revision,
dockerfileRelativePath: "agents/hermes/Dockerfile",
dockerfileRelativePath: CONTEXT_DOCKERFILE_RELATIVE_PATH,
sourceManifestSha256,
contextManifestSha256,
};
Expand All @@ -698,12 +700,20 @@ function renderContextEntries(
settings: HermesPortableBuildContextSettings,
): readonly SourceEntry[] {
return sourceEntries.map((entry) => {
if (entry.kind !== "file" || entry.relativePath !== "agents/hermes/Dockerfile") return entry;
if (entry.kind !== "file" || entry.relativePath !== SOURCE_DOCKERFILE_RELATIVE_PATH) {
return entry;
}
const bytes = Buffer.from(
renderHermesPortableDockerfileBuildSettings(UTF8.decode(entry.bytes!), settings),
"utf8",
);
return { ...entry, bytes, size: bytes.byteLength, sha256: digest(bytes) };
return {
...entry,
relativePath: CONTEXT_DOCKERFILE_RELATIVE_PATH,
bytes,
size: bytes.byteLength,
sha256: digest(bytes),
};
});
}

Expand All @@ -724,7 +734,7 @@ function capture(
);
const sourceEntries = captureSourceEntries(rootPath, tracked);
const dockerfile = sourceEntries.find(
(entry) => entry.relativePath === "agents/hermes/Dockerfile",
(entry) => entry.relativePath === SOURCE_DOCKERFILE_RELATIVE_PATH,
);
if (dockerfile?.kind !== "file" || !dockerfile.bytes) fail("Dockerfile source is unavailable");
parseDockerfileSources(dockerfile.bytes);
Expand Down Expand Up @@ -1375,7 +1385,7 @@ export function createHermesPortableBuildContextPlan(
};
return {
authority: captured.authority,
sourceDockerfilePath: path.join(rootPath, captured.authority.dockerfileRelativePath),
sourceDockerfilePath: path.join(rootPath, SOURCE_DOCKERFILE_RELATIVE_PATH),
assertCurrentSource,
materialize: (input) => {
assertCurrentSource();
Expand Down
6 changes: 3 additions & 3 deletions test/helpers/hermes-portable-onboarding-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,15 @@ export function createHermesPortableTestInput(stateDir: string, policyPath: stri
authority: {
schemaVersion: 1,
sourceRevision: "1".repeat(40),
dockerfileRelativePath: "agents/hermes/Dockerfile",
dockerfileRelativePath: "Dockerfile",
sourceManifestSha256: "2".repeat(64),
contextManifestSha256: "3".repeat(64),
},
sourceDockerfilePath,
assertCurrentSource: vi.fn(),
materialize: vi.fn(() => ({
buildContextPath: "/private/staged-hermes",
dockerfilePath: "/private/staged-hermes/agents/hermes/Dockerfile",
dockerfilePath: "/private/staged-hermes/Dockerfile",
assertCurrent: vi.fn(),
})),
retire: vi.fn(() => true),
Expand Down Expand Up @@ -390,7 +390,7 @@ export function createHermesPortableTransactionFixture(
const policyIndex = argv.indexOf("--policy");
expect(argv[policyIndex + 1]).toContain("policy.");
expect(argv[argv.indexOf("--from") + 1]).toBe(
options.expectedDockerfilePath ?? "/private/staged-hermes/agents/hermes/Dockerfile",
options.expectedDockerfilePath ?? "/private/staged-hermes/Dockerfile",
);
expect(buildContextPath).toBe(options.expectedBuildContextPath ?? "/private/staged-hermes");
present = true;
Expand Down
Loading