Skip to content

fix: skip task completion when already completed#218

Merged
liangshuo-1 merged 1 commit intolarksuite:mainfrom
ILUO:fix/task-complete-skip-if-completed
Apr 3, 2026
Merged

fix: skip task completion when already completed#218
liangshuo-1 merged 1 commit intolarksuite:mainfrom
ILUO:fix/task-complete-skip-if-completed

Conversation

@ILUO
Copy link
Copy Markdown
Contributor

@ILUO ILUO commented Apr 2, 2026

Summary

Avoid redundant completion requests by checking the current task status before issuing a PATCH.
This makes task +complete idempotent for already-completed tasks.

Changes

  • Skip PATCH when the task is already completed in shortcuts/task/task_complete.go
  • Render created_at / due_at using local time in shortcuts/task/task_get_my_tasks.go
  • Add httpmock-based table-driven tests for task shortcuts (+complete, +get-my-tasks)
  • Update skills/lark-task docs: reminder prerequisites and local-time rendering notes

Test Plan

  • go test ./shortcuts/task -run "TestCompleteTask|TestGetMyTasks_LocalTimeFormatting" -v

  • Manual verification

    • lark task +complete --task-id <id> --as bot --format pretty
    • lark task +get-my-tasks --as user --format pretty

Related Issues

N/A

Summary by CodeRabbit

  • New Features

    • Smarter task completion: checks current task state before completing; dry-run shows GET then conditional PATCH.
  • Bug Fixes

    • Task timestamps now render in local time.
  • Documentation

    • Added notes: create/update constraints, reminders require a due date, prefer showing user names over raw IDs, and local-time timestamp guidance.
  • Tests

    • Added tests and test helpers for completion scenarios and local-time formatting.

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

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: af438d5a-2188-4b18-a7c0-6218f91c8f2e

📥 Commits

Reviewing files that changed from the base of the PR and between 27100dc and 1eddd92.

📒 Files selected for processing (8)
  • shortcuts/task/task_complete.go
  • shortcuts/task/task_complete_test.go
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go
  • shortcuts/task/task_shortcut_test.go
  • skills/lark-task/SKILL.md
  • skills/lark-task/references/lark-task-get-my-tasks.md
  • skills/lark-task/references/lark-task-reminder.md
✅ Files skipped from review due to trivial changes (4)
  • skills/lark-task/references/lark-task-get-my-tasks.md
  • skills/lark-task/SKILL.md
  • shortcuts/task/task_shortcut_test.go
  • skills/lark-task/references/lark-task-reminder.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go

📝 Walkthrough

Walkthrough

Execute for task-complete now GETs the task first and skips PATCH if completed_at is set; otherwise it PATCHes to complete. Added tests and test utilities, changed task timestamp rendering to local time, and updated skill docs to require due dates for reminders/repeat rules and advise local-time rendering and name resolution.

Changes

Cohort / File(s) Summary
Task Complete Flow
shortcuts/task/task_complete.go, shortcuts/task/task_complete_test.go
Execute now performs GET /open-apis/task/v2/tasks/{taskId} and inspects task.completed_at; if present and not "0" it returns GET result and skips PATCH; otherwise builds payload and PATCHes to complete. Added table-driven tests for completed/not-completed and JSON output cases.
Task List Time Formatting
shortcuts/task/task_get_my_tasks.go, shortcuts/task/task_get_my_tasks_test.go
Changed timestamp rendering from UTC to local time for created_at, due.timestamp, and human-readable date/time fields; added tests asserting local-time formatted output for pretty and JSON formats.
Task Test Utilities
shortcuts/task/task_shortcut_test.go
Added test helpers: deterministic CLI config, tenant token/warm stubs, shortcut mounting and execution helpers (taskTestConfig, warmTenantToken, taskShortcutTestFactory, runMountedTaskShortcut).
Skill Documentation
skills/lark-task/SKILL.md, skills/lark-task/references/lark-task-reminder.md, skills/lark-task/references/lark-task-get-my-tasks.md
Docs: require due for repeat_rule/reminder; require start <= due when both provided; forbid cross-tenant member adds with tenant_access_token; advise resolving/displaying real user names (not only IDs); require rendering timestamps in local timezone (format noted).

Sequence Diagram(s)

sequenceDiagram
    participant User as User/CLI
    participant Shortcut as Shortcut.Execute
    participant API as Task API
    User->>Shortcut: +complete --task-id {id}
    Shortcut->>API: GET /open-apis/task/v2/tasks/{id}
    API-->>Shortcut: task data (includes completed_at)
    alt completed_at present and != "0"
        Shortcut-->User: return GET result (skip PATCH)
    else not completed
        Shortcut->>API: PATCH /open-apis/task/v2/tasks/{id} (buildCompleteBody)
        API-->>Shortcut: patched task data
        Shortcut-->User: return patched result
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • liangshuo-1

Poem

🐰 I sniffed the task, then took a peek,
If done already, I saved the tweak,
Else I nudged it gently to complete,
Local times now make dates more sweet,
Tests and notes — a carrot treat.

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: skip task completion when already completed' accurately and specifically describes the main change in the PR, which is adding logic to prevent redundant completion requests when a task is already completed.
Description check ✅ Passed The PR description covers all required template sections: Summary explains the motivation, Changes lists all main modifications, Test Plan details verification steps with checkboxes, and Related Issues is addressed.

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

@ILUO
Copy link
Copy Markdown
Contributor Author

ILUO commented Apr 2, 2026 via email

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 2, 2026

Greptile Summary

This PR makes task +complete idempotent by prefetching the task's current state before issuing the PATCH, and fixes timestamp rendering to use the local timezone instead of UTC. Both changes are well-scoped and accompanied by httpmock-based table-driven tests.

  • Idempotency check (task_complete.go): a GET is issued first; if completed_at is non-empty and non-"0", the PATCH is skipped and the GET response is used directly for output. The fallback path (missing or nil task field → empty completedAtStr) correctly falls through to PATCH, so unusual API responses degrade gracefully.
  • Local-time rendering (task_get_my_tasks.go): three .UTC() calls replaced with .Local() for created_at and due.timestamp fields in both JSON and pretty-print output paths.
  • Tests (task_complete_test.go, task_get_my_tasks_test.go, task_shortcut_test.go): warmTenantToken is a plain per-test function (no package-level sync.Once); GetMyTasks is copied by value before its AuthTypes field is reassigned, so the package-level variable is never mutated — both concerns from the prior review are properly addressed.
  • Docs (SKILL.md, lark-task-get-my-tasks.md, lark-task-reminder.md): prerequisite callouts (due-date required for reminders, local-time rendering, user-name resolution) added in both Chinese and English sections.

Confidence Score: 5/5

This PR is safe to merge — both changes are correct, well-tested, and the previous review concerns have been fully addressed.

No P0 or P1 issues found. The idempotency logic correctly handles all edge cases (nil task map, missing field, zero value). The local-time fix is a straightforward and correct API change. Prior concerns (sync.Once warm-up, package-level struct mutation) are resolved cleanly in the new test helpers.

No files require special attention.

Important Files Changed

Filename Overview
shortcuts/task/task_complete.go Adds a GET-then-conditional-PATCH pattern to skip redundant completion calls; logic is correct and the "already completed" check is safe against nil/missing fields.
shortcuts/task/task_shortcut_test.go New test helper file; warmTenantToken is a plain function per-test (no sync.Once), addressing the previous review concern cleanly.
shortcuts/task/task_complete_test.go Table-driven tests cover already-completed and not-completed paths; omitting the PATCH stub for the already-completed case correctly validates the skip logic.
shortcuts/task/task_get_my_tasks.go Three timestamp formatting calls changed from .UTC() to .Local(); straightforward and correct local-time rendering fix.
shortcuts/task/task_get_my_tasks_test.go Uses a local struct copy (s := GetMyTasks) instead of mutating the package-level variable, properly addressing the previous race concern.
skills/lark-task/SKILL.md Documentation additions for create/update constraints, user-name display, and local-time rendering; no code changes.
skills/lark-task/references/lark-task-get-my-tasks.md Adds output rendering notes (user name resolution, local timezone); documentation only.
skills/lark-task/references/lark-task-reminder.md Clarifies that reminders require a due date; single-line documentation fix.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI (task +complete)
    participant API as Lark Task API

    CLI->>API: GET /open-apis/task/v2/tasks/{id}
    API-->>CLI: task data (incl. completed_at)

    alt completed_at != "" and != "0"
        Note over CLI: Task already completed — skip PATCH
        CLI->>CLI: Use GET response as output data
    else task not yet completed
        CLI->>API: PATCH /open-apis/task/v2/tasks/{id}
        API-->>CLI: updated task data
    end

    CLI->>CLI: Render output (pretty / JSON)
Loading

Reviews (4): Last reviewed commit: "fix: skip task completion when already c..." | 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.

🧹 Nitpick comments (2)
shortcuts/task/task_complete_test.go (1)

21-50: Consider adding a test case for "already completed json format".

The test covers pretty format for already-completed tasks and json format for not-completed tasks, but there's no test case verifying JSON output when the task is already completed. This would ensure the skip-PATCH path also produces correct JSON output.

➕ Proposed additional test case
 		{
 			name:        "task not completed json format",
 			taskId:      "task-789",
 			isCompleted: false,
 			formatFlag:  "json",
 			expectedOutput: []string{
 				`"guid": "task-789"`,
 			},
 		},
+		{
+			name:        "task already completed json format",
+			taskId:      "task-abc",
+			isCompleted: true,
+			formatFlag:  "json",
+			expectedOutput: []string{
+				`"guid": "task-abc"`,
+			},
+		},
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/task/task_complete_test.go` around lines 21 - 50, Add a test case
to the tests slice in task_complete_test.go that exercises the JSON output path
when a task is already completed: create an entry with name like "task already
completed json format", taskId (e.g., "task-123"), isCompleted: true,
formatFlag: "json", and expectedOutput containing the JSON field(s) you expect
(e.g., a `"guid": "task-123"` fragment). Ensure the new test struct uses the
same fields as existing cases (name, taskId, isCompleted, formatFlag,
expectedOutput) so it participates in the same test loop that calls the task
completion handler.
shortcuts/task/task_complete.go (1)

33-40: DryRun still shows PATCH even when task might be completed.

The DryRun function always returns a PATCH operation, which doesn't reflect the actual runtime behavior where a GET is performed first. This is likely acceptable since dry-run is meant to show the potential write operation, but users might be confused if they see "PATCH" in dry-run output for an already-completed task.

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

In `@shortcuts/task/task_complete.go` around lines 33 - 40, The DryRun function
always returns a PATCH which can mislead users when the real flow does a
preliminary GET for already-completed tasks; update DryRun (in the DryRun
closure) to inspect a runtime flag (e.g., runtime.Str("task-status") or a
boolean like runtime.Bool("task-completed")) and if the task is already
completed return a GET dry-run using the same taskId
(common.NewDryRunAPI().GET("/open-apis/task/v2/tasks/"+taskId).Params(...)),
otherwise keep returning the PATCH with buildCompleteBody(); refer to the DryRun
function, buildCompleteBody, and common.NewDryRunAPI to implement this
conditional behavior.
🤖 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/task/task_complete_test.go`:
- Around line 21-50: Add a test case to the tests slice in task_complete_test.go
that exercises the JSON output path when a task is already completed: create an
entry with name like "task already completed json format", taskId (e.g.,
"task-123"), isCompleted: true, formatFlag: "json", and expectedOutput
containing the JSON field(s) you expect (e.g., a `"guid": "task-123"` fragment).
Ensure the new test struct uses the same fields as existing cases (name, taskId,
isCompleted, formatFlag, expectedOutput) so it participates in the same test
loop that calls the task completion handler.

In `@shortcuts/task/task_complete.go`:
- Around line 33-40: The DryRun function always returns a PATCH which can
mislead users when the real flow does a preliminary GET for already-completed
tasks; update DryRun (in the DryRun closure) to inspect a runtime flag (e.g.,
runtime.Str("task-status") or a boolean like runtime.Bool("task-completed")) and
if the task is already completed return a GET dry-run using the same taskId
(common.NewDryRunAPI().GET("/open-apis/task/v2/tasks/"+taskId).Params(...)),
otherwise keep returning the PATCH with buildCompleteBody(); refer to the DryRun
function, buildCompleteBody, and common.NewDryRunAPI to implement this
conditional behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 760add5d-eb84-48b4-a2a7-fd130fa12c28

📥 Commits

Reviewing files that changed from the base of the PR and between 112dd5f and dd113fc.

📒 Files selected for processing (7)
  • shortcuts/task/task_complete.go
  • shortcuts/task/task_complete_test.go
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go
  • shortcuts/task/task_shortcut_test.go
  • skills/lark-task/SKILL.md
  • skills/lark-task/references/lark-task-reminder.md

@ILUO ILUO force-pushed the fix/task-complete-skip-if-completed branch from dd113fc to 1963f46 Compare April 2, 2026 10:14
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 2, 2026

CLA assistant check
All committers have signed the CLA.

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 `@skills/lark-task/SKILL.md`:
- Around line 24-25: The blockquote in SKILL.md contains extra blank lines that
violate markdownlint rule MD028; remove any empty lines between the lines that
start with the blockquote marker (the leading '>' characters) so the quote lines
are contiguous (ensure every quoted line begins with '>' with no intervening
blank lines), preserving the existing quote text and indentation.
🪄 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: c7dfdcc4-571f-4a37-b69d-038bef6f7d01

📥 Commits

Reviewing files that changed from the base of the PR and between dd113fc and 1963f46.

📒 Files selected for processing (7)
  • shortcuts/task/task_complete.go
  • shortcuts/task/task_complete_test.go
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go
  • shortcuts/task/task_shortcut_test.go
  • skills/lark-task/SKILL.md
  • skills/lark-task/references/lark-task-reminder.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-task/references/lark-task-reminder.md
  • shortcuts/task/task_complete_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go

@ILUO ILUO force-pushed the fix/task-complete-skip-if-completed branch from 1963f46 to 27100dc Compare April 3, 2026 03:14
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

♻️ Duplicate comments (1)
skills/lark-task/SKILL.md (1)

24-25: ⚠️ Potential issue | 🟡 Minor

Fix blockquote blank lines to satisfy markdownlint MD028.

This issue was already identified in a previous review. There are blank lines inside the blockquote block, which triggers lint warnings. To properly separate the two blockquote sections, remove the > marker from these blank lines.

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

In `@skills/lark-task/SKILL.md` around lines 24 - 25, The blockquote in SKILL.md
contains blank lines that still include the '>' marker, triggering markdownlint
MD028; edit the blockquote so blank separator lines do not start with '>'
(remove the '>' from those empty lines) to properly separate the two blockquote
sections and eliminate the MD028 warning while keeping the rest of the
'>'-prefixed quoted lines intact.
🤖 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/task/task_complete_test.go`:
- Around line 101-108: The current fragile normalization uses
strings.ReplaceAll(out, `":"`, `": "`) in the test, which can corrupt non-JSON
content; replace that logic by detecting and normalizing JSON output: check
json.Valid(out) (or attempt json.Unmarshal into a variable), and if it is valid
JSON unmarshal and re-marshal (e.g., json.MarshalIndent or json.Marshal) to
produce a stable normalized string (assign to outNorm), otherwise keep out
unchanged; update the checks that iterate tt.expectedOutput to use the
normalized outNorm and fall back to out when not JSON, referencing the variables
out, outNorm, and tt.expectedOutput and removing the broad strings.ReplaceAll
call.

---

Duplicate comments:
In `@skills/lark-task/SKILL.md`:
- Around line 24-25: The blockquote in SKILL.md contains blank lines that still
include the '>' marker, triggering markdownlint MD028; edit the blockquote so
blank separator lines do not start with '>' (remove the '>' from those empty
lines) to properly separate the two blockquote sections and eliminate the MD028
warning while keeping the rest of the '>'-prefixed quoted lines intact.
🪄 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: f0a0ce35-f754-42fa-9bcf-a70e433e4677

📥 Commits

Reviewing files that changed from the base of the PR and between 1963f46 and 27100dc.

📒 Files selected for processing (8)
  • shortcuts/task/task_complete.go
  • shortcuts/task/task_complete_test.go
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_get_my_tasks_test.go
  • shortcuts/task/task_shortcut_test.go
  • skills/lark-task/SKILL.md
  • skills/lark-task/references/lark-task-get-my-tasks.md
  • skills/lark-task/references/lark-task-reminder.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-task/references/lark-task-get-my-tasks.md
  • skills/lark-task/references/lark-task-reminder.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • shortcuts/task/task_get_my_tasks.go
  • shortcuts/task/task_complete.go
  • shortcuts/task/task_get_my_tasks_test.go

@ILUO ILUO force-pushed the fix/task-complete-skip-if-completed branch from 27100dc to 1eddd92 Compare April 3, 2026 03:39
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add ILUO/cli#fix/task-complete-skip-if-completed -y -g

@liangshuo-1 liangshuo-1 merged commit 135fde8 into larksuite:main Apr 3, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

4 participants