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
24 changes: 22 additions & 2 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5024,7 +5024,7 @@ jobs:
strategy:
fail-fast: false
matrix:
agent: [openclaw]
agent: [openclaw, hermes]
env:
E2E_JOB: "1"
E2E_TARGET_ID: "bedrock-runtime-compatible-anthropic"
Expand All @@ -5039,6 +5039,26 @@ jobs:
NEMOCLAW_SANDBOX_NAME: e2e-bedrock-${{ matrix.agent }}
OPENSHELL_GATEWAY: "nemoclaw"
steps:
- id: trusted_hermes_swap
name: Provision trusted Hermes E2E swap
if: ${{ github.repository == 'NVIDIA/NemoClaw' && github.ref == 'refs/heads/main' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.agent == 'hermes' }}
shell: /bin/bash --noprofile --norc -e -o pipefail {0}
env:
BASH_ENV: /dev/null
CHECKOUT_SHA: ${{ inputs.checkout_sha }}
DISPATCH_SHA: ${{ github.sha }}
ENV: /dev/null
EVENT_NAME: ${{ github.event_name }}
EXPECTED_WORKFLOW_SHA: ${{ inputs.workflow_sha }}
LC_ALL: C
REF: ${{ github.ref }}
REPOSITORY: ${{ github.repository }}
RUNNER_ARCH_KIND: ${{ runner.arch }}
RUNNER_ENVIRONMENT_KIND: ${{ runner.environment }}
RUNNER_OS_KIND: ${{ runner.os }}
WORKFLOW_SHA: ${{ github.workflow_sha }}
run: *trusted-hermes-e2e-swap

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ inputs.checkout_repository || github.repository }}
Expand All @@ -5052,7 +5072,7 @@ jobs:

- name: Run Bedrock Runtime compatible Anthropic live test
# Preserves the fake Bedrock Runtime endpoint, /etc/hosts mapping,
# source CLI onboard, OpenShell adapter route, OpenClaw runtime probe,
# source CLI onboard, OpenShell adapter route, agent runtime probes,
# and leak-scan contract.
run: |
set -euo pipefail
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type SwapWorkflow = {

const PROTECTED_JOBS = [
"agent-turn-latency",
"bedrock-runtime-compatible-anthropic",
"channels-stop-start",
"common-egress-agent",
"hermes-discord",
Expand Down
2 changes: 1 addition & 1 deletion test/pr-e2e-gate-shards.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function temporaryE2eWorkflow(source: string): string {
describe("PR E2E shard policy", () => {
it("derives Bedrock signal shards from the agent matrix (#6938)", () => {
expect(expectedSignalShards(["bedrock-runtime-compatible-anthropic"])).toEqual({
"bedrock-runtime-compatible-anthropic": ["openclaw"],
"bedrock-runtime-compatible-anthropic": ["openclaw", "hermes"],
});
});

Expand Down
39 changes: 38 additions & 1 deletion test/pr-risk-plan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("deterministic PR risk plan", () => {
const second = plan("src/lib/onboard.ts", "src/lib/state/registry.ts");

expect(first).toEqual(second);
expect(first.version).toBe(10);
expect(first.version).toBe(11);
expect(first.headSha).toBe(HEAD_SHA);
expect(first.planHash).toMatch(/^[a-f0-9]{64}$/u);
expect(first.changedFiles).toEqual(["src/lib/onboard.ts", "src/lib/state/registry.ts"]);
Expand Down Expand Up @@ -117,6 +117,43 @@ describe("deterministic PR risk plan", () => {
]);
});

it("selects every Hermes managed-policy live E2E job (#8008)", () => {
const changedFiles = [
"agents/hermes/config/managed-policy.ts",
"agents/hermes/managed_policy.py",
"agents/hermes/seed-dashboard-config.py",
"src/lib/hermes-managed-route.ts",
];
const result = plan(...changedFiles);

expect(result.families).toContainEqual(
expect.objectContaining({
id: "focused-e2e",
matchedFiles: changedFiles,
requiredJobs: [
"bedrock-runtime-compatible-anthropic",
"channels-stop-start",
"dashboard-remote-bind",
"hermes-e2e",
"hermes-inference-switch",
"hermes-shields-config",
"security-posture",
],
}),
);
expect(riskPlanRequiredJobIds(result)).toEqual(
expect.arrayContaining([
"bedrock-runtime-compatible-anthropic",
"channels-stop-start",
"dashboard-remote-bind",
"hermes-e2e",
"hermes-inference-switch",
"hermes-shields-config",
"security-posture",
]),
);
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

it("leaves E2E support-only changes in the fast e2e-support project (#7921)", () => {
const changedFiles = ["test/e2e/support/workflow-plan.test.ts"];
const focusedE2eJobs = focusedE2eJobsForChangedFiles(changedFiles);
Expand Down
38 changes: 34 additions & 4 deletions tools/advisors/risk-plan.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { createHash } from "node:crypto";

export const RISK_PLAN_VERSION = 10 as const;
export const RISK_PLAN_VERSION = 11 as const;

export const PR_E2E_TYPED_TARGET_IDS = [
"ubuntu-repo-cloud-langchain-deepagents-code",
Expand All @@ -25,6 +25,24 @@ const MANAGED_STARTUP_E2E_JOB_IDS = [
"issue-4462-scope-upgrade-approval",
"openclaw-inference-switch",
] as const;
const HERMES_MANAGED_POLICY_E2E_JOB_IDS = [
"bedrock-runtime-compatible-anthropic",
"channels-stop-start",
"dashboard-remote-bind",
"hermes-e2e",
"hermes-inference-switch",
"hermes-shields-config",
"security-posture",
] as const;
const HERMES_MANAGED_POLICY_FILES = new Set([
"agents/hermes/hermes-wrapper.py",
"agents/hermes/image-build-probes.py",
"agents/hermes/managed_policy.py",
"agents/hermes/patch-profile-policy-defaults.py",
"agents/hermes/seed-dashboard-config.py",
"agents/hermes/start.sh",
"src/lib/hermes-managed-route.ts",
]);

export type RiskTier = 0 | 1 | 2 | 3;
export type RiskFamilyId =
Expand Down Expand Up @@ -165,7 +183,7 @@ export function focusedPrE2eTargetsForChangedFiles(
export function focusedPrE2eJobsForChangedFiles(
changedFiles: readonly string[],
): TrustedFocusedE2eJob[] {
const matchedFiles = stableUnique(
const managedStartupFiles = stableUnique(
changedFiles.filter(
(file) =>
(file.startsWith("src/lib/onboard/managed-startup/") ||
Expand All @@ -174,8 +192,20 @@ export function focusedPrE2eJobsForChangedFiles(
isRuntimeRelevant(file),
),
);
if (matchedFiles.length === 0) return [];
return MANAGED_STARTUP_E2E_JOB_IDS.map((id) => ({ id, matchedFiles }));
const hermesManagedPolicyFiles = stableUnique(
changedFiles.filter(
(file) =>
(file.startsWith("agents/hermes/config/") || HERMES_MANAGED_POLICY_FILES.has(file)) &&
isRuntimeRelevant(file),
),
);
return [
...MANAGED_STARTUP_E2E_JOB_IDS.map((id) => ({ id, matchedFiles: managedStartupFiles })),
...HERMES_MANAGED_POLICY_E2E_JOB_IDS.map((id) => ({
id,
matchedFiles: hermesManagedPolicyFiles,
})),
].filter((selection) => selection.matchedFiles.length > 0);
}

export const RISK_RULES: readonly RiskRule[] = [
Expand Down
1 change: 1 addition & 0 deletions tools/e2e/trusted-hermes-swap-workflow-boundary.mts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export const TRUSTED_HERMES_SWAP_SCRIPT = [

const JOB_CONDITIONS = {
"agent-turn-latency": `\${{ ${TRUSTED_HERMES_SWAP_IF} }}`,
"bedrock-runtime-compatible-anthropic": `\${{ ${TRUSTED_HERMES_SWAP_IF} && matrix.agent == 'hermes' }}`,
"channels-stop-start": `\${{ ${TRUSTED_HERMES_SWAP_IF} && matrix.agent == 'hermes' }}`,
"common-egress-agent": `\${{ ${TRUSTED_HERMES_SWAP_IF} && matrix.scenario == 'hermes-open-reference' }}`,
"hermes-discord": `\${{ ${TRUSTED_HERMES_SWAP_IF} }}`,
Expand Down
9 changes: 3 additions & 6 deletions tools/e2e/workflow-boundary.mts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@ import { validateRunnerComparisonWorkflowBoundary } from "./runner-comparison-wo
import { validateRunnerPressureWorkflow } from "./runner-pressure-workflow-boundary.mts";
import { validateSandboxOperationsWorkflow } from "./sandbox-operations-workflow-boundary.mts";
import { validateSecurityPostureWorkflow } from "./security-posture-workflow-boundary.mts";
import {
normalizeE2eSelectorIds,
selectorsForCanonicalE2eId,
} from "./selector-aliases.mts";
import { normalizeE2eSelectorIds, selectorsForCanonicalE2eId } from "./selector-aliases.mts";
import {
validateTrustedHermesSwapHelperSource,
validateTrustedHermesSwapWorkflow,
Expand Down Expand Up @@ -3735,8 +3732,8 @@ function validateBedrockRuntimeCompatibleAnthropicJob(
errors.push("bedrock-runtime-compatible-anthropic strategy.fail-fast must be false");
}
const matrix = asRecord(strategy.matrix);
if (!Array.isArray(matrix.agent) || matrix.agent.join(",") !== "openclaw") {
errors.push("bedrock-runtime-compatible-anthropic matrix.agent must be openclaw");
if (!Array.isArray(matrix.agent) || matrix.agent.join(",") !== "openclaw,hermes") {
errors.push("bedrock-runtime-compatible-anthropic matrix.agent must be openclaw,hermes");
}

const jobEnv = asRecord(job.env);
Expand Down
Loading