Skip to content

Commit 7669432

Browse files
authored
STAC-24007: Update the help descriptions of the CLI (#128)
1 parent 6d277de commit 7669432

90 files changed

Lines changed: 755 additions & 319 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to OpenCode agents when working with code in this repository.
4+
5+
## Important Product Naming
6+
7+
**CRITICAL**: Always use "SUSE Observability" when referring to the product. "StackState" is deprecated and should not be used in new code, documentation, or communications.
8+
9+
## Project Overview
10+
11+
SUSE Observability CLI (`sts`) - A command-line tool for managing topology-powered observability within the SUSE Observability platform. Built with Go and Cobra framework.
12+
13+
## Development Environment
14+
15+
This project uses Nix Flakes for development environment management:
16+
17+
```bash
18+
# Enter development shell (requires Nix with flakes enabled)
19+
nix develop
20+
21+
# Build the CLI
22+
nix build
23+
24+
# Or use Go directly
25+
go build -o sts main.go
26+
```
27+
28+
## Common Commands
29+
30+
```bash
31+
# Run CLI locally
32+
go run main.go
33+
34+
# Run all tests
35+
go test -v ./...
36+
37+
# Run tests for a specific package
38+
go test -v ./cmd/monitor/...
39+
40+
# Run a single test
41+
go test -v ./cmd/monitor/... -run TestMonitorApply
42+
43+
# Lint
44+
golangci-lint run
45+
46+
# Regenerate OpenAPI clients (when openapi_version changes)
47+
nix develop -c ./scripts/generate_stackstate_api.sh
48+
```
49+
50+
## Architecture
51+
52+
### Command Structure Pattern
53+
54+
All commands follow noun/verb/flags structure:
55+
```
56+
sts [noun] [verb] [flags]
57+
```
58+
Example: `sts context save --api-url URL --api-token TOKEN`
59+
60+
### Key Components
61+
62+
- **Entry point**: `main.go` - Sets up DI container, logging, error handling
63+
- **Commands**: `cmd/` - Each subdirectory is a command group (monitor/, settings/, etc.)
64+
- **DI Container**: `internal/di/Deps` - Dependency injection for testability
65+
- **API Clients**: `generated/stackstate_api/` and `generated/stackstate_admin_api/` - Auto-generated from OpenAPI
66+
- **Output**: `internal/printer/Printer` - All output must go through this interface
67+
- **Errors**: `internal/common/CLIError` - Custom error type with exit codes and usage hints
68+
69+
### Code Generation
70+
71+
OpenAPI clients are generated from external specs:
72+
- Version pinned in `stackstate_openapi/openapi_version`
73+
- Custom templates in `stackstate_openapi/template/`
74+
- Generated code in `generated/` - do not edit manually
75+
76+
## Command Development Rules
77+
78+
From CMD_DEVELOPMENT.md - critical rules for consistency:
79+
80+
### Output
81+
- Always use `Printer` for stdout/stderr output
82+
- Every command must support both human-readable and JSON output (`-o json`)
83+
- Use logger for debug/verbose output, not Printer
84+
85+
### Errors
86+
- Return `CLIError` from commands, don't print errors directly
87+
- Set `ShowUsage=true` for input/parsing errors
88+
- Set `ShowUsage=false` for API/technical errors
89+
90+
### Help Text Requirements
91+
- `Use:` - Skeleton usage. Show required flags directly, mutually exclusive flags in `{}` with `|`
92+
- `Short:` - One sentence, no period, starts with verb
93+
- `Long:` - Full description with period
94+
- `Example:` - Copy-pasteable examples with `#` comments
95+
96+
### Naming
97+
- Nouns plural if pertaining to a set of entities
98+
- Reuse verbs: `apply`, `list`, `describe`, `export`
99+
- Flag shorthands must be consistent across all commands (e.g., `-f` always means `--file`)
100+
101+
## CLI Help Documentation Specialist
102+
103+
**CRITICAL AGENT**: This agent manages cobra.Command help text according to ADR 001 and ADR 002.
104+
105+
### Policy Overview
106+
Per ADR 001: CLI `--help` output is the **authoritative source** for command documentation. External docs provide overviews only. This means help text must be self-sufficient, consistent, and include practical examples.
107+
108+
### Use Field Rules
109+
- **Noun-level commands**: `Use: "context"` (command appended automatically)
110+
- **Noun-verb commands**: `Use: "save --url URL {--api-token TOKEN | --service-token TOKEN}"`
111+
- **Required flags**: Show without brackets: `--url URL`
112+
- **Mutually exclusive required**: Group in `{}` with `|`: `{--api-token TOKEN | --service-token TOKEN}`
113+
- **Mutually exclusive optional**: Group in `[]` with `|`: `[--format JSON | --format YAML]`
114+
- **Flag values**: Use UPPER-CASE placeholders: `URL`, `TOKEN`, `FILE`
115+
116+
### Short Field Rules
117+
- Start with **imperative verb** (Save, List, Delete, Show, Set, Validate)
118+
- Describe what the command does, not how
119+
- Use articles ("a", "the") appropriately
120+
- Maximum one sentence
121+
- **No period** at the end
122+
- Must add context beyond just command name
123+
124+
Examples:
125+
-`"Save a connection context to the CLI configuration"`
126+
-`"Save a context"`
127+
-`"List all configured connection contexts"`
128+
-`"List contexts"`
129+
130+
### Long Field Rules
131+
- Start with upper case, end with period
132+
- Can be multiple sentences
133+
- **Must add value** beyond Short - explain what the entity is, when to use, or outcome
134+
- Avoid excessive abbreviations
135+
- Provide context about the domain concept
136+
137+
Examples:
138+
-`"Save a connection context to the CLI configuration file. A context stores the URL and authentication credentials for a SUSE Observability server, allowing you to switch between different servers or environments."`
139+
-`"Save a context."`
140+
141+
### Example Field Rules
142+
- Use backtick-quoted multiline strings (not string concatenation)
143+
- Each example starts with `#` comment describing what it does
144+
- Comments: lowercase start, no period, imperative verb
145+
- Provide 2-3 examples covering common scenarios
146+
- Examples must be realistic and runnable
147+
- Cover different flag combinations when applicable
148+
149+
Format:
150+
```go
151+
Example: `# save a context with an API token
152+
sts context save --name production --url https://suse-observability.example.com --api-token xxxx-xxxx
153+
154+
# save a context with a service token for CI/CD
155+
sts context save --name ci-pipeline --url https://suse-observability.example.com --service-token xxxx-xxxx`
156+
```
157+
158+
### Flag Description Rules
159+
- Start with upper case, no period at the end
160+
- Describe what the flag does, not implementation details
161+
- Include default value mention if non-obvious
162+
163+
### Quality Checklist
164+
For every cobra.Command:
165+
- [ ] `Use` shows required flags and mutex groups correctly
166+
- [ ] `Short` starts with verb, no period, adds context beyond command name
167+
- [ ] `Long` adds value beyond `Short`, ends with period, explains domain concepts
168+
- [ ] `Example` has 2-3 realistic, copy-pasteable examples with lowercase comments
169+
- [ ] Flag descriptions are clear and properly capitalized
170+
- [ ] Uses "SUSE Observability" (not "StackState") in descriptions
171+
- [ ] No string concatenation - uses backtick multiline strings
172+
173+
### When to Invoke This Agent
174+
- Creating new commands
175+
- Modifying existing command help text
176+
- Code reviews involving cobra.Command changes
177+
- Ensuring consistency across all CLI help documentation
178+
179+
## Testing Patterns
180+
181+
Commands are tested using mock DI container:
182+
183+
```go
184+
func TestCommandName(t *testing.T) {
185+
cli := di.NewMockDeps(t)
186+
// Setup mocks
187+
// Execute command
188+
// Assert results
189+
}
190+
```
191+
192+
Test utilities in `internal/di/mock_deps.go` and `internal/di/command_test_util.go`.
193+
194+
## CI/CD
195+
196+
- Linting: golangci-lint v2.3.1 (see `.golangci.yml`)
197+
- Tests run on every PR
198+
- Releases via GoReleaser on version tags (`v*`)

cmd/agent.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
func AgentCommand(deps *di.Deps) *cobra.Command {
1010
cmd := &cobra.Command{
1111
Use: "agent",
12-
Short: "Manage the StackState agents",
13-
Long: "Manage the StackState agents.",
12+
Short: "Manage SUSE Observability agents and their registrations",
13+
Long: `Manage SUSE Observability agents. Agents collect and send topology, telemetry, and traces data from monitored systems to SUSE Observability.`,
1414
}
1515

1616
cmd.AddCommand(agent.ListCommand(deps))

cmd/agent/agent_list.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ import (
1616
func ListCommand(deps *di.Deps) *cobra.Command {
1717
cmd := &cobra.Command{
1818
Use: "list",
19-
Short: "List all registered agents",
20-
Long: "List all registered agents.",
21-
RunE: deps.CmdRunEWithApi(RunListCommand),
19+
Short: "List all registered agents with their lease status",
20+
Long: `List all registered agents showing their lease status (active, limited, stale), registration time, hardware info, and node budget. Displays totals for each lease status.`,
21+
Example: `# list all agents
22+
sts agent list
23+
24+
# list agents in JSON format for scripting
25+
sts agent list -o json`,
26+
RunE: deps.CmdRunEWithApi(RunListCommand),
2227
}
2328

2429
return cmd

cmd/context.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
func ContextCommand(cli *di.Deps) *cobra.Command {
1010
cmd := &cobra.Command{
1111
Use: "context",
12-
Short: "Manage StackState contexts",
13-
Long: "Manage connections to different StackState servers.",
12+
Short: "Manage CLI connection contexts for SUSE Observability servers",
13+
Long: `Manage CLI connection contexts. A context stores the URL and authentication credentials for a SUSE Observability server, allowing you to switch between different servers or environments without re-entering connection details.`,
1414
}
1515

1616
cmd.AddCommand(context.SaveCommand(cli))

cmd/context/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func PrintConnectionSuccess(pr printer.Printer, apiUrl string, serverInfo *stack
2323
} else {
2424
// Fallback to serverInfo.Version if platformVersion is not present (an updated client could interact with a server not supporting PlatformVersion yet).
2525
pr.Success(
26-
fmt.Sprintf("Connection verified to %s (StackState version: %s)",
26+
fmt.Sprintf("Connection verified to %s (SUSE Observability version: %s)",
2727
apiUrl,
2828
client.VersionToString(serverInfo.Version),
2929
),

cmd/context/context_delete.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ type DeleteArgs struct {
1616
func DeleteCommand(cli *di.Deps) *cobra.Command {
1717
args := &DeleteArgs{}
1818
cmd := &cobra.Command{
19-
Use: "delete",
20-
Short: "Delete a context",
21-
Long: "Delete a context from the local config file.",
22-
RunE: cli.CmdRunEWithConfig(RunContextDeleteCommand(args)),
19+
Use: "delete --name NAME",
20+
Short: "Delete a saved context from the CLI configuration",
21+
Long: "Delete a connection context from the CLI configuration file. The currently active context cannot be deleted; switch to a different context first.",
22+
Example: `# delete an unused context
23+
sts context delete --name old-staging`,
24+
RunE: cli.CmdRunEWithConfig(RunContextDeleteCommand(args)),
2325
}
2426

2527
common.AddRequiredNameFlagVar(cmd, &args.Name, "Name of the context")

cmd/context/context_list.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@ import (
1111
func ListCommand(deps *di.Deps) *cobra.Command {
1212
cmd := &cobra.Command{
1313
Use: "list",
14-
Short: "List available contexts",
15-
Long: "List available contexts in the config file.",
16-
RunE: deps.CmdRunEWithConfig(RunContextListCommand),
14+
Short: "List all configured connection contexts",
15+
Long: "List all connection contexts saved in the CLI configuration file, showing the context name and server URL for each.",
16+
Example: `# list all contexts
17+
sts context list
18+
19+
# list contexts in JSON format
20+
sts context list -o json`,
21+
RunE: deps.CmdRunEWithConfig(RunContextListCommand),
1722
}
1823

1924
return cmd

cmd/context/context_save.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@ type SaveArgs struct {
3030
func SaveCommand(cli *di.Deps) *cobra.Command {
3131
args := &SaveArgs{}
3232
cmd := &cobra.Command{
33-
Use: "save",
34-
Short: "Save a context",
35-
Long: "Save a context to the local config file.",
36-
RunE: cli.CmdRunE(RunContextSaveCommand(args)),
33+
Use: "save --url URL {--api-token TOKEN | --service-token TOKEN}",
34+
Short: "Save a connection context to the CLI configuration",
35+
Long: `Save a connection context to the CLI configuration file. The context stores the server URL and authentication credentials. After saving, this context becomes the current active context.`,
36+
Example: `# save a context with an API token
37+
sts context save --name production --url https://stackstate.example.com --api-token xxxx-xxxx
38+
39+
# save a context with a service token for CI/CD pipelines
40+
sts context save --name ci --url https://stackstate.example.com --service-token xxxx-xxxx
41+
42+
# save a context with a custom CA certificate
43+
sts context save --name production --url https://stackstate.example.com --api-token xxxx-xxxx --ca-cert /path/to/ca.crt`,
44+
RunE: cli.CmdRunE(RunContextSaveCommand(args)),
3745
}
3846

3947
common.AddNameFlagVarVal(cmd, &args.Name, "default", "Name of the context")

cmd/context/context_set.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ type SetArgs struct {
1616
func SetCommand(cli *di.Deps) *cobra.Command {
1717
args := &SetArgs{}
1818
cmd := &cobra.Command{
19-
Use: "set",
20-
Short: "Set the current context",
21-
Long: "Set the current context.",
22-
RunE: cli.CmdRunEWithConfig(RunContextSetCommand(args, cli)),
19+
Use: "set --name NAME",
20+
Short: "Set the active context to use for CLI commands",
21+
Long: "Set the active connection context. All subsequent CLI commands will use this context's server URL and credentials.",
22+
Example: `# switch to the production context
23+
sts context set --name production
24+
25+
# switch to a different environment
26+
sts context set --name staging`,
27+
RunE: cli.CmdRunEWithConfig(RunContextSetCommand(args, cli)),
2328
}
2429

2530
common.AddRequiredNameFlagVar(cmd, &args.Name, "Name of the context")

cmd/context/context_show.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ import (
1010
func ShowCommand(deps *di.Deps) *cobra.Command {
1111
cmd := &cobra.Command{
1212
Use: "show",
13-
Short: "Show the current context",
14-
Long: "Show the current context.",
15-
RunE: deps.CmdRunEWithConfig(RunContextShowCommand),
13+
Short: "Display the currently active context",
14+
Long: "Display the name of the currently active connection context. Use 'sts context list' to see all available contexts.",
15+
Example: `# show the current context name
16+
sts context show
17+
18+
# show current context details in JSON format
19+
sts context show -o json`,
20+
RunE: deps.CmdRunEWithConfig(RunContextShowCommand),
1621
}
1722

1823
return cmd

0 commit comments

Comments
 (0)