fix(output): deterministic --format table ordering and show error status code #258

Merged
wbtiger merged 1 commits from luwanzhou/gitlink-cli:fix/output-table-determinism into master 2026-07-14 20:44:13 +08:00
Contributor

问题描述

gitlink-cli ... --format table 的渲染依赖 Go map 的遍历顺序,而 Go 的 map 遍历是随机的

  • 现象
    • printMapTable(单对象 KEY/VALUE 表)每次运行的行顺序都不一样
    • collectKeys 在补全非优先列时直接 for k := range m,导致 printSliceTable(列表表)优先列之后的列顺序也随机
    • 另外,table 模式的错误输出只显示 Error: <message>不显示状态码
  • 影响:同一条命令两次运行的表格输出不一致,难以肉眼对比、diff、截图,也无法在脚本 / 测试中稳定断言;错误时也不易快速区分 404 / 422 / 500。

问题复现步骤

  1. 对任意返回扁平对象的命令使用 --format table,例如:

    gitlink-cli <cmd> --format table
    gitlink-cli <cmd> --format table
    
  2. 多次运行,观察 KEY/VALUE 行顺序(及列表表优先列之后的列顺序)在两次运行间发生变化。

  3. 触发一个错误(如对不存在资源请求)并用 --format table,输出只有 Error: <message>,看不到状态码。

根本原因

internal/output/formatter.go

  • printMapTable 直接 for k, v := range m 输出,行顺序 = map 随机遍历顺序;
  • collectKeys 在追加非优先列时 for k := range m,列顺序同样随机;
  • table 错误分支只打印 envelope.Error.Message,未利用已有的 envelope.Error.Code

修复方案

仅改动 internal/output/formatter.go(与其它进行中的 PR 无文件交叉):

  1. collectKeys:优先列(id/name/login/title/status/state/created_at/updated_at)之后的剩余列改为 sort.Strings 排序,列顺序稳定可预期。
  2. printMapTable:改为按 collectKeys 的顺序输出,行顺序确定,且与列表表的列顺序保持一致。
  3. 错误输出:存在错误码时显示 Error [<code>]: <message>(无错误码时回退 Error: <message>),便于快速识别状态码。

不影响 json / yaml 输出,也不改变成功数据内容,仅稳定其呈现顺序并丰富错误提示。

合并请求描述

本 PR 修复 --format table 输出随 Go map 遍历顺序变化、不确定的问题,使表格输出在多次运行间稳定一致,并在错误输出中补充状态码,提升可读性与可脚本化程度。

相关Issue

无直接关联 Issue(输出格式 / 错误提示一致性优化,对应赛题一「优化现有命令的输出格式、错误提示」)。

变更内容

1. 修复:表格输出确定性排序(internal/output/formatter.go

  • collectKeys 非优先列 sort.Strings 排序;
  • printMapTablecollectKeys 顺序渲染,行序确定且与列表表一致。

2. 增强:错误输出展示状态码

  • Error [<code>]: <message>(无码时回退 Error: <message>)。

3. 测试(internal/output/formatter_test.go

  • collectKeys 非优先列按字典序排序;
  • 单对象表渲染 25 次输出完全一致;
  • 列表表表头顺序 25 次渲染一致;
  • 错误输出含状态码 Error [500]: ...,无码时回退 Error: ...

4. 变更说明(doc/changes/output-table-determinism.md

测试与验证

go build ./...go vet ./...go test ./...gofmt -s 全部通过;新增/既有 internal/output 测试全绿。

## 问题描述 `gitlink-cli ... --format table` 的渲染依赖 Go map 的遍历顺序,而 Go 的 map 遍历是**随机的**。 - **现象**: - `printMapTable`(单对象 KEY/VALUE 表)每次运行的**行顺序都不一样**; - `collectKeys` 在补全非优先列时直接 `for k := range m`,导致 `printSliceTable`(列表表)优先列之后的**列顺序也随机**。 - 另外,table 模式的错误输出只显示 `Error: <message>`,**不显示状态码**。 - **影响**:同一条命令两次运行的表格输出不一致,难以肉眼对比、`diff`、截图,也无法在脚本 / 测试中稳定断言;错误时也不易快速区分 404 / 422 / 500。 ## 问题复现步骤 1. 对任意返回扁平对象的命令使用 `--format table`,例如: ```bash gitlink-cli <cmd> --format table gitlink-cli <cmd> --format table ``` 2. 多次运行,观察 KEY/VALUE 行顺序(及列表表优先列之后的列顺序)在两次运行间发生变化。 3. 触发一个错误(如对不存在资源请求)并用 `--format table`,输出只有 `Error: <message>`,看不到状态码。 ## 根本原因 `internal/output/formatter.go`: - `printMapTable` 直接 `for k, v := range m` 输出,行顺序 = map 随机遍历顺序; - `collectKeys` 在追加非优先列时 `for k := range m`,列顺序同样随机; - table 错误分支只打印 `envelope.Error.Message`,未利用已有的 `envelope.Error.Code`。 ## 修复方案 仅改动 `internal/output/formatter.go`(与其它进行中的 PR 无文件交叉): 1. **`collectKeys`**:优先列(id/name/login/title/status/state/created_at/updated_at)之后的剩余列改为 `sort.Strings` 排序,列顺序稳定可预期。 2. **`printMapTable`**:改为按 `collectKeys` 的顺序输出,行顺序确定,且与列表表的列顺序保持一致。 3. **错误输出**:存在错误码时显示 `Error [<code>]: <message>`(无错误码时回退 `Error: <message>`),便于快速识别状态码。 不影响 json / yaml 输出,也不改变成功数据内容,仅稳定其呈现顺序并丰富错误提示。 ## 合并请求描述 本 PR 修复 `--format table` 输出随 Go map 遍历顺序变化、不确定的问题,使表格输出在多次运行间稳定一致,并在错误输出中补充状态码,提升可读性与可脚本化程度。 ## 相关Issue 无直接关联 Issue(输出格式 / 错误提示一致性优化,对应赛题一「优化现有命令的输出格式、错误提示」)。 ## 变更内容 ### 1. 修复:表格输出确定性排序(`internal/output/formatter.go`) - `collectKeys` 非优先列 `sort.Strings` 排序; - `printMapTable` 按 `collectKeys` 顺序渲染,行序确定且与列表表一致。 ### 2. 增强:错误输出展示状态码 - `Error [<code>]: <message>`(无码时回退 `Error: <message>`)。 ### 3. 测试(`internal/output/formatter_test.go`) - `collectKeys` 非优先列按字典序排序; - 单对象表渲染 25 次输出完全一致; - 列表表表头顺序 25 次渲染一致; - 错误输出含状态码 `Error [500]: ...`,无码时回退 `Error: ...`。 ### 4. 变更说明(`doc/changes/output-table-determinism.md`) ## 测试与验证 `go build ./...`、`go vet ./...`、`go test ./...`、`gofmt -s` 全部通过;新增/既有 `internal/output` 测试全绿。
luwanzhou added 1 commit 2026-06-15 14:41:15 +08:00
2f4b7674d6 fix(output): deterministic --format table ordering and show error status code
--format table 的渲染依赖 Go map 随机遍历顺序:printMapTable 的行顺序、
以及 collectKeys 补全非优先列后 printSliceTable 的列顺序,每次运行都可能不同,
导致同一命令两次输出不一致,难以对比/diff/脚本断言。

- collectKeys:优先列之后的剩余列改为 sort.Strings 排序,顺序稳定可预期。
- printMapTable:按 collectKeys 顺序输出,行序确定且与列表表列序一致。
- 错误输出:有错误码时显示 Error [<code>]: <message>,便于区分 404/422/500。

仅稳定 table 呈现顺序并丰富错误提示,不影响 json/yaml 输出与成功数据内容。
新增单测覆盖排序、25 次渲染确定性、错误码展示。
wbtiger merged commit 3264c53bcc into master 2026-07-14 20:43:52 +08:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Gitlink/gitlink-cli#258
No description provided.