Skip to content

Commit de4ed91

Browse files
committed
docs(status-page): correct the command names in the README and e2e tests
The status page group is registered as `status-page`, but the README and the e2e suite still used `statuspage` with subcommands (`changes`, `create-incident`, `create-timeline`, space-separated `migrate ...`) and a `--id` flag that never existed. Anyone following them — a person or an agent reading the docs — got "unknown command". Corrected against the registrations in zz_generated_status_pages.go, and documented the two things that trip up a first call: `change-create` takes page-id as a positional that overrides the `--data` key, and the required `updates` array has no flag, so every real call carries `--data` (or `--data -` to read the body from stdin). The e2e suite is behind the e2e build tag and skips without an app key, so it was not failing CI, but it was broken in both directions: the positive tests could not have passed, and the negative ones passed for the wrong reason — asserting a validation error while actually getting "unknown command". Two further defects surfaced while fixing them: the list helpers unmarshalled a top-level array where the CLI prints an {"items":[...]} envelope, and the header assertion named columns the reflective heuristic never emits. Two tests had no valid replacement verb and were retargeted rather than deleted: `list` has no --id filter, so single-page lookup became `status-page info`, and the invalid-id case moved to `change-active-list`. The generated fences and the flashduty skill card were already correct and are untouched.
1 parent 941d3d1 commit de4ed91

6 files changed

Lines changed: 290 additions & 76 deletions

File tree

README.md

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -186,32 +186,105 @@ flashduty field list [flags] # List custom field definitions
186186

187187
Supports `--name`.
188188

189-
### `statuspage` - Status Page Management (5 command groups)
189+
### `status-page` - Status Page Management (28 commands)
190+
191+
The group is `status-page` (hyphenated), not `statuspage`. Nested object/array
192+
fields carry no typed flag and must be supplied as JSON through `--data`;
193+
`--data -` reads the entire request body from stdin. Positional arguments and
194+
explicitly-set typed flags override the matching keys inside `--data`.
195+
196+
**Pages, components, sections**
197+
198+
```bash
199+
flashduty status-page list # List status pages (JSON: {"items":[...]})
200+
flashduty status-page info <page-id> # Page detail, incl. component and section IDs
201+
flashduty status-page create --name <name> --url-name <slug> --type <public|internal> \
202+
--date-view <calendar|list> --display-uptime-mode <chart_and_percentage|chart|none>
203+
flashduty status-page update <page-id> [--name <name>] [--url-name <slug>] ... # Update a page
204+
flashduty status-page delete <page-id> # Delete a page
205+
flashduty status-page component-upsert <page-id> --data '{"components":[{"name":"API","section_id":"<section-id>"}]}'
206+
flashduty status-page component-delete <component-id> [<id2>...] --page-id <page-id>
207+
flashduty status-page section-upsert <page-id> --data '{"sections":[{"name":"Core"}]}'
208+
flashduty status-page section-delete <section-id> [<id2>...] --page-id <page-id>
209+
```
210+
211+
**Events (incident / maintenance) and their timeline**
212+
213+
```bash
214+
flashduty status-page change-active-list <page-id> --type <incident|maintenance> # Only in-progress events
215+
flashduty status-page change-list <page-id> --type <incident|maintenance> --status <status>
216+
flashduty status-page change-info --page-id <page-id> --change-id <change-id>
217+
flashduty status-page change-create <page-id> --type <incident|maintenance> --title <title> \
218+
--status <status> --description <text> --data '{"updates":[...]}'
219+
flashduty status-page change-update --page-id <page-id> --change-id <change-id> [--title <title>]
220+
flashduty status-page change-delete --page-id <page-id> --change-id <change-id>
221+
flashduty status-page change-timeline-create --page-id <page-id> --change-id <change-id> \
222+
--status <status> --description <text> [--data '{"component_changes":[...]}']
223+
flashduty status-page change-timeline-update --page-id <page-id> --change-id <change-id> --update-id <update-id> [--description <text>]
224+
flashduty status-page change-timeline-delete --page-id <page-id> --change-id <change-id> --update-id <update-id>
225+
```
226+
227+
`change-create` takes `<page-id>` as a **required positional argument**, and its
228+
required `updates` array (with the nested `component_changes`) has no flag — so a
229+
real `change-create` call always carries a `--data` payload:
230+
231+
```bash
232+
flashduty status-page change-create 5750613685214 --type incident \
233+
--title "API latency elevated" --status investigating \
234+
--description "Investigating elevated latency." \
235+
--data '{"updates":[{"status":"investigating","description":"Team is investigating.","component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"degraded"}]}]}'
236+
```
237+
238+
The whole body can also come from stdin with `--data -`:
239+
240+
```bash
241+
cat change.json | flashduty status-page change-create 5750613685214 --data -
242+
```
243+
244+
Resolving an incident goes through `change-timeline-create`; every component the
245+
event touched must be moved back to `operational`:
246+
247+
```bash
248+
flashduty status-page change-timeline-create --page-id 5750613685214 --change-id 5821693893131 \
249+
--status resolved --description "Recovered." \
250+
--data '{"component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"operational"}]}'
251+
```
252+
253+
**Subscribers and templates**
254+
255+
```bash
256+
flashduty status-page subscriber-list <page-id> [--component-ids <ids>] [--page <n>] [--limit <n>]
257+
flashduty status-page subscriber-import <page-id> --method <email|im> --data '{"subscribers":[...]}'
258+
flashduty status-page subscriber-export <page-id> [--component-ids <ids>]
259+
flashduty status-page template-list <page-id> --type <pre_defined|message>
260+
flashduty status-page template-upsert <page-id> --type <pre_defined|message> --data '{"template":{...}}'
261+
flashduty status-page template-delete --page-id <page-id> --template-id <template-id> --type <pre_defined|message>
262+
```
263+
264+
**Migration from Atlassian Statuspage**
190265

191266
```bash
192-
flashduty statuspage list [--id <ids>] # List status pages
193-
flashduty statuspage changes --page-id <id> --type <incident|maintenance> # List active changes
194-
flashduty statuspage create-incident --page-id <id> --title <title> # Create status incident
195-
flashduty statuspage create-timeline --page-id <id> --change <id> --message <msg> # Add timeline update
196-
flashduty statuspage migrate structure --from atlassian --source-page-id <id> --api-key <key> # Start structure/history migration
197-
flashduty statuspage migrate email-subscribers --from atlassian --source-page-id <id> --target-page-id <id> --api-key <key> # Start email subscriber migration
198-
flashduty statuspage migrate status --job-id <id> # Check migration job status
199-
flashduty statuspage migrate cancel --job-id <id> # Cancel a running migration job
267+
flashduty status-page migrate-structure <source-page-id> --api-key <key> [--url-name <slug>] # Structure + history
268+
flashduty status-page migrate-email-subscribers --source-page-id <id> --target-page-id <id> --api-key <key>
269+
flashduty status-page migration-status <job-id> # Check migration job status
270+
flashduty status-page migration-cancel <job-id> # Cancel a running migration job
200271
```
201272

202-
Migration jobs are asynchronous. After starting `structure` or `email-subscribers`, use:
273+
Migration jobs are asynchronous. After starting `migrate-structure` or
274+
`migrate-email-subscribers`, poll the returned `job_id`:
203275

204276
```bash
205-
flashduty statuspage migrate status --job-id <job_id>
277+
flashduty status-page migration-status <job-id>
206278
```
207279

208280
Typical flow:
209281

210282
```bash
211-
flashduty statuspage migrate structure --from atlassian --source-page-id page_123 --api-key $ATLASSIAN_STATUSPAGE_API_KEY
212-
flashduty statuspage migrate status --job-id <structure_job_id>
213-
flashduty statuspage migrate email-subscribers --from atlassian --source-page-id page_123 --target-page-id <target_page_id> --api-key $ATLASSIAN_STATUSPAGE_API_KEY
214-
flashduty statuspage migrate status --job-id <subscriber_job_id>
283+
flashduty status-page migrate-structure page_123 --api-key $ATLASSIAN_STATUSPAGE_API_KEY
284+
flashduty status-page migration-status <structure_job_id>
285+
flashduty status-page migrate-email-subscribers --source-page-id page_123 \
286+
--target-page-id <target_page_id> --api-key $ATLASSIAN_STATUSPAGE_API_KEY
287+
flashduty status-page migration-status <subscriber_job_id>
215288
```
216289

217290
### `template` - Notification Template Management (4 commands)

README_zh.md

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,102 @@ flashduty field list [flags] # 列出自定义字段定义
185185

186186
支持 `--name`
187187

188-
### `statuspage` - 状态页管理(4 个命令)
188+
### `status-page` - 状态页管理(28 个命令)
189+
190+
命令组名是 `status-page`(带连字符),不是 `statuspage`。嵌套对象、数组类字段没有
191+
对应的 flag,必须通过 `--data` 传 JSON;`--data -` 表示整个请求体从 stdin 读取。
192+
位置参数和显式设置的 flag 会覆盖 `--data` 里的同名字段。
193+
194+
**状态页、组件、分组**
195+
196+
```bash
197+
flashduty status-page list # 列出状态页(JSON 形如 {"items":[...]})
198+
flashduty status-page info <page-id> # 状态页详情,含组件 ID 和分组 ID
199+
flashduty status-page create --name <name> --url-name <slug> --type <public|internal> \
200+
--date-view <calendar|list> --display-uptime-mode <chart_and_percentage|chart|none>
201+
flashduty status-page update <page-id> [--name <name>] [--url-name <slug>] ... # 更新状态页
202+
flashduty status-page delete <page-id> # 删除状态页
203+
flashduty status-page component-upsert <page-id> --data '{"components":[{"name":"API","section_id":"<section-id>"}]}'
204+
flashduty status-page component-delete <component-id> [<id2>...] --page-id <page-id>
205+
flashduty status-page section-upsert <page-id> --data '{"sections":[{"name":"核心服务"}]}'
206+
flashduty status-page section-delete <section-id> [<id2>...] --page-id <page-id>
207+
```
208+
209+
**事件(故障 / 维护)与时间线**
210+
211+
```bash
212+
flashduty status-page change-active-list <page-id> --type <incident|maintenance> # 只列进行中的事件
213+
flashduty status-page change-list <page-id> --type <incident|maintenance> --status <status>
214+
flashduty status-page change-info --page-id <page-id> --change-id <change-id>
215+
flashduty status-page change-create <page-id> --type <incident|maintenance> --title <title> \
216+
--status <status> --description <text> --data '{"updates":[...]}'
217+
flashduty status-page change-update --page-id <page-id> --change-id <change-id> [--title <title>]
218+
flashduty status-page change-delete --page-id <page-id> --change-id <change-id>
219+
flashduty status-page change-timeline-create --page-id <page-id> --change-id <change-id> \
220+
--status <status> --description <text> [--data '{"component_changes":[...]}']
221+
flashduty status-page change-timeline-update --page-id <page-id> --change-id <change-id> --update-id <update-id> [--description <text>]
222+
flashduty status-page change-timeline-delete --page-id <page-id> --change-id <change-id> --update-id <update-id>
223+
```
224+
225+
`change-create``<page-id>`**必填位置参数**;必填的 `updates` 数组(以及嵌套在里面的
226+
`component_changes`)没有对应的 flag,所以真实的 `change-create` 调用一定带 `--data`
227+
228+
```bash
229+
flashduty status-page change-create 5750613685214 --type incident \
230+
--title "API 延迟升高" --status investigating \
231+
--description "正在排查延迟升高问题。" \
232+
--data '{"updates":[{"status":"investigating","description":"团队正在排查。","component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"degraded"}]}]}'
233+
```
234+
235+
整个请求体也可以用 `--data -` 从 stdin 读:
236+
237+
```bash
238+
cat change.json | flashduty status-page change-create 5750613685214 --data -
239+
```
240+
241+
关闭事件走 `change-timeline-create`,并且事件涉及的每个组件都要改回 `operational`
242+
243+
```bash
244+
flashduty status-page change-timeline-create --page-id 5750613685214 --change-id 5821693893131 \
245+
--status resolved --description "已恢复。" \
246+
--data '{"component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"operational"}]}'
247+
```
248+
249+
**订阅者与模板**
250+
251+
```bash
252+
flashduty status-page subscriber-list <page-id> [--component-ids <ids>] [--page <n>] [--limit <n>]
253+
flashduty status-page subscriber-import <page-id> --method <email|im> --data '{"subscribers":[...]}'
254+
flashduty status-page subscriber-export <page-id> [--component-ids <ids>]
255+
flashduty status-page template-list <page-id> --type <pre_defined|message>
256+
flashduty status-page template-upsert <page-id> --type <pre_defined|message> --data '{"template":{...}}'
257+
flashduty status-page template-delete --page-id <page-id> --template-id <template-id> --type <pre_defined|message>
258+
```
259+
260+
**从 Atlassian Statuspage 迁移**
261+
262+
```bash
263+
flashduty status-page migrate-structure <source-page-id> --api-key <key> [--url-name <slug>] # 迁移结构与历史
264+
flashduty status-page migrate-email-subscribers --source-page-id <id> --target-page-id <id> --api-key <key>
265+
flashduty status-page migration-status <job-id> # 查询迁移任务状态
266+
flashduty status-page migration-cancel <job-id> # 取消正在跑的迁移任务
267+
```
268+
269+
迁移任务是异步的。启动 `migrate-structure``migrate-email-subscribers` 之后,
270+
用返回的 `job_id` 轮询:
271+
272+
```bash
273+
flashduty status-page migration-status <job-id>
274+
```
275+
276+
典型流程:
189277

190278
```bash
191-
flashduty statuspage list [--id <ids>] # 列出状态页
192-
flashduty statuspage changes --page-id <id> --type <incident|maintenance> # 列出活跃的变更
193-
flashduty statuspage create-incident --page-id <id> --title <title> # 创建状态页事件
194-
flashduty statuspage create-timeline --page-id <id> --change <id> --message <msg> # 添加时间线更新
279+
flashduty status-page migrate-structure page_123 --api-key $ATLASSIAN_STATUSPAGE_API_KEY
280+
flashduty status-page migration-status <structure_job_id>
281+
flashduty status-page migrate-email-subscribers --source-page-id page_123 \
282+
--target-page-id <target_page_id> --api-key $ATLASSIAN_STATUSPAGE_API_KEY
283+
flashduty status-page migration-status <subscriber_job_id>
195284
```
196285

197286
### `template` - 通知模板管理(4 个命令)

e2e/auth_global_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func TestHelpForEverySubcommand(t *testing.T) {
5858
// Test 110: all top-level commands show help without errors
5959
commands := []string{
6060
"channel", "member", "team", "field", "escalation-rule",
61-
"statuspage", "template", "change", "config", "login",
61+
"status-page", "template", "change", "config", "login",
6262
}
6363
for _, cmd := range commands {
6464
t.Run(cmd, func(t *testing.T) {

e2e/edge_case_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestNoTruncOnFieldList(t *testing.T) {
4949
}
5050

5151
func TestNoTruncOnStatusPageList(t *testing.T) {
52-
r := runCLI(t, "statuspage", "list", "--no-trunc")
52+
r := runCLI(t, "status-page", "list", "--no-trunc")
5353
requireSuccess(t, r)
5454
}
5555

e2e/resource_list_test.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package e2e_test
44

55
import (
6+
"strings"
67
"testing"
78
)
89

@@ -113,16 +114,25 @@ func TestChangeListJSON(t *testing.T) {
113114
// StatusPage
114115
// ---------------------------------------------------------------------------
115116

116-
// Test 248: statuspage list
117+
// Test 248: status-page list
118+
//
119+
// `status-page list` is a generated command with no displayColumns entry, so the
120+
// table columns are the reflective heuristic: the first 8 scalar fields of
121+
// StatusPageItem, headed by their upper-cased JSON tag. Components/sections are
122+
// nested arrays and are skipped by that heuristic, so there is no COMPONENTS
123+
// column, and PAGE_ID/NAME/URL_NAME fall past the 8-column cut.
117124
func TestStatusPageList(t *testing.T) {
118-
r := runCLI(t, "statuspage", "list")
125+
r := runCLI(t, "status-page", "list")
119126
requireSuccess(t, r)
120-
requireTableHeaders(t, r.Stdout, "ID", "NAME", "SLUG", "STATUS", "COMPONENTS")
127+
if strings.HasPrefix(strings.TrimSpace(r.Stdout), "No results.") {
128+
t.Skip("no status pages available")
129+
}
130+
requireTableHeaders(t, r.Stdout, "CONTACT_INFO", "CUSTOM_DOMAIN", "DATE_VIEW", "DISPLAY_UPTIME_MODE")
121131
}
122132

123-
// Test 252: statuspage list JSON
133+
// Test 252: status-page list JSON
124134
func TestStatusPageListJSON(t *testing.T) {
125-
r := runCLI(t, "statuspage", "list", "--json")
135+
r := runCLI(t, "status-page", "list", "--json")
126136
requireSuccess(t, r)
127137
requireValidJSON(t, r.Stdout)
128138
}

0 commit comments

Comments
 (0)