Skip to content

fix(close): make issue close/cancel idempotent when already in terminal state - #113

Merged
bougyman merged 1 commit into
mainfrom
CRY-42-idempotent-issue-close
Aug 14, 2026
Merged

fix(close): make issue close/cancel idempotent when already in terminal state#113
bougyman merged 1 commit into
mainfrom
CRY-42-idempotent-issue-close

Conversation

@bougyman

Copy link
Copy Markdown
Member

Summary

  • Adds state attribute to the Issue resource and includes state { id name type } in GraphQL queries, giving the CLI visibility into an issue's current workflow-state type.
  • Short-circuits close_issue/2 and cancel_issue/2 in IssueHelpers: when issue.state.type already matches the target (completed / cancelled), skips the reason comment and issueUpdate mutation, prints "<identifier> is already <state name>", and returns {:ok, issue}.
  • Fixes Issue.Update.Close mutation payload: omits trashed entirely when not requested instead of sending "trashed" => false, which the Linear API rejects.

Test plan

  • IssueHelpers.close_issue/2 no-ops and prints accessible message when issue is already completed
  • IssueHelpers.close_issue/2 no-ops when called with cancel: true and issue is already cancelled
  • IssueHelpers.cancel_issue/2 no-ops and prints accessible message when issue is already cancelled
  • Linear.close_issue/2 omits trashed from mutation input when not requested
  • Linear.close_issue/2 sends trashed: true only when explicitly requested
  • Issue.from_map/1 parses state from API response into a WorkflowState struct
  • All 231 existing and new tests pass

🤖 Generated with Claude Code

…al state

- Add `state` attribute to Issue resource; include `state { id name type }`
  in both base_fields and full_fields GraphQL queries so the CLI can inspect
  an issue's current workflow-state type.

- Short-circuit `close_issue/2` and `cancel_issue/2` in IssueHelpers: when
  `issue.state.type` is already the target type (completed / cancelled), skip
  the comment and mutation, print "<identifier> is already <state name>", and
  return `{:ok, issue}`.

- Fix `Issue.Update.Close` mutation payload: omit `trashed` entirely when
  false instead of sending `"trashed" => false`, which the Linear API rejects
  (only `true` or null are valid).

- Tests: add idempotency cases for close, cancel, and close-with-cancel-flag;
  verify state is parsed from API responses; update trashed-omission assertion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 14, 2026 18:39

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@bougyman
bougyman merged commit 0a71060 into main Aug 14, 2026
2 checks passed
@bougyman
bougyman deleted the CRY-42-idempotent-issue-close branch August 14, 2026 18:46
bougyman pushed a commit that referenced this pull request Aug 14, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.6.0](v1.5.1...v1.6.0)
(2026-08-14)


### Features

* **build:** add mix burrito.dinein for local binary builds
([#112](#112))
([decf951](decf951))


### Bug Fixes

* **ai:** adds CLAUDE.md symlink
([#110](#110))
([5165c4e](5165c4e))
* **close:** make issue close/cancel idempotent when already in terminal
state ([#113](#113))
([0a71060](0a71060))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants