agentpr: close and reopen issues
- add issue close and issue reopen subcommands - add GetIssue and SetIssueState to the Gitea client - fail when the issue is already in the requested state - document the new subcommands in README.md and AGENTS.md
This commit is contained in:
@@ -329,6 +329,46 @@ func (c *GiteaClient) EditIssue(repoPath string, number int, opts EditOptions) (
|
||||
return issue, err
|
||||
}
|
||||
|
||||
// Issue states Gitea accepts on a state change. Gitea has no third state: an
|
||||
// issue is open or closed.
|
||||
const (
|
||||
IssueStateOpen = "open"
|
||||
IssueStateClosed = "closed"
|
||||
)
|
||||
|
||||
// ErrIssueStateUnchanged reports a state change asked for the state the issue
|
||||
// is already in. Gitea answers such a PATCH with 200 and changes nothing, so
|
||||
// without this check closing an already-closed issue would look like it worked.
|
||||
var ErrIssueStateUnchanged = errors.New("issue is already in that state")
|
||||
|
||||
// GetIssue fetches a single issue
|
||||
// (GET /api/v1/repos/{owner}/{repo}/issues/{index}).
|
||||
func (c *GiteaClient) GetIssue(repoPath string, number int) (Issue, error) {
|
||||
var issue Issue
|
||||
err := c.do(http.MethodGet, fmt.Sprintf("/api/v1/repos/%s/issues/%d", repoPath, number), nil, &issue)
|
||||
return issue, err
|
||||
}
|
||||
|
||||
// SetIssueState closes or reopens an issue. It reads the issue first so an
|
||||
// issue already in the requested state fails with ErrIssueStateUnchanged
|
||||
// instead of reporting a change that never happened.
|
||||
func (c *GiteaClient) SetIssueState(repoPath string, number int, state string) (Issue, error) {
|
||||
if state != IssueStateOpen && state != IssueStateClosed {
|
||||
return Issue{}, fmt.Errorf("invalid issue state %q: want %q or %q", state, IssueStateOpen, IssueStateClosed)
|
||||
}
|
||||
current, err := c.GetIssue(repoPath, number)
|
||||
if err != nil {
|
||||
return Issue{}, err
|
||||
}
|
||||
if current.State == state {
|
||||
return current, fmt.Errorf("%s#%d: %w (%s)", repoPath, number, ErrIssueStateUnchanged, state)
|
||||
}
|
||||
var issue Issue
|
||||
payload := map[string]string{"state": state}
|
||||
err = c.do(http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/issues/%d", repoPath, number), payload, &issue)
|
||||
return issue, err
|
||||
}
|
||||
|
||||
// Comment is the subset of an issue comment we track.
|
||||
type Comment struct {
|
||||
ID int64 `json:"id"`
|
||||
|
||||
Reference in New Issue
Block a user