Skip to content

Commit 7dda9cb

Browse files
authored
feat(cli): --integration filter on alert list and alert-event list (#131)
* docs(skills): status-page card — confirm gate + rollback reporting for public-page structure mutations * feat(cli): --integration filter on alert list and alert-event list Both /alert/list and /alert-event/list accept an integration_ids filter server-side, and the pinned SDK already carries IntegrationIDs []int64 on AlertListRequest and AlertEventGlobalListRequest. The hand-curated alert list and alert-event list commands never wired it, so filtering by integration required piping through jq client-side. Add --integration (comma-separated integration IDs) to both commands, mirroring the existing --channel pattern end-to-end. On alert-event list this is distinct from the existing --integration-type flag, which filters by plugin key rather than numeric ID; help text calls out the distinction. * docs(skills): regenerate alert card for --integration Regenerate the GENERATED:alert fence in skills/flashduty/reference/alert.md via make gen-cards to pick up the new --integration flag on alert list.
1 parent 45d6c20 commit 7dda9cb

4 files changed

Lines changed: 80 additions & 3 deletions

File tree

internal/cli/alert.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func newAlertCmd() *cobra.Command {
2424
}
2525

2626
func newAlertListCmd() *cobra.Command {
27-
var severity, channel, since, until, fields string
27+
var severity, channel, integration, since, until, fields string
2828
var active, recovered, muted bool
2929
var limit, page int
3030

@@ -75,6 +75,14 @@ func newAlertListCmd() *cobra.Command {
7575
req.ChannelIDs = channelIDs
7676
}
7777

78+
if integration != "" {
79+
integrationIDs, err := parseIntSlice(integration)
80+
if err != nil {
81+
return fmt.Errorf("invalid --integration: %w", err)
82+
}
83+
req.IntegrationIDs = integrationIDs
84+
}
85+
7886
result, _, err := ctx.Client.Alerts.ReadList(cmdContext(ctx.Cmd), req)
7987
if err != nil {
8088
return err
@@ -108,6 +116,7 @@ func newAlertListCmd() *cobra.Command {
108116
registerEnumFlag(cmd, "severity", severityEnum...)
109117
cmd.Flags().BoolVar(&recovered, "recovered", false, "Show recovered only")
110118
cmd.Flags().StringVar(&channel, "channel", "", "Comma-separated channel IDs")
119+
cmd.Flags().StringVar(&integration, "integration", "", "Comma-separated integration IDs")
111120
cmd.Flags().BoolVar(&muted, "muted", false, "Show ever-muted only")
112121
cmd.Flags().StringVar(&since, "since", "24h", "Start time")
113122
cmd.Flags().StringVar(&until, "until", "now", "End time")

internal/cli/alert_event.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func newAlertEventCmd() *cobra.Command {
1818
}
1919

2020
func newAlertEventListCmd() *cobra.Command {
21-
var severity, channel, integrationType, since, until, fields string
21+
var severity, channel, integration, integrationType, since, until, fields string
2222
var limit, page int
2323

2424
cmd := &cobra.Command{
@@ -60,6 +60,14 @@ func newAlertEventListCmd() *cobra.Command {
6060
input.ChannelIDs = channelIDs
6161
}
6262

63+
if integration != "" {
64+
integrationIDs, err := parseIntSlice(integration)
65+
if err != nil {
66+
return fmt.Errorf("invalid --integration: %w", err)
67+
}
68+
input.IntegrationIDs = integrationIDs
69+
}
70+
6371
if integrationType != "" {
6472
input.IntegrationTypes = parseStringSlice(integrationType)
6573
}
@@ -101,7 +109,8 @@ func newAlertEventListCmd() *cobra.Command {
101109
cmd.Flags().StringVar(&severity, "severity", "", "Filter: Critical,Warning,Info (comma-separated)")
102110
cmd.Flags().StringVar(&channel, "channel", "", "Comma-separated channel IDs")
103111
registerEnumFlag(cmd, "severity", severityEnum...)
104-
cmd.Flags().StringVar(&integrationType, "integration-type", "", "Comma-separated integration types")
112+
cmd.Flags().StringVar(&integration, "integration", "", "Comma-separated integration IDs")
113+
cmd.Flags().StringVar(&integrationType, "integration-type", "", "Comma-separated integration types (plugin keys, e.g. AliCloud,Prometheus) — not integration IDs; use --integration for that")
105114
cmd.Flags().StringVar(&since, "since", "1h", "Start time")
106115
cmd.Flags().StringVar(&until, "until", "now", "End time")
107116
cmd.Flags().IntVar(&limit, "limit", 20, "Max results")

internal/cli/alert_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cli
22

33
import (
4+
"fmt"
45
"strings"
56
"testing"
67
)
@@ -62,6 +63,63 @@ func TestCommandAlertListNoStatusFilterOmitsIsActive(t *testing.T) {
6263
}
6364
}
6465

66+
// TestCommandAlertListIntegrationFlagReachesWire guards --integration on
67+
// `alert list`: a comma-separated value must parse via the shared
68+
// parseIntSlice helper (same as --channel) and forward as integration_ids on
69+
// /alert/list.
70+
func TestCommandAlertListIntegrationFlagReachesWire(t *testing.T) {
71+
saveAndResetGlobals(t)
72+
stub := newGFStub(t)
73+
74+
if _, err := execCommand("alert", "list", "--integration", "10001,10002"); err != nil {
75+
t.Fatalf("execCommand: %v", err)
76+
}
77+
if stub.lastPath != "/alert/list" {
78+
t.Fatalf("expected /alert/list, got %q", stub.lastPath)
79+
}
80+
if got, want := fmt.Sprint(stub.lastBody["integration_ids"]), "[10001 10002]"; got != want {
81+
t.Fatalf("expected integration_ids %q, got %q", want, got)
82+
}
83+
}
84+
85+
// TestCommandAlertListIntegrationFlagInvalidValue guards the error path: a
86+
// non-numeric --integration value must fail with a named error instead of
87+
// silently dropping the filter.
88+
func TestCommandAlertListIntegrationFlagInvalidValue(t *testing.T) {
89+
saveAndResetGlobals(t)
90+
newGFStub(t)
91+
92+
_, err := execCommand("alert", "list", "--integration", "abc")
93+
if err == nil {
94+
t.Fatal("expected an error, got nil")
95+
}
96+
if !strings.Contains(err.Error(), "invalid --integration") {
97+
t.Fatalf("expected an \"invalid --integration\" error, got: %v", err)
98+
}
99+
}
100+
101+
// TestCommandAlertEventListIntegrationFlagReachesWire guards --integration on
102+
// `alert-event list`: it must forward as integration_ids on /alert-event/list,
103+
// distinct from --integration-type which forwards as integration_types.
104+
func TestCommandAlertEventListIntegrationFlagReachesWire(t *testing.T) {
105+
saveAndResetGlobals(t)
106+
stub := newGFStub(t)
107+
108+
if _, err := execCommand("alert-event", "list",
109+
"--integration", "10001,10002", "--integration-type", "AliCloud"); err != nil {
110+
t.Fatalf("execCommand: %v", err)
111+
}
112+
if stub.lastPath != "/alert-event/list" {
113+
t.Fatalf("expected /alert-event/list, got %q", stub.lastPath)
114+
}
115+
if got, want := fmt.Sprint(stub.lastBody["integration_ids"]), "[10001 10002]"; got != want {
116+
t.Fatalf("expected integration_ids %q, got %q", want, got)
117+
}
118+
if got, want := fmt.Sprint(stub.lastBody["integration_types"]), "[AliCloud]"; got != want {
119+
t.Fatalf("expected integration_types %q, got %q", want, got)
120+
}
121+
}
122+
65123
// TestCommandAlertMergeCommentFileReachesWireByteForByte guards the same
66124
// shell-interpolation fix applied to incident comment (see
67125
// TestCommandIncidentCommentPreservesShellMetacharactersByteForByte): alert

skills/flashduty/reference/alert.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ List alerts
9090
- `--active` bool
9191
- `--channel` string
9292
- `--fields` string
93+
- `--integration` string
9394
- `--limit` int
9495
- `--muted` bool
9596
- `--page` int

0 commit comments

Comments
 (0)