Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
33 changes: 16 additions & 17 deletions test/e2e/live/dcode-base-image-runtime-evidence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import fs from "node:fs";
import { readSandboxBaseImageResolutionMetadata } from "../../../src/lib/sandbox-base-image/label-codec.ts";
import type { SandboxBaseImageResolutionMetadata } from "../../../src/lib/sandbox-base-image/types.ts";
import {
DCODE_BASE_IMAGE_TARGET_PLATFORM,
type DcodeBaseImageContract,
type DcodePlatform,
parseDcodeBaseImageContract,
} from "../../../tools/e2e/dcode-base-image-contract.mts";
import { requireDcodeBaseImageReference } from "../fixtures/dcode-base-image.ts";
Expand All @@ -22,7 +22,7 @@ export interface DcodeBaseImageRuntimeEvidence {
digest: string;
image: string;
imageId: string;
platform: DcodePlatform;
platform: typeof DCODE_BASE_IMAGE_TARGET_PLATFORM;
reference: string;
sandboxImage: string;
source: "override";
Expand Down Expand Up @@ -76,9 +76,12 @@ export function parseDcodeBaseImagePublicationEvidence(
);
}
const contract = parseDcodeBaseImageContract(evidence.base);
if (requireDcodeBaseImageReference(environment) !== contract.reference) {
if (
requireDcodeBaseImageReference(environment) !==
contract.platformReferences[DCODE_BASE_IMAGE_TARGET_PLATFORM]
) {
throw new Error(
"Deep Agents Code onboarding reference does not match the published base contract",
"Deep Agents Code onboarding reference does not match the published amd64 platform reference",
);
}
return contract;
Expand All @@ -103,14 +106,6 @@ export function loadDcodeBaseImagePublicationEvidence(
);
}

function platformFor(metadata: SandboxBaseImageResolutionMetadata): DcodePlatform {
const platform = `${metadata.os}/${metadata.architecture}`;
if (platform !== "linux/amd64" && platform !== "linux/arm64") {
throw new Error(`Deep Agents Code base resolution used unsupported platform '${platform}'`);
}
return platform;
}

export function verifyDcodeBaseImageRuntimeEvidence(
contract: DcodeBaseImageContract,
sandboxImage: string,
Expand All @@ -122,9 +117,13 @@ export function verifyDcodeBaseImageRuntimeEvidence(
if (!metadata) {
throw new Error("Deep Agents Code sandbox image is missing base resolution metadata");
}
const platform = platformFor(metadata);
const expectedDigest = contract.platformDigests[platform];
const expectedReference = contract.platformReferences[platform];
if (`${metadata.os}/${metadata.architecture}` !== DCODE_BASE_IMAGE_TARGET_PLATFORM) {
throw new Error(
`Deep Agents Code sandbox image did not use the published ${DCODE_BASE_IMAGE_TARGET_PLATFORM} base digest`,
);
}
const expectedDigest = contract.platformDigests[DCODE_BASE_IMAGE_TARGET_PLATFORM];
const expectedReference = contract.platformReferences[DCODE_BASE_IMAGE_TARGET_PLATFORM];
if (
metadata.schema !== 1 ||
metadata.imageName !== contract.image ||
Expand All @@ -135,15 +134,15 @@ export function verifyDcodeBaseImageRuntimeEvidence(
metadata.ref !== `${metadata.imageName}@${metadata.digest}`
) {
throw new Error(
`Deep Agents Code sandbox image did not use the published ${platform} base digest`,
`Deep Agents Code sandbox image did not use the published ${DCODE_BASE_IMAGE_TARGET_PLATFORM} base digest`,
);
}
return {
contractReference: contract.reference,
digest: metadata.digest,
image: metadata.imageName,
imageId: metadata.imageId,
platform,
platform: DCODE_BASE_IMAGE_TARGET_PLATFORM,
reference: metadata.ref,
sandboxImage,
source: metadata.source,
Expand Down
50 changes: 44 additions & 6 deletions test/e2e/support/dcode-base-image-contract.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";

const mocks = vi.hoisted(() => ({
appendFileSync: vi.fn(),
execFileSync: vi.fn<(...args: unknown[]) => string>(),
readFileSync: vi.fn<(...args: unknown[]) => string>(),
}));

vi.mock("node:child_process", () => ({ execFileSync: mocks.execFileSync }));
vi.mock("node:fs", () => ({
appendFileSync: mocks.appendFileSync,
readFileSync: mocks.readFileSync,
}));

import {
main,
validateDcodeBaseImageContract,
validateDcodeBaseImageImports,
} from "../../../tools/e2e/dcode-base-image-contract.mts";
Expand All @@ -13,21 +26,22 @@ const RUN_ATTEMPT = 2;
const HEAD_SHA = "a".repeat(40);
const IMAGE = "ghcr.io/nvidia/nemoclaw/langchain-deepagents-code-sandbox-base";
const DIGEST = `sha256:${"b".repeat(64)}`;
const AMD64_DIGEST = `sha256:${"c".repeat(64)}`;
const ARM64_DIGEST = `sha256:${"d".repeat(64)}`;
const AMD64_REFERENCE = `${IMAGE}@${AMD64_DIGEST}`;

function contract(overrides: Record<string, unknown> = {}): Record<string, unknown> {
const amd64 = `sha256:${"c".repeat(64)}`;
const arm64 = `sha256:${"d".repeat(64)}`;
return {
contractVersion: 1,
agent: "langchain-deepagents-code",
image: IMAGE,
digest: DIGEST,
reference: `${IMAGE}@${DIGEST}`,
platforms: ["linux/amd64", "linux/arm64"],
platformDigests: { "linux/amd64": amd64, "linux/arm64": arm64 },
platformDigests: { "linux/amd64": AMD64_DIGEST, "linux/arm64": ARM64_DIGEST },
platformReferences: {
"linux/amd64": `${IMAGE}@${amd64}`,
"linux/arm64": `${IMAGE}@${arm64}`,
"linux/amd64": AMD64_REFERENCE,
"linux/arm64": `${IMAGE}@${ARM64_DIGEST}`,
},
sourceRevision: HEAD_SHA,
run: { id: RUN_ID, attempt: RUN_ATTEMPT },
Expand All @@ -38,6 +52,10 @@ function contract(overrides: Record<string, unknown> = {}): Record<string, unkno
const expected = { runId: RUN_ID, runAttempt: RUN_ATTEMPT, headSha: HEAD_SHA };

describe("Deep Agents Code E2E base contract", () => {
beforeEach(() => {
vi.clearAllMocks();
});

it("accepts the exact immutable publication contract (#9049)", () => {
expect(validateDcodeBaseImageContract(contract(), expected).reference).toBe(
`${IMAGE}@${DIGEST}`,
Expand Down Expand Up @@ -89,4 +107,24 @@ describe("Deep Agents Code E2E base contract", () => {
/did not prove both required imports/u,
);
});

it("hands the published amd64 reference to the amd64 live target (#9386)", () => {
const value = contract();
mocks.readFileSync.mockReturnValue(JSON.stringify(value));
mocks.execFileSync.mockReturnValue("nemoclaw-dcode-base-imports-ok");

main(["contract.json"], {
GITHUB_OUTPUT: "/tmp/dcode-github-output",
PUBLICATION_HEAD_SHA: HEAD_SHA,
PUBLICATION_RUN_ATTEMPT: String(RUN_ATTEMPT),
PUBLICATION_RUN_ID: String(RUN_ID),
});

expect(mocks.execFileSync.mock.calls[0]?.[1]).toContain(AMD64_REFERENCE);
expect(mocks.appendFileSync).toHaveBeenCalledWith(
"/tmp/dcode-github-output",
`base_ref=${AMD64_REFERENCE}\ncontract=${JSON.stringify(value)}\n`,
"utf8",
);
});
});
31 changes: 21 additions & 10 deletions test/e2e/support/dcode-base-image-runtime-evidence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const PUBLICATION_REVISION = "e".repeat(40);

function publicationEnvironment(overrides: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv {
return {
[DCODE_BASE_IMAGE_ENV]: INDEX_REFERENCE,
[DCODE_BASE_IMAGE_ENV]: AMD64_REFERENCE,
...overrides,
};
}
Expand Down Expand Up @@ -99,15 +99,17 @@ describe("Deep Agents Code published base runtime evidence", () => {
});
});

it("rejects a valid official reference that differs from the publication contract", () => {
it.each([
["the publication index", INDEX_REFERENCE],
["the opposite platform", ARM64_REFERENCE],
["a different official digest", `${DCODE_BASE_IMAGE}@sha256:${"f".repeat(64)}`],
])("rejects %s as the amd64 onboarding reference", (_label, reference) => {
expect(() =>
parseDcodeBaseImagePublicationEvidence(
publicationEvidence(),
publicationEnvironment({
[DCODE_BASE_IMAGE_ENV]: `${DCODE_BASE_IMAGE}@sha256:${"f".repeat(64)}`,
}),
publicationEnvironment({ [DCODE_BASE_IMAGE_ENV]: reference }),
),
).toThrow(/does not match the published base contract/);
).toThrow(/does not match the published amd64 platform reference/);
});

it("prefers the selected manual candidate over the trusted workflow SHA", () => {
Expand Down Expand Up @@ -192,7 +194,7 @@ describe("Deep Agents Code published base runtime evidence", () => {
loadDcodeBaseImagePublicationEvidence(
DCODE_BASE_IMAGE_TARGET_ID,
`/missing-dcode-base-evidence-${process.pid}.json`,
{ [DCODE_BASE_IMAGE_ENV]: INDEX_REFERENCE },
{ [DCODE_BASE_IMAGE_ENV]: AMD64_REFERENCE },
),
).toBeUndefined();
});
Expand All @@ -204,7 +206,7 @@ describe("Deep Agents Code published base runtime evidence", () => {
`/missing-dcode-base-evidence-${process.pid}.json`,
{
GITHUB_ACTIONS: "true",
[DCODE_BASE_IMAGE_ENV]: INDEX_REFERENCE,
[DCODE_BASE_IMAGE_ENV]: AMD64_REFERENCE,
},
),
).toThrow(/GitHub Actions run is missing published base evidence/);
Expand All @@ -218,10 +220,19 @@ describe("Deep Agents Code published base runtime evidence", () => {
/did not use the published linux\/amd64 base digest/,
],
[
"the opposite platform digest",
"the opposite platform digest for amd64",
resolutionMetadata({ digest: ARM64_DIGEST, ref: ARM64_REFERENCE }),
/did not use the published linux\/amd64 base digest/,
],
[
"self-consistent opposite-platform metadata",
resolutionMetadata({
architecture: "arm64",
digest: ARM64_DIGEST,
ref: ARM64_REFERENCE,
}),
/did not use the published linux\/amd64 base digest/,
],
[
"a different image repository",
resolutionMetadata({ imageName: "ghcr.io/example/base" }),
Expand All @@ -240,7 +251,7 @@ describe("Deep Agents Code published base runtime evidence", () => {
[
"an unsupported platform",
resolutionMetadata({ architecture: "ppc64le" }),
/used unsupported platform/,
/did not use the published linux\/amd64 base digest/,
],
])("rejects %s", (_label, metadata, expectedError) => {
const contract = parseDcodeBaseImagePublicationEvidence(
Expand Down
13 changes: 6 additions & 7 deletions tools/e2e/dcode-base-image-contract.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { fileURLToPath } from "node:url";
const AGENT = "langchain-deepagents-code";
const IMAGE = "ghcr.io/nvidia/nemoclaw/langchain-deepagents-code-sandbox-base";
const PLATFORMS = ["linux/amd64", "linux/arm64"] as const;
export const DCODE_BASE_IMAGE_TARGET_PLATFORM = "linux/amd64" as const;
const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/u;
const SHA_PATTERN = /^[0-9a-f]{40}$/u;
const IMPORT_MARKER = "nemoclaw-dcode-base-imports-ok";
Expand Down Expand Up @@ -120,10 +121,7 @@ export function validateDcodeBaseImageContract(
if (contract.sourceRevision !== expected.headSha) {
throw new Error("base contract source revision does not match the selected publication");
}
if (
contract.run.id !== expected.runId ||
contract.run.attempt !== expected.runAttempt
) {
if (contract.run.id !== expected.runId || contract.run.attempt !== expected.runAttempt) {
throw new Error("base contract run does not match the selected publication");
}
return contract;
Expand All @@ -144,7 +142,7 @@ export function validateDcodeBaseImageImports(
"run",
"--rm",
"--platform",
"linux/amd64",
DCODE_BASE_IMAGE_TARGET_PLATFORM,
"--network",
"none",
"--cap-drop",
Expand Down Expand Up @@ -186,10 +184,11 @@ export function main(argv = process.argv.slice(2), env = process.env): void {
headSha: env.PUBLICATION_HEAD_SHA ?? "",
},
);
validateDcodeBaseImageImports(contract.reference);
const amd64Reference = contract.platformReferences[DCODE_BASE_IMAGE_TARGET_PLATFORM];
validateDcodeBaseImageImports(amd64Reference);
appendFileSync(
outputPath,
`base_ref=${contract.reference}\ncontract=${JSON.stringify(contract)}\n`,
`base_ref=${amd64Reference}\ncontract=${JSON.stringify(contract)}\n`,
"utf8",
);
}
Expand Down
Loading