diff --git a/packages/cli/test/lib/api/alerts.test.ts b/packages/cli/test/lib/api/alerts.test.ts index 469ceccc5..dc76f26a5 100644 --- a/packages/cli/test/lib/api/alerts.test.ts +++ b/packages/cli/test/lib/api/alerts.test.ts @@ -604,6 +604,38 @@ describe("createMetricAlertRule", () => { ]); }); + test("drops empty trigger actions from detector conditions", async () => { + let sentBody: Record = {}; + globalThis.fetch = mockFetch(async (input, init) => { + sentBody = (await new Request(input!, init).json()) as Record< + string, + unknown + >; + return Response.json(metricDetector({ id: "1" }), { status: 201 }); + }); + + await createMetricAlertRule("test-org", { + name: "Error spike", + query: "is:unresolved", + aggregate: "count()", + dataset: "errors", + timeWindow: 5, + triggers: [ + { label: "critical", alertThreshold: 11, actions: [] }, + { label: "warning", alertThreshold: 5, actions: [] }, + ], + projects: ["backend"], + }); + + expect( + (sentBody.conditionGroup as Record).conditions, + ).toEqual([ + { type: "gt", comparison: 11, conditionResult: 75 }, + { type: "gt", comparison: 5, conditionResult: 50 }, + { type: "lte", comparison: 11, conditionResult: 0 }, + ]); + }); + test("passes native detector conditions through unchanged", async () => { let sentBody: Record = {}; globalThis.fetch = mockFetch(async (input, init) => { diff --git a/packages/cli/test/types/metric-alert.test.ts b/packages/cli/test/types/metric-alert.test.ts index f918ed4d3..1f772dce4 100644 --- a/packages/cli/test/types/metric-alert.test.ts +++ b/packages/cli/test/types/metric-alert.test.ts @@ -87,6 +87,20 @@ describe("parseMetricTriggers", () => { ).not.toThrow(); }); + // Older CLI releases required a non-empty `actions` array on each trigger + // (CLI-20K). Callers still send `actions: []`; it must parse, not fail. + test("passes threshold triggers with an empty actions array", () => { + expect( + parseMetricTriggers([ + { label: "critical", alertThreshold: 11, actions: [] }, + { label: "warning", alertThreshold: 5, actions: [] }, + ]), + ).toEqual([ + { label: "critical", alertThreshold: 11, actions: [] }, + { label: "warning", alertThreshold: 5, actions: [] }, + ]); + }); + test("rejects trigger actions, pointing at --workflow", () => { expect(() => parseMetricTriggers([