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
5 changes: 4 additions & 1 deletion actions/setup/js/handle_agent_failure.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,10 @@ function buildFailureMatchCategories(options) {
if (options.hasDailyAICExceeded) categories.push("daily_ai_credits_exceeded");
if (options.isAWFFirewallStartupFailed) categories.push("awf_firewall_startup_failed");

if (options.agentConclusion === "failure" && !options.isTimedOut) {
// Keep agent_failure as the fallback class only when no existing
// specific category already explains the failure cause.
const hasSpecificFailureCategory = categories.length > 0;
if (options.agentConclusion === "failure" && !options.isTimedOut && !hasSpecificFailureCategory) {
categories.push("agent_failure");
}

Expand Down
29 changes: 27 additions & 2 deletions actions/setup/js/handle_agent_failure.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4701,6 +4701,16 @@ describe("handle_agent_failure", () => {
expect(categories).toContain("report_incomplete");
});

it("does not add agent_failure when a specific category already exists", () => {
const categories = buildFailureMatchCategories({
agentConclusion: "failure",
isTimedOut: false,
hasReportIncomplete: true,
});
expect(categories).toContain("report_incomplete");
expect(categories).not.toContain("agent_failure");
});

it("returns sorted categories", () => {
const categories = buildFailureMatchCategories({
hasMissingSafeOutputs: true,
Expand All @@ -4727,7 +4737,7 @@ describe("handle_agent_failure", () => {
isAWFFirewallStartupFailed: true,
});
expect(categories).toContain("awf_firewall_startup_failed");
expect(categories).toContain("agent_failure");
expect(categories).not.toContain("agent_failure");
});

it("does not return awf_firewall_startup_failed category when isAWFFirewallStartupFailed is false", () => {
Expand Down Expand Up @@ -4808,6 +4818,7 @@ describe("handle_agent_failure", () => {
delete process.env.GITHUB_WORKSPACE;
delete process.env.GH_AW_FAILURE_CATEGORIES_FILTER;
delete process.env.GH_AW_FAILURE_EXCLUDED_CATEGORIES_FILTER;
delete process.env.GH_AW_INFERENCE_ACCESS_ERROR;

if (tmpDir && fs.existsSync(tmpDir)) {
fs.rmSync(tmpDir, { recursive: true, force: true });
Expand All @@ -4819,34 +4830,48 @@ describe("handle_agent_failure", () => {
name: "include-only filter creates issue when category matches",
includeFilter: ["agent_failure"],
excludeFilter: null,
extraEnv: {},
shouldCreateIssue: true,
},
{
name: "include-only filter skips issue when category does not match",
includeFilter: ["missing_safe_outputs"],
excludeFilter: null,
extraEnv: {},
shouldCreateIssue: false,
},
{
name: "include-only filter skips infra-classified failures when only agent_failure is included",
includeFilter: ["agent_failure"],
excludeFilter: null,
extraEnv: { GH_AW_INFERENCE_ACCESS_ERROR: "true" },
shouldCreateIssue: false,
},
{
name: "exclude-only filter skips issue when category is excluded",
includeFilter: null,
excludeFilter: ["agent_failure"],
extraEnv: {},
shouldCreateIssue: false,
},
{
name: "mixed include+exclude filter skips issue when excluded category is present",
includeFilter: ["agent_failure"],
excludeFilter: ["agent_failure"],
extraEnv: {},
shouldCreateIssue: false,
},
])("$name", async ({ includeFilter, excludeFilter, shouldCreateIssue }) => {
])("$name", async ({ includeFilter, excludeFilter, extraEnv, shouldCreateIssue }) => {
const { createIssueMock } = setupGithubMock();
if (includeFilter) {
process.env.GH_AW_FAILURE_CATEGORIES_FILTER = JSON.stringify(includeFilter);
}
if (excludeFilter) {
process.env.GH_AW_FAILURE_EXCLUDED_CATEGORIES_FILTER = JSON.stringify(excludeFilter);
}
for (const [key, value] of Object.entries(extraEnv || {})) {
process.env[key] = value;
}

await main();

Expand Down
Loading