Skip to content

feat(feed): add feed +create shortcut for app feed card#526

Closed
jinzemo wants to merge 7 commits intolarksuite:mainfrom
yxzhaao:feat/feed-app-feed-card
Closed

feat(feed): add feed +create shortcut for app feed card#526
jinzemo wants to merge 7 commits intolarksuite:mainfrom
yxzhaao:feat/feed-app-feed-card

Conversation

@jinzemo
Copy link
Copy Markdown

@jinzemo jinzemo commented Apr 16, 2026

Summary

  • Add new feed domain with +create shortcut to send app feed cards to users
  • Bot-only auth, requires im:app_feed_card:write scope
  • Supports required flags: --user-ids, --title, --link
  • Supports optional flags: --preview, --time-sensitive
  • Includes comprehensive validation, dry-run mode, and skill documentation

Test plan

  • Unit tests pass (go test ./shortcuts/feed/...)
  • E2E tests pass (33/33 tests in sandbox)
  • Acceptance review pass (3/3 scenarios)
  • Skill eval pass (7/7 cases)
  • Validation: user-id format, link HTTPS, title/preview length limits
  • Dry-run outputs correct API path and body

Files changed

File Description
shortcuts/feed/feed_create.go FeedCreate shortcut implementation
shortcuts/feed/feed_create_test.go Unit tests
shortcuts/feed/shortcuts.go Domain registry
shortcuts/register.go Global registration
skills/lark-feed/SKILL.md Domain skill doc
skills/lark-feed/references/lark-feed-create.md Shortcut reference
tests/cli_e2e/feed/2026_04_16_feed_create_test.go E2E tests

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added feed +create command to send app feed card messages to Lark users, supporting multiple recipients (up to 20), title, HTTPS link, optional preview and time-sensitive flag, and dry-run preview.
  • Documentation

    • Added user guide and reference docs describing usage, flags, safety constraints, examples, and expected output.
  • Tests

    • Added unit and end-to-end tests covering success, validation failures, dry-run, and payload behavior.
  • Chores

    • Registered the feed shortcuts so they appear in the CLI.

jinzemo and others added 6 commits April 16, 2026 21:28
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Shortcuts() aggregator in shortcuts/feed/shortcuts.go and register
feed.Shortcuts() in shortcuts/register.go so `lark-cli feed +create`
is available at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use auth status to get userOpenId instead of contact API
- Fix JSON path: data.biz_id and data.failed_cards
- Passes all 6 feed E2E scenarios in sandbox

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 16, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added the size/L Large or sensitive change across domains or core paths label Apr 16, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

Adds a new feed shortcut +create (bot-only) to build and POST app feed cards to /open-apis/im/v2/app_feed_card, including flag validation, dry-run support, response handling, unit and e2e tests, registration in shortcut registry, and documentation for the new skill.

Changes

Cohort / File(s) Summary
Feed Shortcut Implementation
shortcuts/feed/feed_create.go
New FeedCreate shortcut: flags (--user-ids, --link, --title, optional --preview, --time-sensitive), validation rules (user count ≤20, HTTPS link, rune-length checks), DryRun builds request JSON, Execute posts to POST /open-apis/im/v2/app_feed_card and returns biz_id and failed_cards.
Feed Shortcuts Export
shortcuts/feed/shortcuts.go
Adds Shortcuts() returning the feed shortcuts slice (includes FeedCreate).
Shortcut Registration
shortcuts/register.go
Imports feed package and appends feed.Shortcuts() into global allShortcuts in init().
Unit Tests
shortcuts/feed/feed_create_test.go
Adds unit tests for DryRun/Execute flows, validation failures, successful responses, captured request assertions for preview and time_sensitive, and Shortcuts() presence.
E2E Tests
tests/cli_e2e/feed/2026_04_16_feed_create_test.go
Adds CLI e2e tests (positive, negative, dry-run) that discover recipient open_id and assert exit codes and JSON biz_id/failed_cards.
Docs: Skill Manifest
skills/lark-feed/SKILL.md
New skill manifest lark-feed with metadata, notes (bot-only), and reference to +create.
Docs: Reference
skills/lark-feed/references/lark-feed-create.md
New reference doc describing command usage, flags, safety constraints, examples, output schema, and semantics (partial delivery, silent ignores).

Sequence Diagram(s)

sequenceDiagram
    participant User as User/CLI
    participant CLI as Shortcut Runtime
    participant API as Lark Open API
    User->>CLI: run `feed +create` with flags (--as bot, --user-ids, --link, --title, ...)
    CLI->>CLI: validate flags (user count, https link, lengths)
    alt dry-run
        CLI->>User: print prepared POST /open-apis/im/v2/app_feed_card request JSON
    else execute
        CLI->>API: POST /open-apis/im/v2/app_feed_card (user_id_type=open_id, body=app_feed_card)
        API-->>CLI: response JSON (biz_id, failed_cards)
        CLI->>User: print biz_id and failed_cards
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

domain/ccm, size/M

Suggested reviewers

  • fangshuyu-768
  • liujinkun2025

Poem

🐰 A feed card tiptoes into the code,
Bot-only hops along the JSON road,
Twenty friends, a title, an HTTPS link,
Tests nibble edges while docs give a wink,
Cheers — the shortcut wakes from its mode.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding a new feed +create shortcut for app feed cards. It is specific, related to the primary feature, and follows good commit message conventions.
Description check ✅ Passed The PR description exceeds the template requirements with detailed summary, comprehensive test plan with checkmarks, file-by-file breakdown, and verification results. All required sections are present and well-populated.

✏️ 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.

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

🧹 Nitpick comments (2)
skills/lark-feed/references/lark-feed-create.md (1)

81-81: Use “Dry Run” as the section title for consistency.

The flag is --dry-run; matching the heading style (Dry Run) improves scanability across docs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-feed/references/lark-feed-create.md` at line 81, Rename the
section heading currently written as "## DryRun" to "## Dry Run" to match the
flag `--dry-run` and overall docs style; update the heading text in the
lark-feed-create.md file so the section title reads "Dry Run" for consistency
and better scanability with the `--dry-run` flag.
shortcuts/feed/feed_create_test.go (1)

114-148: Optional-fields test should assert request shape, not only response text.

TestFeedCreate_SuccessWithOptionalFields would still pass if --preview / --time-sensitive stopped being included in the outgoing body. Please assert payload content for app_feed_card.preview and app_feed_card.time_sensitive.

As per coding guidelines, “Every behavior change must have an accompanying test.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/feed/feed_create_test.go` around lines 114 - 148, Update
TestFeedCreate_SuccessWithOptionalFields to assert the outgoing request payload
includes the optional fields: capture or inspect the request sent by
runMountedFeedShortcut (via reg.Register's request handler or the httpmock stub
mechanism used in other tests) and assert that the JSON body contains
app_feed_card.preview == "这是预览文字" and app_feed_card.time_sensitive == true;
modify the existing reg.Register call in the test (where the POST to
/open-apis/im/v2/app_feed_card is registered) to inspect the incoming request
body and fail the test if those two fields are missing or incorrect while still
returning the same response.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/feed/feed_create.go`:
- Around line 42-45: The loop that calls common.ValidateUserID on each entry in
userIDs currently discards the trimmed/normalized return value, so raw values
(e.g., " ou_abc ") are later sent in the API body via
runtime.StrArray("user-ids"); update the validation loop in feed_create.go to
capture and replace each userIDs[i] with the cleaned value returned from
common.ValidateUserID (use the validated string result) so the array used to
build runtime.StrArray("user-ids") contains normalized IDs before sending.

In `@tests/cli_e2e/feed/2026_04_16_feed_create_test.go`:
- Around line 147-167: TestFeed_CreateDryRun relies on runtime auth and
discoverFeedRecipientOpenID; replace the dynamic recipient lookup with a static
valid ou_... recipient ID and set the required dry-run environment variables on
the clie2e request to isolate the test. In the TestFeed_CreateDryRun function,
remove the call to discoverFeedRecipientOpenID and use a constant
recipientOpenID string (ou_...), and add the env map entries
LARKSUITE_CLI_APP_ID, APP_SECRET and BRAND to the clie2e.Request (or equivalent
request.Env) so the RunCmd invocation runs with those vars and --dry-run to
validate request structure without hitting real APIs.

---

Nitpick comments:
In `@shortcuts/feed/feed_create_test.go`:
- Around line 114-148: Update TestFeedCreate_SuccessWithOptionalFields to assert
the outgoing request payload includes the optional fields: capture or inspect
the request sent by runMountedFeedShortcut (via reg.Register's request handler
or the httpmock stub mechanism used in other tests) and assert that the JSON
body contains app_feed_card.preview == "这是预览文字" and app_feed_card.time_sensitive
== true; modify the existing reg.Register call in the test (where the POST to
/open-apis/im/v2/app_feed_card is registered) to inspect the incoming request
body and fail the test if those two fields are missing or incorrect while still
returning the same response.

In `@skills/lark-feed/references/lark-feed-create.md`:
- Line 81: Rename the section heading currently written as "## DryRun" to "##
Dry Run" to match the flag `--dry-run` and overall docs style; update the
heading text in the lark-feed-create.md file so the section title reads "Dry
Run" for consistency and better scanability with the `--dry-run` flag.
🪄 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

Run ID: e476e47c-f539-400a-8f59-49df8d2f82c3

📥 Commits

Reviewing files that changed from the base of the PR and between c442fa2 and 191eca8.

📒 Files selected for processing (7)
  • shortcuts/feed/feed_create.go
  • shortcuts/feed/feed_create_test.go
  • shortcuts/feed/shortcuts.go
  • shortcuts/register.go
  • skills/lark-feed/SKILL.md
  • skills/lark-feed/references/lark-feed-create.md
  • tests/cli_e2e/feed/2026_04_16_feed_create_test.go

Comment thread shortcuts/feed/feed_create.go
Comment thread tests/cli_e2e/feed/2026_04_16_feed_create_test.go
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 77.19298% with 13 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@44e7b5b). Learn more about missing BASE report.

Files with missing lines Patch % Lines
shortcuts/feed/feed_create.go 75.47% 10 Missing and 3 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #526   +/-   ##
=======================================
  Coverage        ?   59.09%           
=======================================
  Files           ?      386           
  Lines           ?    32693           
  Branches        ?        0           
=======================================
  Hits            ?    19320           
  Misses          ?    11562           
  Partials        ?     1811           

☔ 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

github-actions Bot commented Apr 16, 2026

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add yxzhaao/cli#feat/feed-app-feed-card -y -g

- Remove net/http import, use string literal for HTTP method
- Add user ID normalization with strings.TrimSpace
- Fix docs: "DryRun" -> "Dry Run" in reference doc
- Add request payload assertions in optional fields test
- Use static user ID for dry-run E2E test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

♻️ Duplicate comments (1)
tests/cli_e2e/feed/2026_04_16_feed_create_test.go (1)

149-161: ⚠️ Potential issue | 🟠 Major

Set required dry-run E2E env vars explicitly in-test.

Line 153 constructs the dry-run invocation without setting LARKSUITE_CLI_APP_ID, APP_SECRET, and BRAND, so this test can still depend on ambient machine state.

🔧 Proposed fix
 func TestFeed_CreateDryRun(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	t.Cleanup(cancel)
+	t.Setenv("LARKSUITE_CLI_APP_ID", "cli_e2e_dryrun_app_id")
+	t.Setenv("APP_SECRET", "cli_e2e_dryrun_app_secret")
+	t.Setenv("BRAND", "feishu")

 	result, err := clie2e.RunCmd(ctx, clie2e.Request{
 		Args: []string{"feed", "+create",
 			"--user-ids", "ou_test_dry_run_static",

As per coding guidelines, “Dry-run E2E tests must set env vars LARKSUITE_CLI_APP_ID, APP_SECRET, BRAND and use --dry-run flag to validate request structure without calling real APIs.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/cli_e2e/feed/2026_04_16_feed_create_test.go` around lines 149 - 161,
The TestFeed_CreateDryRun test builds a dry-run invocation but doesn't set
required E2E env vars, so it can leak ambient state; before calling
clie2e.RunCmd in TestFeed_CreateDryRun, set LARKSUITE_CLI_APP_ID, APP_SECRET,
and BRAND (use t.Setenv or os.Setenv + t.Cleanup to restore) so the
clie2e.Request/Args call always runs with those explicit dry-run credentials;
keep the existing "--dry-run" arg and then call clie2e.RunCmd as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/cli_e2e/feed/2026_04_16_feed_create_test.go`:
- Around line 149-161: The TestFeed_CreateDryRun test builds a dry-run
invocation but doesn't set required E2E env vars, so it can leak ambient state;
before calling clie2e.RunCmd in TestFeed_CreateDryRun, set LARKSUITE_CLI_APP_ID,
APP_SECRET, and BRAND (use t.Setenv or os.Setenv + t.Cleanup to restore) so the
clie2e.Request/Args call always runs with those explicit dry-run credentials;
keep the existing "--dry-run" arg and then call clie2e.RunCmd as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ec6d28fa-27b8-4f70-8856-69b41e142836

📥 Commits

Reviewing files that changed from the base of the PR and between 191eca8 and fa4aaf1.

📒 Files selected for processing (4)
  • shortcuts/feed/feed_create.go
  • shortcuts/feed/feed_create_test.go
  • skills/lark-feed/references/lark-feed-create.md
  • tests/cli_e2e/feed/2026_04_16_feed_create_test.go
✅ Files skipped from review due to trivial changes (1)
  • skills/lark-feed/references/lark-feed-create.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • shortcuts/feed/feed_create.go

@liuxinyanglxy
Copy link
Copy Markdown
Collaborator

This PR introduces improvements to the CLI around event handling and command structure.

Overall, the changes make the interface more consistent and align better with common CLI design patterns (resource-oriented commands like event consume).

The implementation looks clean and follows the existing architecture, with clear separation between command definition and execution logic.

From a usability perspective, this should improve discoverability and reduce confusion for both human users and AI agents.

Impact is mostly localized to the event-related commands and should be backward-compatible (if aliases or migration paths are handled properly).

Nice work overall 👍

@jinzemo jinzemo closed this Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants