Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2589,7 +2589,9 @@ jobs:
E2E_WORKLOAD_SOURCE: "managed-image"
RELEASE_E2E_ACTIVATION_PATH: ci/protected-managed-image-runtime-activation-v1.json
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
NEMOCLAW_E2E_EXPECTED_SHA: ${{ inputs.checkout_sha }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
NEMOCLAW_E2E_SHARD: linux-amd64-gpu
NEMOCLAW_E2E_TESTED_ROOT: ${{ github.workspace }}/.candidate-runtime
NEMOCLAW_NON_INTERACTIVE: "1"
NEMOCLAW_PROTECTED_MANAGED_IMAGE_BASE_SHA: ${{ inputs.base_sha || github.event.before || github.sha }}
NEMOCLAW_PROTECTED_MANAGED_IMAGE_BUILD_CACHE: ${{ github.workspace }}/.protected-managed-image-build-cache/linux-amd64
Expand Down
16 changes: 16 additions & 0 deletions test/e2e-risk-signal-reporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ describe("E2E risk signal reporter", () => {
expect(() => configuredEnvironment(env, () => "c".repeat(40))).toThrow(/checked-out HEAD/u);
});

it("attests an explicit tested root when trusted code runs beside the candidate checkout", () => {
const env = {
E2E_ARTIFACT_DIR: "/tmp/e2e-risk-signal-test",
E2E_TARGET_ID: "managed-image-protected-runtime",
GITHUB_WORKSPACE: "/workspace/trusted",
NEMOCLAW_E2E_EXPECTED_SHA: EXPECTED_SHA,
NEMOCLAW_E2E_CORRELATION_ID: CORRELATION_ID,
NEMOCLAW_E2E_SHARD: "linux-amd64-gpu",
NEMOCLAW_E2E_TESTED_ROOT: "/workspace/trusted/.candidate-runtime",
};
const resolveHead = vi.fn(() => EXPECTED_SHA);

expect(configuredEnvironment(env, resolveHead)?.testedSha).toBe(EXPECTED_SHA);
expect(resolveHead).toHaveBeenCalledWith("/workspace/trusted/.candidate-runtime");
});

it("writes pass, failure, skip, and pending counts for the tested commit", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-risk-signal-"));
try {
Expand Down
10 changes: 10 additions & 0 deletions test/e2e/support/managed-image-protected-runtime-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ describe("protected managed-image runtime workflow boundary", () => {
expect(validateManagedImageProtectedRuntimeWorkflow(value)).toEqual([]);
});

it("binds protected risk evidence to the isolated exact candidate checkout", () => {
const value = workflow();
const jobEnv = runtimeJob(value).env as Record<string, unknown>;
jobEnv.NEMOCLAW_E2E_TESTED_ROOT = "${{ github.workspace }}";

expect(validateManagedImageProtectedRuntimeWorkflow(value)).toContain(
"managed-image-protected-runtime env must bind NEMOCLAW_E2E_TESTED_ROOT to ${{ github.workspace }}/.candidate-runtime",
);
});

it("does not record manual PR risk signals on main pushes", () => {
const value = workflow();
const jobEnv = multiarchJob(value).env as Record<string, unknown>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ export function validateManagedImageProtectedRuntimeWorkflow(workflow: WorkflowR
E2E_TARGET_ID: JOB_ID,
E2E_WORKLOAD_SOURCE: "managed-image",
RELEASE_E2E_ACTIVATION_PATH: ACTIVATION_PATH,
NEMOCLAW_E2E_EXPECTED_SHA: "${{ inputs.checkout_sha }}",
NEMOCLAW_E2E_SHARD: "linux-amd64-gpu",
NEMOCLAW_E2E_TESTED_ROOT: "${{ github.workspace }}/.candidate-runtime",
NEMOCLAW_NON_INTERACTIVE: "1",
NEMOCLAW_PROTECTED_MANAGED_IMAGE_BASE_SHA:
"${{ inputs.base_sha || github.event.before || github.sha }}",
Expand Down
7 changes: 6 additions & 1 deletion tools/e2e/risk-signal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { execFileSync } from "node:child_process";
import path from "node:path";

export const RISK_SIGNAL_FILE = "risk-signal.json";

Expand Down Expand Up @@ -73,7 +74,11 @@ export function configuredRiskSignalEnvironment(
if (!CORRELATION_PATTERN.test(values.correlationId)) {
throw new Error("risk signal requires a lowercase UUIDv4 correlation id");
}
const testedSha = resolveHead(env.GITHUB_WORKSPACE ?? process.cwd());
const testedRoot = env.NEMOCLAW_E2E_TESTED_ROOT ?? env.GITHUB_WORKSPACE ?? process.cwd();
if (!path.isAbsolute(testedRoot)) {
throw new Error("risk signal requires an absolute tested root");
}
const testedSha = resolveHead(testedRoot);
if (!SHA_PATTERN.test(testedSha) || testedSha !== values.expectedSha) {
throw new Error("risk signal checked-out HEAD does not match the expected SHA");
}
Expand Down
Loading