Skip to content

feat(mail): add +template-get read-only shortcut#675

Closed
infeng wants to merge 1 commit intolarksuite:mainfrom
infeng:harness/smoke-cli-mail-template-mini-20260427-160723
Closed

feat(mail): add +template-get read-only shortcut#675
infeng wants to merge 1 commit intolarksuite:mainfrom
infeng:harness/smoke-cli-mail-template-mini-20260427-160723

Conversation

@infeng
Copy link
Copy Markdown
Collaborator

@infeng infeng commented Apr 27, 2026

Generated by the harness-coding skill.

  • Task ID: smoke-cli-mail-template-mini-20260427-160723
  • Branch: harness/smoke-cli-mail-template-mini-20260427-160723
  • Target: main

Sprints

ID Title Status Commit
S1 Synthesize transport contract for larksuite/cli passed
S2 Add mail +template-get read-only shortcut passed c6513fc

Source specs

  • /tmp/harness-test/smoke-cli-mail-template-mini-20260427-160723/input/spec.md

This MR was created autonomously. Quality gates were enforced by the repo's own pre-commit hooks.

Summary by CodeRabbit

  • New Features

    • Added mail +template-get command to retrieve personal mail templates by template ID with client-side validation. Supports multiple output formats (JSON, pretty, table, NDJSON, CSV) and dry-run mode. Pretty output displays truncated template content and recipient counts.
  • Documentation

    • Added reference guide for the new mail template retrieval command.

Implements `lark-cli mail +template-get` for fetching a personal mail
template by ID. Validate stage rejects non-decimal template-id strings
(no int64 round-trip); Execute reads via runtime.RawAPI so --format json
returns the raw OAPI response, while --format pretty surfaces a compact
summary with template_content rune-truncated to 200 chars.

sprint: S2
@github-actions github-actions Bot added domain/mail PR touches the mail domain size/M Single-domain feat or fix with limited business impact labels Apr 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

A new CLI shortcut mail +template-get is added to fetch a single personal mail template by --template-id. The implementation includes input validation, API integration, error handling, comprehensive tests, and documentation for the feature.

Changes

Cohort / File(s) Summary
Mail Template Shortcut Implementation
shortcuts/mail/mail_template_get.go
Implements the mail +template-get shortcut with decimal-integer validation for --template-id, API calls to the templates endpoint, OAPI-style error interpretation, and output formatting with content truncation (200 chars) and recipient/attachment counting.
Mail Template Tests
shortcuts/mail/mail_template_get_test.go
Comprehensive test suite validating input validation rules, missing flag detection, successful API responses, error handling, and pretty-print behavior including content truncation and aggregated counts.
Shortcut Registration
shortcuts/mail/shortcuts.go
Registers the new MailTemplateGet shortcut identifier in the Shortcuts() function's returned slice.
Documentation
skills/lark-mail/references/lark-mail-template-get.md
Reference documentation describing CLI usage, parameter validation, output formats (json/pretty/table/ndjson/csv), and response expectations including content truncation in pretty mode.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

size/L

Suggested reviewers

  • chanthuang

Poem

🐰 A template retriever hops through the mail,
Validating IDs with regex's detail,
API calls made, responses unwrapped,
Pretty formatting neatly mapped,
Two hundred chars on display—success at last! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description deviates from the repository template by omitting key required sections (Summary, Changes, Test Plan checkboxes) and instead provides task/sprint metadata without standard summary format. Reorganize the description to follow the template: add a concise Summary, list main Changes, provide Test Plan with checkboxes, and include Related Issues section.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(mail): add +template-get read-only shortcut' is clear, specific, and directly summarizes the main change: adding a new mail template retrieval feature.
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

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 and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 61.01695% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.97%. Comparing base (8ec95a4) to head (c6513fc).
⚠️ Report is 17 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/mail/mail_template_get.go 62.06% 18 Missing and 4 partials ⚠️
shortcuts/mail/shortcuts.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #675   +/-   ##
=======================================
  Coverage   62.96%   62.97%           
=======================================
  Files         436      437    +1     
  Lines       38605    38664   +59     
=======================================
+ Hits        24307    24347   +40     
- Misses      12150    12165   +15     
- Partials     2148     2152    +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add infeng/cli#harness/smoke-cli-mail-template-mini-20260427-160723 -y -g

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.

🧹 Nitpick comments (3)
shortcuts/mail/mail_template_get_test.go (2)

146-183: Optional: add a multi-byte rune truncation case.

The truncation cap is documented as rune-based (common.TruncateStr operates on []rune), but the existing test only uses ASCII as, so it wouldn’t catch a regression that swapped to byte-based slicing. A small follow-up case with multi-byte characters (e.g., strings.Repeat("中", 250)) would lock the rune semantics in.

♻️ Suggested addition
+	// Rune semantics: 250 multi-byte runes should truncate to 200 runes,
+	// not to a 200-byte slice that may split a code point.
+	dataUnicode := map[string]interface{}{
+		"template_id":      "1",
+		"name":             "n",
+		"subject":          "s",
+		"template_content": strings.Repeat("中", 250),
+	}
+	var bufU strings.Builder
+	renderTemplatePretty(&bufU, dataUnicode)
+	if !strings.Contains(bufU.String(), strings.Repeat("中", 200)) {
+		t.Errorf("expected 200 multi-byte runes in pretty output")
+	}
+	if strings.Contains(bufU.String(), strings.Repeat("中", 201)) {
+		t.Errorf("multi-byte template_content was not truncated to 200 runes")
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/mail/mail_template_get_test.go` around lines 146 - 183, Add a test
case to ensure truncation is rune-based by using a multi-byte string (e.g.,
strings.Repeat("中", 250)) and passing it through renderTemplatePretty (or
directly through common.TruncateStr if appropriate) similar to the existing
ASCII test; assert the output contains exactly the expected number of runes
(200) and does not contain 201 runes, mirroring the existing checks that use
strings.Repeat("a", ...), so any byte-based slicing regressions are caught.

97-122: Nit: @ is a gen-delim, not a sub-delim.

Per RFC 3986, @ is a gen-delim; it’s left unescaped in path segments because pchar explicitly permits @. The behavioral assertion (URL keeps the literal @) is correct — only the comment’s classification is off.

📝 Suggested wording tweak
-		// `@` is a sub-delim that url.PathEscape leaves untouched, so the
-		// outgoing URL keeps the literal `@`. mailboxPath would still escape
-		// reserved chars (e.g. `/`); this guards against accidental raw
-		// fmt.Sprintf regression on the segment.
+		// `@` is allowed in path segments (RFC 3986 pchar) and url.PathEscape
+		// leaves it untouched, so the outgoing URL keeps the literal `@`.
+		// mailboxPath would still escape reserved chars (e.g. `/`); this
+		// guards against accidental raw fmt.Sprintf regression on the segment.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/mail/mail_template_get_test.go` around lines 97 - 122, The test
comment in TestMailTemplateGet_PathEscapesMailbox misclassifies the '@'
character as a sub-delim; update the comment to state '@' is a gen-delim per RFC
3986 and keep the rest of the explanation (that url.PathEscape leaves it
unescaped and the test guards against accidental raw fmt.Sprintf regression on
the segment). Locate the comment above the httpmock.Stub in
TestMailTemplateGet_PathEscapesMailbox (reference mailboxPath in the comment)
and replace "sub-delim" with "gen-delim" and adjust wording accordingly so the
comment is factually correct while preserving the intent.
shortcuts/mail/mail_template_get.go (1)

93-104: Optional: prefer-one-shape recipient counting.

Summing across both to and to_recipients (and similarly for cc/bcc) would double-count if the OAPI response ever returns both forms. In practice the API uses one shape, so this is fine, but if you want stricter behavior you could short-circuit per recipient class:

♻️ Optional refactor
 func recipientCount(data map[string]interface{}) int {
-	total := 0
-	for _, key := range []string{"to", "to_recipients", "cc", "cc_recipients", "bcc", "bcc_recipients"} {
-		if list, ok := data[key].([]interface{}); ok {
-			total += len(list)
-		}
-	}
-	return total
+	count := func(primary, fallback string) int {
+		if list, ok := data[primary].([]interface{}); ok {
+			return len(list)
+		}
+		if list, ok := data[fallback].([]interface{}); ok {
+			return len(list)
+		}
+		return 0
+	}
+	return count("to", "to_recipients") + count("cc", "cc_recipients") + count("bcc", "bcc_recipients")
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/mail/mail_template_get.go` around lines 93 - 104, The
recipientCount function can double-count when both alternate shapes exist;
update recipientCount to prefer one shape per recipient class (for each pair:
prefer "to_recipients" if present else "to", prefer "cc_recipients" else "cc",
prefer "bcc_recipients" else "bcc") and short-circuit after finding the first
present list so you only count one shape per class; locate the recipientCount
function and change the loop logic to check each pair in turn (checking
existence/type of the preferred key first) and add its length to total without
also counting the alternate key.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@shortcuts/mail/mail_template_get_test.go`:
- Around line 146-183: Add a test case to ensure truncation is rune-based by
using a multi-byte string (e.g., strings.Repeat("中", 250)) and passing it
through renderTemplatePretty (or directly through common.TruncateStr if
appropriate) similar to the existing ASCII test; assert the output contains
exactly the expected number of runes (200) and does not contain 201 runes,
mirroring the existing checks that use strings.Repeat("a", ...), so any
byte-based slicing regressions are caught.
- Around line 97-122: The test comment in TestMailTemplateGet_PathEscapesMailbox
misclassifies the '@' character as a sub-delim; update the comment to state '@'
is a gen-delim per RFC 3986 and keep the rest of the explanation (that
url.PathEscape leaves it unescaped and the test guards against accidental raw
fmt.Sprintf regression on the segment). Locate the comment above the
httpmock.Stub in TestMailTemplateGet_PathEscapesMailbox (reference mailboxPath
in the comment) and replace "sub-delim" with "gen-delim" and adjust wording
accordingly so the comment is factually correct while preserving the intent.

In `@shortcuts/mail/mail_template_get.go`:
- Around line 93-104: The recipientCount function can double-count when both
alternate shapes exist; update recipientCount to prefer one shape per recipient
class (for each pair: prefer "to_recipients" if present else "to", prefer
"cc_recipients" else "cc", prefer "bcc_recipients" else "bcc") and short-circuit
after finding the first present list so you only count one shape per class;
locate the recipientCount function and change the loop logic to check each pair
in turn (checking existence/type of the preferred key first) and add its length
to total without also counting the alternate key.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87574dbb-e06a-4e71-93d6-7afa8714d18b

📥 Commits

Reviewing files that changed from the base of the PR and between 8ec95a4 and c6513fc.

📒 Files selected for processing (4)
  • shortcuts/mail/mail_template_get.go
  • shortcuts/mail/mail_template_get_test.go
  • shortcuts/mail/shortcuts.go
  • skills/lark-mail/references/lark-mail-template-get.md

@infeng infeng closed this Apr 28, 2026
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/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant