diff --git a/internal/cli/incident.go b/internal/cli/incident.go index 61515bb..2da3f92 100644 --- a/internal/cli/incident.go +++ b/internal/cli/incident.go @@ -80,7 +80,7 @@ func newIncidentListCmd() *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List incidents", - Long: curatedLong("List incidents matching the given filters. The --since/--until window must be < 31 days; --limit max is 100.", "Incidents", "List"), + Long: curatedLong("List incidents matching the given filters. The --since/--until window must be < 31 days; --limit max is 100.\n\nSee also: fduty insight for aggregated metrics (MTTA, MTTR, noise reduction) instead of paginating raw incidents.", "Incidents", "List"), RunE: func(cmd *cobra.Command, args []string) error { return runCommand(cmd, args, func(ctx *RunContext) error { startTime, err := timeutil.Parse(since) diff --git a/internal/cli/insight.go b/internal/cli/insight.go index 182c75b..d61729d 100644 --- a/internal/cli/insight.go +++ b/internal/cli/insight.go @@ -13,7 +13,7 @@ import ( func newInsightCmd() *cobra.Command { cmd := &cobra.Command{ Use: "insight", - Short: "Query insight metrics", + Short: "Query aggregated incident metrics by team, responder, or channel", } // insight team/channel/responder are now served by the generated commands // (richer flag set: severities, *_ids, fields, aggregate-unit, …; relative diff --git a/internal/cli/team.go b/internal/cli/team.go index 1d82ac2..6aa35e2 100644 --- a/internal/cli/team.go +++ b/internal/cli/team.go @@ -92,23 +92,40 @@ func newTeamGetCmd() *cobra.Command { ) cmd := &cobra.Command{ - Use: "get", + Use: "get []", Short: "Get team detail", Long: curatedLong(`Get detailed information about a specific team. -Specify the team by exactly one of: --id, --name, or --ref-id. +Specify the team by positional ID, or by exactly one of: --id, --name, or --ref-id. The output includes team metadata, member list, and audit information. Examples: + flashduty team get 123 flashduty team get --id 123 flashduty team get --name "SRE Team" flashduty team get --ref-id "hr-dept-42" flashduty team get --id 123 --json`, "Teams", "ReadInfo"), + Args: optionalArg("id"), PreRunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 1 { + for _, f := range []string{"id", "name", "ref-id"} { + if cmd.Flags().Changed(f) { + return fmt.Errorf("positional cannot be combined with --%s", f) + } + } + return nil + } return requireExactlyOneFlag(cmd, "id", "name", "ref-id") }, RunE: func(cmd *cobra.Command, args []string) error { return runCommand(cmd, args, func(ctx *RunContext) error { + if len(ctx.Args) == 1 { + id, err := strconv.ParseInt(ctx.Args[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid team id %q: must be a number", ctx.Args[0]) + } + teamID = id + } team, _, err := ctx.Client.Teams.ReadInfo(cmdContext(ctx.Cmd), &flashduty.TeamInfoRequest{ TeamID: uint64(teamID), TeamName: teamName, diff --git a/internal/cli/team_get_test.go b/internal/cli/team_get_test.go new file mode 100644 index 0000000..265f12c --- /dev/null +++ b/internal/cli/team_get_test.go @@ -0,0 +1,38 @@ +package cli + +import "testing" + +func TestTeamGetAcceptsPositionalID(t *testing.T) { + cmd := newTeamGetCmd() + // MaximumNArgs(1): two positional args should be rejected + if cmd.Args != nil { + if err := cmd.Args(cmd, []string{"123456", "789"}); err == nil { + t.Fatal("team get should reject two positional args") + } + } +} + +func TestTeamGetNoArgNoFlagFails(t *testing.T) { + cmd := newTeamGetCmd() + err := cmd.PreRunE(cmd, []string{}) + if err == nil { + t.Fatal("expected error when no positional arg and no flag provided") + } +} + +func TestTeamGetPositionalArgBypassesPreRunE(t *testing.T) { + cmd := newTeamGetCmd() + err := cmd.PreRunE(cmd, []string{"123456"}) + if err != nil { + t.Fatalf("PreRunE should succeed with positional arg, got: %v", err) + } +} + +func TestTeamGetPositionalAndFlagConflictFails(t *testing.T) { + cmd := newTeamGetCmd() + _ = cmd.Flags().Set("id", "456") + err := cmd.PreRunE(cmd, []string{"123"}) + if err == nil { + t.Fatal("expected error when positional arg and --id flag are both provided") + } +}