Skip to content

Fix mail rule reorder with partial IDs - #2175

Open
yangr-happy wants to merge 2 commits into
larksuite:mainfrom
yangr-happy:feat/ebe347c
Open

Fix mail rule reorder with partial IDs#2175
yangr-happy wants to merge 2 commits into
larksuite:mainfrom
yangr-happy:feat/ebe347c

Conversation

@yangr-happy

@yangr-happy yangr-happy commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

This completes mail receive-rule reorder requests before they are sent to the service.

  • Fetches the current rule list before reorder operations.
  • Validates requested rule IDs against the current mailbox rules.
  • Sends the full ordered rule ID list expected by the reorder API.
  • Adds tests for partial reorder input and documents the behavior.

Tested with go test ./cmd/service.

Summary by CodeRabbit

  • New Features

    • Mail rules can now be reordered by specifying only the rules that should move to the front; remaining rules are automatically appended in their existing order.
    • The CLI retrieves the complete rule list, supports paginated results, and validates the requested ordering before applying changes.
  • Bug Fixes

    • Added validation for empty, duplicate, or unknown rule IDs and clearer handling of list and reorder API failures.
  • Documentation

    • Documented partial mail-rule reordering and validation behavior.

Fetch the current mailbox rules with the same service command context before calling reorder, validate the requested IDs locally, and submit the completed rule ID order.

Document partial reorder input behavior for the mail skill reference.

Test: go test ./cmd/service

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The CLI preprocesses mail-rule reorder requests. It validates rule_ids, retrieves all existing rules with pagination, appends omitted rules, and sends the completed order. Tests and documentation cover validation, errors, paths, and usage.

Changes

Mail-rule reorder flow

Layer / File(s) Summary
Request validation and order completion
cmd/service/mail_rules_reorder.go
The CLI parses and validates reorder bodies and rule_ids, rejects invalid or unknown IDs, and appends omitted existing rules.
Paginated rule listing and API handling
cmd/service/mail_rules_reorder.go
The CLI derives the list endpoint, follows pagination, copies parameters without page_token, and parses supported response shapes.
Service integration and validation coverage
cmd/service/service.go, cmd/service/mail_rules_reorder_test.go, skills/lark-mail/references/lark-mail-rules.md
The service runner preprocesses reorder requests before dry-run or execution. Tests and documentation cover ordering, errors, pagination, paths, and usage.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant serviceMethodRun
  participant MailRulesListAPI
  participant MailRulesReorderAPI
  CLI->>serviceMethodRun: submit reorder request
  serviceMethodRun->>MailRulesListAPI: retrieve existing rule IDs
  MailRulesListAPI-->>serviceMethodRun: return paginated rule IDs
  serviceMethodRun->>MailRulesReorderAPI: submit completed rule order
  MailRulesReorderAPI-->>CLI: return reorder response
Loading

Possibly related PRs

  • larksuite/cli#2166: Implements related mail-rule reorder validation, pagination, and ID completion.
  • larksuite/cli#2167: Modifies the same reorder preprocessing and service integration points.
  • larksuite/cli#2185: Implements overlapping reorder ID completion and service preprocessing changes.

Suggested reviewers: liangshuo-1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preprocessing mail rule reorder requests with partial IDs by fetching current rules and completing the order before sending to the API.
Description check ✅ Passed The description covers the motivation, main changes, and testing approach. However, it lacks the structured format sections (Summary, Changes, Test Plan, Related Issues) specified in the template.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths labels Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
cmd/service/mail_rules_reorder.go (2)

149-158: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Consider restricting the parameters that are copied to the list request.

copyRequestParamsWithoutPageToken forwards every undeclared query parameter from the reorder request to the list request. The service runner passes undeclared --params keys through verbatim (buildServiceRequest, Line 614). Such a key can be meaningful for reorder and rejected by the list endpoint. An allowlist (for example page_size only) keeps the list call stable.

🤖 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 `@cmd/service/mail_rules_reorder.go` around lines 149 - 158, Update
copyRequestParamsWithoutPageToken to copy only query parameters supported by the
list request, such as page_size, instead of forwarding every key; continue
excluding page_token and preserve the existing output map behavior.

160-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Empty rule_id with a non-string id produces a confusing state.

At Line 179, if rule["rule_id"] is an empty string, ok is true and id is "". Line 181 then reassigns both from rule["id"]. This path is correct, but the double-fallback is hard to follow. A single helper that returns the first non-empty string field is clearer.

♻️ Proposed simplification
-		id, ok := rule["rule_id"].(string)
-		if !ok || id == "" {
-			id, ok = rule["id"].(string)
-		}
-		if !ok || id == "" {
+		id := firstNonEmptyString(rule, "rule_id", "id")
+		if id == "" {
 			return nil, errs.NewInternalError(errs.SubtypeInvalidResponse, "mail rules list item %d missing rule_id", i)
 		}
func firstNonEmptyString(m map[string]any, keys ...string) string {
	for _, k := range keys {
		if s, ok := m[k].(string); ok && s != "" {
			return s
		}
	}
	return ""
}
🤖 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 `@cmd/service/mail_rules_reorder.go` around lines 160 - 189, In
extractMailRuleIDs, replace the current rule_id/id type-and-empty checks with a
shared firstNonEmptyString helper that checks those fields in order and returns
the first non-empty string. Preserve the existing invalid-response error when
neither field yields a valid ID, including the item index.
cmd/service/mail_rules_reorder_test.go (2)

54-64: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the cobraCommandShim indirection.

newMailRulesReorderCommand wraps SetArgs and Execute in a struct of function fields. TestMailRulesReorder_ListUsesRulesBaseWhenReorderHasSubpath at Lines 249-267 uses the *cobra.Command directly. Return *cobra.Command from the helper and delete the shim for one consistent pattern.

🤖 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 `@cmd/service/mail_rules_reorder_test.go` around lines 54 - 64, Remove the
cobraCommandShim type and update newMailRulesReorderCommand to return the
underlying *cobra.Command directly alongside the existing values. Adjust
callers, including TestMailRulesReorder_ListUsesRulesBaseWhenReorderHasSubpath,
to invoke SetArgs and Execute on that command without the wrapper.

149-167: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert that no API call occurs.

The test name states that validation errors do not call APIs. The test registers no stubs, so the claim rests on the mock registry rejecting unmatched requests. Make the contract explicit: register a reusable list stub and a reusable reorder stub, then assert that neither was hit. The test then fails if preprocessing calls the list endpoint before validation.

🤖 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 `@cmd/service/mail_rules_reorder_test.go` around lines 149 - 167, Update
TestMailRulesReorder_ValidationErrorsDoNotCallAPIs to register reusable list and
reorder API stubs, retain references to both stubs, and assert neither was hit
after each validation case. Ensure the assertions cover preprocessing as well as
the reorder request, while preserving the existing validation-message checks.
skills/lark-mail/references/lark-mail-rules.md (1)

5-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

建议补充所需权限说明。

reorder 现在会先调用 user_mailbox.rules list。因此该命令除 reorder 权限外,还需要规则列表读取权限。仅具备 reorder 权限的凭证现在会收到 permission error。请在此处说明该新增权限要求,以便用户提前配置。

(说明:静态检查将 Line 7 的“补齐”标记为疑似笔误,属误报,无需修改。)

🤖 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 `@skills/lark-mail/references/lark-mail-rules.md` around lines 5 - 16,
在“重排序”说明中补充权限要求:由于 CLI 会先调用 user_mailbox.rules list,执行 reorder 的凭证除 reorder
权限外还必须具备规则列表读取权限;仅有 reorder 权限时应提示会收到 permission error。保留现有“补齐”表述不变。

Source: Linters/SAST tools

🤖 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 `@cmd/service/mail_rules_reorder_test.go`:
- Around line 275-284: Update cmd/service/mail_rules_reorder_test.go:275-284 in
assertServiceValidationError to assert validationErr.Param equals "rule_ids" and
verify Category and Subtype via errs.ProblemOf, while retaining the type check.
At cmd/service/mail_rules_reorder_test.go:193-196 and :211-214, extend the list
and reorder failure assertions for the *errs.APIError to validate Category and
Subtype through errs.ProblemOf and confirm the original cause is preserved; do
not rely only on message substrings.
- Around line 107-112: Update the OnMatch callback in the reorder tests,
including the cases around the shared mailbox assertions, to capture decoded
rule IDs in a variable instead of calling t.Fatalf there. After cmd.execute()
returns, assert the captured IDs on the test goroutine; apply the same change to
the corresponding callbacks around the later test cases.

In `@cmd/service/service.go`:
- Around line 433-436: Document in lark-mail-rules.md that
mail.user_mailbox.rules.reorder --dry-run displays the user-supplied,
potentially incomplete rule_ids, while real execution completes the list via
maybeCompleteMailRulesReorderIDs before sending; clarify that the dry-run body
is not the final payload.

---

Nitpick comments:
In `@cmd/service/mail_rules_reorder_test.go`:
- Around line 54-64: Remove the cobraCommandShim type and update
newMailRulesReorderCommand to return the underlying *cobra.Command directly
alongside the existing values. Adjust callers, including
TestMailRulesReorder_ListUsesRulesBaseWhenReorderHasSubpath, to invoke SetArgs
and Execute on that command without the wrapper.
- Around line 149-167: Update TestMailRulesReorder_ValidationErrorsDoNotCallAPIs
to register reusable list and reorder API stubs, retain references to both
stubs, and assert neither was hit after each validation case. Ensure the
assertions cover preprocessing as well as the reorder request, while preserving
the existing validation-message checks.

In `@cmd/service/mail_rules_reorder.go`:
- Around line 149-158: Update copyRequestParamsWithoutPageToken to copy only
query parameters supported by the list request, such as page_size, instead of
forwarding every key; continue excluding page_token and preserve the existing
output map behavior.
- Around line 160-189: In extractMailRuleIDs, replace the current rule_id/id
type-and-empty checks with a shared firstNonEmptyString helper that checks those
fields in order and returns the first non-empty string. Preserve the existing
invalid-response error when neither field yields a valid ID, including the item
index.

In `@skills/lark-mail/references/lark-mail-rules.md`:
- Around line 5-16: 在“重排序”说明中补充权限要求:由于 CLI 会先调用 user_mailbox.rules list,执行
reorder 的凭证除 reorder 权限外还必须具备规则列表读取权限;仅有 reorder 权限时应提示会收到 permission
error。保留现有“补齐”表述不变。
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b4ee069-5daa-4ca2-b02a-e7ff9537a432

📥 Commits

Reviewing files that changed from the base of the PR and between 3b66d47 and 2561652.

📒 Files selected for processing (4)
  • cmd/service/mail_rules_reorder.go
  • cmd/service/mail_rules_reorder_test.go
  • cmd/service/service.go
  • skills/lark-mail/references/lark-mail-rules.md

Comment thread cmd/service/mail_rules_reorder_test.go
Comment thread cmd/service/mail_rules_reorder_test.go
Comment thread cmd/service/service.go Outdated
Comment on lines +433 to +436
if err := maybeCompleteMailRulesReorderIDs(opts.Ctx, ac, opts, &request, checkErr); err != nil {
return err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

--dry-run prints the uncompleted rule_ids.

The dry-run branch returns at Line 408, before this hook runs. For mail.user_mailbox.rules.reorder, --dry-run therefore prints the partial rule_ids that the user supplied, while a real run sends the completed list. Completion requires a list API call, so skipping it in dry-run is defensible. Document this difference in skills/lark-mail/references/lark-mail-rules.md so users do not treat the dry-run body as the final payload.

🤖 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 `@cmd/service/service.go` around lines 433 - 436, Document in
lark-mail-rules.md that mail.user_mailbox.rules.reorder --dry-run displays the
user-supplied, potentially incomplete rule_ids, while real execution completes
the list via maybeCompleteMailRulesReorderIDs before sending; clarify that the
dry-run body is not the final payload.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@98c5edb4e602af00d29b3628ea2e7db70b102ed9

🧩 Skill update

npx skills add yangr-happy/cli#feat/ebe347c -y -g

Complete mail rule reorder IDs before dry-run output so printed requests match executed requests.

Move HTTP mock assertions out of OnMatch callbacks and assert typed error metadata for reorder failures.

Change-Type: ci-fix

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

PR Quality Summary

CI did not complete successfully. Use the failed check links below to decide whether this PR needs a code change or a rerun.

Failed checks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@cmd/service/mail_rules_reorder_test.go`:
- Around line 333-337: Update interfaceSliceToStrings to return an error
alongside the string slice, rejecting non-array inputs and any item that is not
a string instead of using fmt.Sprint. In every OnMatch callback that invokes
this helper, capture the returned error and assert it after cmd.execute()
completes, while preserving valid string-array handling.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 52b3c6da-2f4e-4d37-b4b3-985edd99ff1e

📥 Commits

Reviewing files that changed from the base of the PR and between 2561652 and 98c5edb.

📒 Files selected for processing (2)
  • cmd/service/mail_rules_reorder_test.go
  • cmd/service/service.go

Comment on lines +333 to +337
func interfaceSliceToStrings(v interface{}) []string {
items, _ := v.([]interface{})
out := make([]string, 0, len(items))
for _, item := range items {
out = append(out, fmt.Sprint(item))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject non-string rule_ids values in the test projection.

fmt.Sprint(item) silently converts invalid JSON types. For example, numeric 2 becomes "2". This can let a test accept a request body with the wrong rule_ids type.

Return an error for a non-array value or a non-string item. Capture that error in each OnMatch callback and assert it after cmd.execute() returns.

Proposed fix
-func interfaceSliceToStrings(v interface{}) []string {
-	items, _ := v.([]interface{})
+func interfaceSliceToStrings(v interface{}) ([]string, error) {
+	items, ok := v.([]interface{})
+	if !ok {
+		return nil, fmt.Errorf("rule_ids = %T, want array", v)
+	}
 	out := make([]string, 0, len(items))
-	for _, item := range items {
-		out = append(out, fmt.Sprint(item))
+	for i, item := range items {
+		value, ok := item.(string)
+		if !ok {
+			return nil, fmt.Errorf("rule_ids[%d] = %T, want string", i, item)
+		}
+		out = append(out, value)
 	}
-	return out
+	return out, nil
 }

As per coding guidelines, parse map[string]interface{} at the boundary and never silently coerce unsupported inputs.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func interfaceSliceToStrings(v interface{}) []string {
items, _ := v.([]interface{})
out := make([]string, 0, len(items))
for _, item := range items {
out = append(out, fmt.Sprint(item))
func interfaceSliceToStrings(v interface{}) ([]string, error) {
items, ok := v.([]interface{})
if !ok {
return nil, fmt.Errorf("rule_ids = %T, want array", v)
}
out := make([]string, 0, len(items))
for i, item := range items {
value, ok := item.(string)
if !ok {
return nil, fmt.Errorf("rule_ids[%d] = %T, want string", i, item)
}
out = append(out, value)
}
return out, nil
}
🤖 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 `@cmd/service/mail_rules_reorder_test.go` around lines 333 - 337, Update
interfaceSliceToStrings to return an error alongside the string slice, rejecting
non-array inputs and any item that is not a string instead of using fmt.Sprint.
In every OnMatch callback that invokes this helper, capture the returned error
and assert it after cmd.execute() completes, while preserving valid string-array
handling.

Source: Coding guidelines

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

Labels

domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant