Skip to content

fix(docs): validate --selection-by-title format early#256

Open
wwenrr wants to merge 2 commits intolarksuite:mainfrom
wwenrr:fix/issue-93-selection-by-title-validation
Open

fix(docs): validate --selection-by-title format early#256
wwenrr wants to merge 2 commits intolarksuite:mainfrom
wwenrr:fix/issue-93-selection-by-title-validation

Conversation

@wwenrr
Copy link
Copy Markdown

@wwenrr wwenrr commented Apr 3, 2026

Summary

  • add early validation for docs +update --selection-by-title so invalid plain-text inputs are rejected before sending MCP requests
  • require markdown heading syntax (e.g. ## Section) for --selection-by-title
  • add explicit error messages that guide users to the expected format

Why

Issue #93 reports that users pass plain titles (like 第二章) and receive opaque MCP validation failures. This change fails fast in CLI with actionable guidance, reducing trial-and-error and noisy server calls.

Thinking path

  • Considered implementing server-side title parsing changes, but that requires MCP-side updates and longer review cycle.
  • Chose a CLI-side guard as a small, isolated fix suitable for quick contribution scope.
  • Added tests around the validator to lock behavior and keep error guidance stable.

Changes

  • shortcuts/doc/docs_update.go
    • call validateSelectionByTitle during flag validation
    • new helper validates:
      • empty title => pass
      • heading-style title (#, ##, etc.) => pass
      • multi-line title => fail with single-line guidance
      • plain text title => fail with heading-prefix guidance
  • shortcuts/doc/docs_update_test.go
    • add TestValidateSelectionByTitle for pass/fail cases

Verification

Executed in Docker (host has no Go toolchain):

docker run --rm -v /tmp/larksuite-cli:/src -w /src golang:1.24 bash -lc "export PATH=/usr/local/go/bin:$PATH; go test ./shortcuts/doc -run 'TestValidateSelectionByTitle|TestIsWhiteboardCreateMarkdown|TestNormalizeDocsUpdateResult'"

Result: ok github.com/larksuite/cli/shortcuts/doc

Also ran broad suite check:

docker run --rm -v /tmp/larksuite-cli:/src -w /src golang:1.24 bash -lc "export PATH=/usr/local/go/bin:$PATH; go test ./..."

Observed unrelated pre-existing failures in internal/registry and e2e integration tests requiring external binaries/env; changed package tests pass.

Closes #93

Summary by CodeRabbit

  • Bug Fixes

    • Strengthened validation for the --selection-by-title option: trims whitespace, rejects line breaks, and enforces a markdown heading prefix with clearer error messages.
  • Tests

    • Added unit tests covering valid and invalid title inputs and asserting the improved validation and error guidance.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 3, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added domain/ccm PR touches the ccm domain size/M Single-domain feat or fix with limited business impact labels Apr 3, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

DocsUpdate now validates the --selection-by-title flag via a new helper validateSelectionByTitle. The validator trims whitespace, permits empty titles, rejects inputs containing \n or \r, accepts values that start with #, and otherwise returns a flag error requiring a markdown heading prefix.

Changes

Cohort / File(s) Summary
Selection-by-title validation
shortcuts/doc/docs_update.go
Added validateSelectionByTitle(title string) error that trims whitespace, allows empty titles, rejects multiline input (\n/\r), accepts titles beginning with #, and returns a common.FlagErrorf guiding users to use a markdown heading. Integrated this check into DocsUpdate's Validate flow for --selection-by-title.
Validation tests
shortcuts/doc/docs_update_test.go
Added TestValidateSelectionByTitle with subtests covering empty, heading-prefixed, plain-text, and multiline inputs. Introduced containsAll helper and updated imports; tests assert accepted and rejected cases and require error messages to include specific guidance tokens.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇📜 I trim my whiskers, trim your title too,
No sneaky newlines, just headings that brew.
Start with a hash, or leave it blank — it's fine,
A rabbit-approved rule for your doc's outline. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding early validation for the --selection-by-title format.
Description check ✅ Passed The description covers all required template sections with clear summary, detailed changes, comprehensive test verification, and linked issue reference.
Linked Issues check ✅ Passed The PR addresses issue #93 by adding CLI-side validation for --selection-by-title format, rejecting plain-text inputs and requiring markdown heading syntax, which implements a fail-fast approach to guide users toward correct usage.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the stated objectives: validator implementation in docs_update.go and comprehensive test coverage in docs_update_test.go, with no unrelated modifications.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR adds early client-side validation for the --selection-by-title flag in docs update, rejecting plain-text titles and multi-line inputs before any MCP request is made, with actionable error messages pointing users to the correct markdown-heading syntax.

Key changes:

  • shortcuts/doc/docs_update.go: New validateSelectionByTitle helper called during flag validation. Multi-line check (\n/\r) is evaluated before the #-prefix check, so inputs like "## A\n## B" are correctly rejected. Empty titles pass through (flag is optional).
  • shortcuts/doc/docs_update_test.go: TestValidateSelectionByTitle covers empty, single-heading-pass, plain-text-fail, multi-line-heading-fail, and multi-line-plain-fail cases — including the "## 第二章\n## 第三章" case that was flagged as missing in a prior review.
  • Both issues raised in previous review threads (check ordering and missing test) have been resolved in the current HEAD.

Confidence Score: 5/5

Safe to merge — logic is correct, tests are comprehensive, and both prior review concerns have been resolved.

No P0 or P1 findings remain. The two issues flagged in previous review threads (multi-line check ordering and the missing multi-line-heading test case) are both addressed in the current HEAD. The validation logic is simple and well-covered by tests.

No files require special attention.

Important Files Changed

Filename Overview
shortcuts/doc/docs_update.go Adds validateSelectionByTitle helper and wires it into flag validation; multi-line check correctly precedes the #-prefix check, addressing the ordering concern raised in prior review threads.
shortcuts/doc/docs_update_test.go Adds TestValidateSelectionByTitle covering empty, single-heading, plain-text, multi-line heading (`## A

B`), and multi-line plain-text cases; the previously-missing multi-line heading test is now present. |

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["validateSelectionByTitle(title)"] --> B{title == ""}
    B -- yes --> C[return nil ✓]
    B -- no --> D["trimmed = TrimSpace(title)"]
    D --> E{"contains \n or \r?"}
    E -- yes --> F["error: must be a single heading line"]
    E -- no --> G{"HasPrefix(trimmed, '#')"}
    G -- yes --> H[return nil ✓]
    G -- no --> I["error: must include markdown heading prefix '#'"]
Loading

Reviews (2): Last reviewed commit: "fix(docs): reject multiline selection-by..." | Re-trigger Greptile

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

🤖 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/doc/docs_update.go`:
- Around line 168-173: The current logic returns early for any trimmed string
starting with "#" (trimmed variable) before checking for newlines, allowing
multiline headings like "## Section\nNext" to pass; change the order or add a
newline check before the prefix acceptance so strings containing "\n" or "\r"
trigger common.FlagErrorf("--selection-by-title must be a single heading line
(for example: '## Section')") even if they start with "#". Ensure the multiline
guard (strings.Contains(trimmed, "\n") || strings.Contains(trimmed, "\r")) runs
prior to the if strings.HasPrefix(trimmed, "#") return nil branch.
🪄 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: 93550292-bb6d-47a0-9c95-a404218a42e1

📥 Commits

Reviewing files that changed from the base of the PR and between 0c77c95 and 73559f8.

📒 Files selected for processing (2)
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_test.go

@wwenrr
Copy link
Copy Markdown
Author

wwenrr commented Apr 3, 2026

Addressed review feedback ✅

I fixed the validation-order bug in validateSelectionByTitle:

  • now checks multiline (\n/\r) before heading-prefix check
  • so inputs like "## A\n## B" are rejected correctly

Added test coverage:

  • multi-line heading still fails case in TestValidateSelectionByTitle

Verification:

docker run --rm -v /tmp/larksuite-cli:/src -w /src golang:1.24 bash -lc "export PATH=/usr/local/go/bin:$PATH; go test ./shortcuts/doc -run 'TestValidateSelectionByTitle|TestIsWhiteboardCreateMarkdown|TestNormalizeDocsUpdateResult'"

Result: pass (ok github.com/larksuite/cli/shortcuts/doc)

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 (1)
shortcuts/doc/docs_update_test.go (1)

88-92: Consider adding edge case tests for robustness.

The current tests cover the main scenarios well. For additional confidence, consider adding tests for:

  • Single # heading: "# Title"
  • Leading/trailing whitespace: " ## Section "
  • Windows line endings: "## A\r\n## B"
📝 Additional test cases
 	t.Run("heading style title passes", func(t *testing.T) {
 		if err := validateSelectionByTitle("## 第二章"); err != nil {
 			t.Fatalf("expected nil error, got %v", err)
 		}
 	})
+
+	t.Run("single # heading passes", func(t *testing.T) {
+		if err := validateSelectionByTitle("# Title"); err != nil {
+			t.Fatalf("expected nil error, got %v", err)
+		}
+	})
+
+	t.Run("heading with surrounding whitespace passes", func(t *testing.T) {
+		if err := validateSelectionByTitle("  ## Section  "); err != nil {
+			t.Fatalf("expected nil error, got %v", err)
+		}
+	})
+
+	t.Run("windows line endings fail", func(t *testing.T) {
+		err := validateSelectionByTitle("## A\r\n## B")
+		if err == nil {
+			t.Fatalf("expected validation error")
+		}
+	})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/doc/docs_update_test.go` around lines 88 - 92, Add edge-case
table-driven tests for validateSelectionByTitle: include t.Run cases for
single-level heading "# Title", headings with leading/trailing whitespace like "
## Section  ", and Windows CRLF input "## A\r\n## B" to ensure trimming and CRLF
handling; locate the existing test block that contains t.Run("heading style
title passes", func(t *testing.T) { ... }) and add these additional t.Run
subtests asserting nil error (or expected behavior) for each input.
🤖 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/doc/docs_update_test.go`:
- Around line 88-92: Add edge-case table-driven tests for
validateSelectionByTitle: include t.Run cases for single-level heading "#
Title", headings with leading/trailing whitespace like "  ## Section  ", and
Windows CRLF input "## A\r\n## B" to ensure trimming and CRLF handling; locate
the existing test block that contains t.Run("heading style title passes", func(t
*testing.T) { ... }) and add these additional t.Run subtests asserting nil error
(or expected behavior) for each input.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 09644839-3178-4aa3-9e60-4717982abd83

📥 Commits

Reviewing files that changed from the base of the PR and between 73559f8 and e50a006.

📒 Files selected for processing (2)
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_update_test.go

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

Labels

domain/ccm PR touches the ccm 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.

--selection-by-title 无法匹配标题

2 participants