Skip to content

<fix>[gosdk]: port generator fixes to feature-5.5.22-zcf-temporary#3908

Open
ZStack-Robot wants to merge 4 commits intofeature-5.5.22-zcf-temporaryfrom
sync/hanyu.liang/fix-gosdk
Open

<fix>[gosdk]: port generator fixes to feature-5.5.22-zcf-temporary#3908
ZStack-Robot wants to merge 4 commits intofeature-5.5.22-zcf-temporaryfrom
sync/hanyu.liang/fix-gosdk

Conversation

@ZStack-Robot
Copy link
Copy Markdown
Collaborator

Cherry-pick Go SDK generator fixes from feature-zcf-v0.1 to feature-5.5.22-zcf-temporary:

  • c3d81cf [sdk]: fix Go SDK generator for Delete-via-POST and Get patterns
  • 5614cd5 [rest]: port Go SDK generator bug fixes from ZSV-11399
  • 410c0b1 [rest]: GoInventory.reset() must clear all instance caches

Purpose:

  • Align Go SDK generation behavior with feature-zcf-v0.1.
  • Bring context-aware generated methods, response key fixes, and generator reset/cache fixes into feature-5.5.22-zcf-temporary.

Note:

  • This MR only ports the existing missing Go SDK generator fixes. The AddIAM2VirtualIDsToGroup-specific POST path-placeholder/no-inventory issue still needs a follow-up generator fix if required.

sync from gitlab !9792

liang-hanyu and others added 3 commits May 9, 2026 10:45
1. Delete-via-POST: detect actionType=="Delete" with httpMethod==POST and
   generate PostWithRespKey with empty responseKey instead of Post with
   hardcoded "inventory" key. Handles URL placeholders via buildFullPath.
2. Get-with-inventories: when reply has "inventories" (List) instead of
   "inventory" (single), use the response struct directly with GetWithRespKey
   and empty responseKey to unmarshal the full response.

Resolves: ZCF-0

Change-Id: I708245d6bd49172fd27488a506dec57d2bfd73ee
Port critical Go SDK generation fixes from MR !9249 (ZSV-11399):

GoApiTemplate.groovy:
- Add context.Context parameter to all generated Go method signatures
- Add allTo response key extraction for PostWithRespKey
- Add valid flag + isValid() for safe template initialization
- Add reset() to prevent stale state across repeated SDK generation
- Add getApiOptPath() for optional path handling
- Fix pluralization: only replace y→ies after consonants
- Pass allTo to GetWithSpec for correct response unwrapping

GoInventory.groovy:
- Add reset() + call GoApiTemplate.reset() at start of generation
- Use template.isValid() instead of template.at != null
- Fix time.Now → time.Now() in generated Go code (4 occurrences)
- Remove deprecated generateClientFile() (~400 lines of dead code)

base_param_types.go.template:
- Fix time.Now → time.Now() (missing parentheses)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous reset() only cleared longJobMappings (static), leaving
instance-level caches (allApiTemplates, generatedViewStructs,
generatedParamStructs, generatedClientMethods, additionalClasses,
etc.) intact across repeated generate() calls on the same instance.

This caused skipped or duplicate output when TestGenerateGoSDK ran
more than once in the same JVM.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

Walkthrough

生成器添加模板有效性标志与重置,读取并传递 allTo;将所有生成的客户端方法改为接受 context.Context 并调用上下文感知的 cli 辅助函数;为 POST-delete 添加专门分支;修复 time 未使用导入占位写法。

变更

Go SDK 生成器上下文与验证重构

层 / 文件(s) 概述
状态管理与重置
rest/src/main/resources/scripts/GoApiTemplate.groovy, rest/src/main/resources/scripts/GoInventory.groovy
添加 valid 标志和 isValid() 方法用于追踪模板初始化状态;新增 GoApiTemplate.reset()GoInventory.reset() 清除所有静态缓存和生成状态。
数据契约 - 响应注解
rest/src/main/resources/scripts/GoApiTemplate.groovy
新增 allTo 字段用于从 @RestResponse 注解读取路由数据,并将其传递至生成的 GetWithSpec 调用。
模板初始化与验证
rest/src/main/resources/scripts/GoApiTemplate.groovy
构造函数现在初始化 valid 标志并提取 allTo;prepareApiTemplates 改用 template.isValid() 替代 template.at != null
上下文感知 HTTP 方法
rest/src/main/resources/scripts/GoApiTemplate.groovy
所有 HTTP 方法生成器(Create/POST、Query/List、Page、Get、Update/PUT、Delete、Expunge、Generic)现在接受 ctx context.Context 参数并调用 cli.Post(ctx, ...)cli.List(ctx, ...)cli.Page(ctx, ...)cli.GetWithSpec(ctx, ...) 等上下文感知辅助函数。
删除操作特殊处理
rest/src/main/resources/scripts/GoApiTemplate.groovy
在 POST 生成分支中添加特殊逻辑:当 actionType == "Delete" 且 HTTP 方法为 POST 时,调用新增 generateDeleteViaPostMethod;该方法通过 fmt.Sprintf 支持 URL 占位符处理并使用 PostWithRespKey(..., "", ...)
异步与生成集成
rest/src/main/resources/scripts/GoApiTemplate.groovy, rest/src/main/resources/scripts/GoInventory.groovy
generateAsyncMethod 现在在生成的异步方法签名中包含 ctx context.ContextGoInventory.generate() 在启动扫描前调用重置方法。
未使用导入修复
rest/src/main/resources/scripts/GoInventory.groovy, rest/src/main/resources/scripts/templates/base_param_types.go.template
所有 Go 代码生成模板将未使用的 time 包引用从 var _ = time.Now 改为 var _ = time.Now(),确保正确的编译器识别。

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GeneratedMethod
  participant CLI
  Client->>GeneratedMethod: 调用 Method(ctx, params)
  GeneratedMethod->>CLI: cli.Post/Get/Put/Delete(ctx, path, body)
  CLI-->>GeneratedMethod: 返回 response
  GeneratedMethod-->>Client: 返回结果
Loading

预估代码审查工作量

🎯 4 (复杂) | ⏱️ ~60 分钟

🐰 兔子之歌
上下文在方法间轻轻跳,
重置把旧印记拂去,
allTo 指引响应归处,
time 包被唤作 time.Now(),
生成器再次欢跃。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 标题遵循了 [scope]: 格式,长度为66字符,小于72字符限制,内容清晰表达了此PR的目的(移植生成器修复)。
Description check ✅ Passed 描述详细说明了此PR的目的(樱桃选择Go SDK生成器修复),列举了具体的提交,解释了变更的原因和范围。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/hanyu.liang/fix-gosdk

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rest/src/main/resources/scripts/GoApiTemplate.groovy`:
- Around line 992-1053: generateDeleteViaPostMethod currently emits Go methods
without a ctx context.Context parameter and does not pass ctx into
PostWithRespKey; update the generator so every produced function signature
includes ctx context.Context (e.g. func (cli *ZSClient) ${clzName}(ctx
context.Context, ...)) whether or not there are URL placeholders or params,
adjust placeholder param ordering (ctx first) and change every PostWithRespKey
call to pass ctx as the first argument (PostWithRespKey(ctx, ...)); ensure you
update all branches (placeholders vs no placeholders, with and without
param.${clzName}Param) so signatures and calls are consistent with other
generators like generateCreateMethod/generateQueryMethod.

In `@rest/src/main/resources/scripts/GoInventory.groovy`:
- Around line 109-128: The reset() method currently clears many caches but omits
the viewStructNameMap map, so stale Class->String mappings persist across
generations; update GoInventory.reset() to also clear viewStructNameMap (the
Map<Class, String> defined earlier) by invoking its clear() alongside the other
cache clears so the view struct name cache is reset before each generate() run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: b4293a39-916d-49c6-8934-a1490f13b214

📥 Commits

Reviewing files that changed from the base of the PR and between 5b8953c and 5da1d54.

📒 Files selected for processing (3)
  • rest/src/main/resources/scripts/GoApiTemplate.groovy
  • rest/src/main/resources/scripts/GoInventory.groovy
  • rest/src/main/resources/scripts/templates/base_param_types.go.template

Comment thread rest/src/main/resources/scripts/GoApiTemplate.groovy
Comment on lines +109 to +128
/**
* Reset all static and instance state for clean re-generation.
* Must be called before each generate() to avoid stale caches
* causing skipped or duplicate output across repeated runs.
*/
void reset() {
longJobMappings.clear()
allApiTemplates.clear()
inventories.clear()
markedInventories.clear()
additionalClasses.clear()
generatedViewStructs.clear()
generatedViewFiles.clear()
paramNestedTypes.clear()
generatedParamStructs.clear()
generatedClientMethods.clear()
generatingForParam = false
currentGeneratingClass = null
logger.warn("[GoSDK] Reset GoInventory state (static + instance)")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

reset() 方法遗漏清理 viewStructNameMap

reset() 方法未清理 viewStructNameMap(第 32 行定义的 Map<Class, String>)。此缓存存储类到视图结构体名称的映射,若不清理可能导致跨生成运行时残留过期映射。

🐛 建议修复
 void reset() {
     longJobMappings.clear()
     allApiTemplates.clear()
     inventories.clear()
     markedInventories.clear()
+    viewStructNameMap.clear()
     additionalClasses.clear()
     generatedViewStructs.clear()
     generatedViewFiles.clear()
     paramNestedTypes.clear()
     generatedParamStructs.clear()
     generatedClientMethods.clear()
     generatingForParam = false
     currentGeneratingClass = null
     logger.warn("[GoSDK] Reset GoInventory state (static + instance)")
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rest/src/main/resources/scripts/GoInventory.groovy` around lines 109 - 128,
The reset() method currently clears many caches but omits the viewStructNameMap
map, so stale Class->String mappings persist across generations; update
GoInventory.reset() to also clear viewStructNameMap (the Map<Class, String>
defined earlier) by invoking its clear() alongside the other cache clears so the
view struct name cache is reset before each generate() run.

Generate POST APIs with URL placeholders as explicit Go method
parameters and build the request path with fmt.Sprintf. Also use
PostWithRespKey for POST responses so APIs returning plain Event/Reply
without inventory are unmarshaled from the full response body.

This fixes AddIAM2VirtualIDsToGroup and other POST APIs whose REST path
contains placeholders such as {uuid}, {groupUuid}, or multiple path args.

Resolves: ZCF-0
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rest/src/main/resources/scripts/GoApiTemplate.groovy (1)

1377-1383: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

异步生成方法中 ctx 参数未传递给 cli.PostWithAsync()

方法签名已接受 ctx context.Context 参数(第1377行),但后续对 cli.PostWithAsync(...) 的调用(第1383行)并未将其传递。若 PostWithAsync 已更新为 context-aware 签名,生成的 Go 代码将无法编译;即使 helper 尚未更新,取消和超时功能也无法正常工作。

建议修改:

最小修复
-        builder.append("\tapiId, err := cli.PostWithAsync(resource, responseKey, params, retVal, true)\n")
+        builder.append("\tapiId, err := cli.PostWithAsync(ctx, resource, responseKey, params, retVal, true)\n")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rest/src/main/resources/scripts/GoApiTemplate.groovy` around lines 1377 -
1383, The generated async method for ZSClient (func (cli *ZSClient)
${asyncMethodName}(ctx context.Context, ...)) accepts a ctx but does not forward
it to cli.PostWithAsync; update the call to cli.PostWithAsync to pass the
context (e.g., include ctx as the first argument) so the generated method
forwards cancellation/timeouts and matches a context-aware PostWithAsync
signature; modify the template around the PostWithAsync invocation in
GoApiTemplate.groovy to include ctx when building the call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rest/src/main/resources/scripts/GoApiTemplate.groovy`:
- Around line 1032-1036: 生成器在生成 DELETE 方法(当 useSpec 为 false)时始终在签名中加入 uuid
string 并调用 cli.Delete,导致无占位符路径(例如 /delete/sso/client)会多拼一个 path
segment;在模板里的分支需依照占位符数量拆成两条:当没有占位符时,生成 func (cli *ZSClient) ${clzName}(ctx
context.Context, deleteMode param.DeleteMode) error 并调用 cli.Delete(ctx,
"${cleanPath}", "", string(deleteMode)) 或提供不传 uuid 的重载;当只有一个占位符时,保持现有签名 func
(cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode
param.DeleteMode) error 并调用 cli.Delete(ctx, "${cleanPath}", uuid,
string(deleteMode));修改模板中 useSpec 分支逻辑和生成的 ZSClient.${clzName}
方法以根据占位符数选择正确的签名和传参。

---

Outside diff comments:
In `@rest/src/main/resources/scripts/GoApiTemplate.groovy`:
- Around line 1377-1383: The generated async method for ZSClient (func (cli
*ZSClient) ${asyncMethodName}(ctx context.Context, ...)) accepts a ctx but does
not forward it to cli.PostWithAsync; update the call to cli.PostWithAsync to
pass the context (e.g., include ctx as the first argument) so the generated
method forwards cancellation/timeouts and matches a context-aware PostWithAsync
signature; modify the template around the PostWithAsync invocation in
GoApiTemplate.groovy to include ctx when building the call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml (via .coderabbit.yaml)

Review profile: CHILL

Plan: Pro

Run ID: 08c0c647-4713-4b45-91e7-8ec78e681b35

📥 Commits

Reviewing files that changed from the base of the PR and between 5da1d54 and 0224893.

📒 Files selected for processing (1)
  • rest/src/main/resources/scripts/GoApiTemplate.groovy

Comment on lines 1032 to 1036
if (!useSpec) {
// Single or no placeholder: use the standard Delete method
return """func (cli *ZSClient) ${clzName}(uuid string, deleteMode param.DeleteMode) error {
\treturn cli.Delete("${cleanPath}", uuid, string(deleteMode))
return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode param.DeleteMode) error {
\treturn cli.Delete(ctx, "${cleanPath}", uuid, string(deleteMode))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

DELETE 无占位符时不应继续生成 uuid 参数。

这里的注释写的是 “Single or no placeholder”,但生成的方法签名始终包含 uuid string,并把它传给 cli.Delete。对 /delete/sso/client 这类无占位符路径,SDK 会凭空多拼一个 path segment,最终请求 URL 会错误。

🔧 建议拆分 0/1 个占位符分支
-        if (!useSpec) {
-            // Single or no placeholder: use the standard Delete method
-            return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode param.DeleteMode) error {
-\treturn cli.Delete(ctx, "${cleanPath}", uuid, string(deleteMode))
-}
-"""
+        if (!useSpec) {
+            if (placeholders.isEmpty()) {
+                return """func (cli *ZSClient) ${clzName}(ctx context.Context, deleteMode param.DeleteMode) error {
+\treturn cli.Delete(ctx, "${cleanPath}", "", string(deleteMode))
+}
+"""
+            }
+            return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode param.DeleteMode) error {
+\treturn cli.Delete(ctx, "${cleanPath}", uuid, string(deleteMode))
+}
+"""
         } else {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rest/src/main/resources/scripts/GoApiTemplate.groovy` around lines 1032 -
1036, 生成器在生成 DELETE 方法(当 useSpec 为 false)时始终在签名中加入 uuid string 并调用
cli.Delete,导致无占位符路径(例如 /delete/sso/client)会多拼一个 path
segment;在模板里的分支需依照占位符数量拆成两条:当没有占位符时,生成 func (cli *ZSClient) ${clzName}(ctx
context.Context, deleteMode param.DeleteMode) error 并调用 cli.Delete(ctx,
"${cleanPath}", "", string(deleteMode)) 或提供不传 uuid 的重载;当只有一个占位符时,保持现有签名 func
(cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode
param.DeleteMode) error 并调用 cli.Delete(ctx, "${cleanPath}", uuid,
string(deleteMode));修改模板中 useSpec 分支逻辑和生成的 ZSClient.${clzName}
方法以根据占位符数选择正确的签名和传参。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants