diff --git a/README.md b/README.md index c421d3c..6d50d40 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,9 @@ fgj issue comment 456 -b "My comment" # Close an issue fgj issue close 456 + +# Close an issue with a comment +fgj issue close 456 -c "Fixed in v2.0" ``` ### Repositories diff --git a/cmd/issue.go b/cmd/issue.go index 4caf5bf..5537105 100644 --- a/cmd/issue.go +++ b/cmd/issue.go @@ -87,6 +87,7 @@ func init() { issueCommentCmd.Flags().StringP("body", "b", "", "Comment body") issueCloseCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format") + issueCloseCmd.Flags().StringP("comment", "c", "", "Comment body to add before closing") issueEditCmd.Flags().StringP("repo", "R", "", "Repository in owner/name format") issueEditCmd.Flags().StringP("title", "t", "", "New title for the issue") @@ -281,6 +282,7 @@ func runIssueComment(cmd *cobra.Command, args []string) error { func runIssueClose(cmd *cobra.Command, args []string) error { repo, _ := cmd.Flags().GetString("repo") + commentBody, _ := cmd.Flags().GetString("comment") issueNumber, err := strconv.ParseInt(args[0], 10, 64) if err != nil { return fmt.Errorf("invalid issue number: %w", err) @@ -301,6 +303,15 @@ func runIssueClose(cmd *cobra.Command, args []string) error { return err } + if commentBody != "" { + _, _, err = client.CreateIssueComment(owner, name, issueNumber, gitea.CreateIssueCommentOption{ + Body: commentBody, + }) + if err != nil { + return fmt.Errorf("failed to create comment: %w", err) + } + } + stateClosed := gitea.StateClosed _, _, err = client.EditIssue(owner, name, issueNumber, gitea.EditIssueOption{ State: &stateClosed, diff --git a/tests/functional/functional_test.go b/tests/functional/functional_test.go index 7fed7a1..6dee28b 100644 --- a/tests/functional/functional_test.go +++ b/tests/functional/functional_test.go @@ -304,6 +304,66 @@ func TestCLIIssueClose(t *testing.T) { t.Logf("Successfully tested issue close via API for CLI #%d", issueNum) } +// TestCLIIssueCloseWithComment verifies the `fgj issue close -c` command works +func TestCLIIssueCloseWithComment(t *testing.T) { + env := NewTestEnv(t) + + // Create an issue via API + issueNum := env.CreateTestIssue( + "[FGJ CLI Test] Close with comment", + "This issue will be closed with a comment in one command", + ) + + commentText := "Fixed in v2.0 - closing via functional test" + + // Close with comment via CLI + result := env.RunCLI( + "--hostname", env.Hostname, + "issue", "close", + fmt.Sprintf("%d", issueNum), + "-c", commentText, + ) + + if result.ExitCode != 0 { + t.Fatalf("issue close -c failed with exit code %d: %s", result.ExitCode, result.Stderr) + } + + // Verify the issue was closed + issue, _, err := env.Client.GetIssue(env.Owner, env.RepoName, issueNum) + if err != nil { + t.Fatalf("failed to get issue: %v", err) + } + + if issue.State != "closed" { + t.Fatalf("expected issue state 'closed', got '%s'", issue.State) + } + + // Verify the comment was added + comments, _, err := env.Client.ListIssueComments(env.Owner, env.RepoName, issueNum, gitea.ListIssueCommentOptions{}) + if err != nil { + t.Fatalf("failed to list issue comments: %v", err) + } + + if len(comments) == 0 { + t.Fatalf("expected at least one comment, got none") + } + + // Find our comment + found := false + for _, comment := range comments { + if comment.Body == commentText { + found = true + break + } + } + + if !found { + t.Fatalf("comment '%s' not found in issue comments", commentText) + } + + t.Logf("Successfully tested issue close with comment via CLI #%d", issueNum) +} + // TestEditIssueTitle verifies we can edit an issue's title func TestEditIssueTitle(t *testing.T) { env := NewTestEnv(t)