Repository: cli/cli (go)

Issue:
gh pr comment --edit-last now creates if no previous comment
### Describe the bug

Prior to [https://github.com/cli/cli/pull/10427](https://github.com/cli/cli/pull/10427), --edit-last didn't comment if there wasn't a previous comment. That seems to have changed with this, and now it creates (by default) if no comment. 

This means we can no longer use it or expect it to fail if there's no previous comment, which is breaking many of our flows from github actions - it's commenting when we wouldn't expect

At least in 26.8.1

### Affected version

`
gh version 2.68.1 (2025-03-06)
https://github.com/cli/cli/releases/tag/v2.68.1
`

### Steps to reproduce the behavior

1. create a PR
2. type this: `gh pr comment PR_ID_OR_URL --edit-last --body "test from gh pr"
3. See comment is added

Try again with a previous gh version, it doesn't do this (as per the recommendation here for why it's asking for a different feature for this: [https://github.com/cli/cli/issues/6790](https://github.com/cli/cli/issues/6790)

### Expected vs actual behavior

--edit-last behaviour shouldn't have changed, or else we need a flag to not have it create a comment

CC: @latzskim and @BagToad as the mergers of that PR. Sorry for the ping; if there's an alternate workaround to get back old behavior, let us know.


Pull request:
Editing last comment on issue or pull request only creates comment if --create-if-none flag is set
Fixes #10580

On top of fixing the underlying bug with creating new comments by default if editing issue or pull requests without comments, the following changes focus heavily on testing along.

## Manual acceptance test results

Using the following script, all new acceptance tests pass:

```shell
$ bash test.sh
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                       TEST                       │             PACKAGE               │
│─────────┼─────────┼──────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    9.02 │ TestIssues/issue-comment-edit-last-with-comments │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestIssues                                       │ github.com/cli/cli/v2/acceptance  │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  9.54s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                            TEST                             │             PACKAGE               │
│─────────┼─────────┼─────────────────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    6.17 │ TestIssues/issue-comment-edit-last-without-comments-creates │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestIssues                                                  │ github.com/cli/cli/v2/acceptance  │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  6.68s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                            TEST                            │             PACKAGE               │
│─────────┼─────────┼────────────────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    4.45 │ TestIssues/issue-comment-edit-last-without-comments-errors │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestIssues                                                 │ github.com/cli/cli/v2/acceptance  │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  4.96s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             TEST             │             PACKAGE               │
│─────────┼─────────┼──────────────────────────────┼───────────────────────────────────│
│  PASS   │    6.04 │ TestIssues/issue-comment-new │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestIssues                   │ github.com/cli/cli/v2/acceptance  │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  6.54s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                        TEST                         │             PACKAGE               │
│─────────┼─────────┼─────────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    9.63 │ TestPullRequests/pr-comment-edit-last-with-comments │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestPullRequests                                    │ github.com/cli/cli/v2/acceptance  │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │ 10.15s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                              TEST                              │             PACKAGE               │
│─────────┼─────────┼────────────────────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    8.43 │ TestPullRequests/pr-comment-edit-last-without-comments-creates │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestPullRequests                                               │ github.com/cli/cli/v2/acceptance  │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  8.99s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │              TEST               │             PACKAGE               │
│─────────┼─────────┼─────────────────────────────────┼───────────────────────────────────│
│  PASS   │    7.78 │ TestPullRequests/pr-comment-new │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestPullRequests                │ github.com/cli/cli/v2/acceptance  │
└─────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  8.34s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │                             TEST                              │             PACKAGE               │
│─────────┼─────────┼───────────────────────────────────────────────────────────────┼───────────────────────────────────│
│  PASS   │    6.22 │ TestPullRequests/pr-comment-edit-last-without-comments-errors │ github.com/cli/cli/v2/acceptance  │
│  PASS   │    0.00 │ TestPullRequests                                              │ github.com/cli/cli/v2/acceptance  │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────────┐
│  STATUS │ ELAPSED │             PACKAGE              │ COVER │ PASS │ FAIL │ SKIP  │
│─────────┼─────────┼──────────────────────────────────┼───────┼──────┼──────┼───────│
│  PASS   │  6.74s  │ github.com/cli/cli/v2/acceptance │  --   │  2   │  0   │  0    │
└────────────────────────────────────────────────────────────────────────────────────┘
```

<details>
<summary>
  <b>Shell script for running acceptance tests</b>
</summary>
<p>

```shell
#! /usr/bin/env bash

export GH_ACCEPTANCE_TOKEN=$(gh auth token --hostname github.com)
export GH_ACCEPTANCE_HOST=github.com
export GH_ACCEPTANCE_ORG=gh-acceptance-testing

set -o pipefail && GH_ACCEPTANCE_SCRIPT=issue-comment-edit-last-with-comments.txtar            go test -tags acceptance -json -run ^TestIssues$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=issue-comment-edit-last-without-comments-creates.txtar go test -tags acceptance -json -run ^TestIssues$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=issue-comment-edit-last-without-comments-errors.txtar  go test -tags acceptance -json -run ^TestIssues$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=issue-comment-new.txtar                                go test -tags acceptance -json -run ^TestIssues$ github.com/cli/cli/v2/acceptance  | tparse --all go test

set -o pipefail && GH_ACCEPTANCE_SCRIPT=pr-comment-edit-last-with-comments.txtar               go test -tags acceptance -json -run ^TestPullRequests$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=pr-comment-edit-last-without-comments-creates.txtar    go test -tags acceptance -json -run ^TestPullRequests$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=pr-comment-new.txtar                                   go test -tags acceptance -json -run ^TestPullRequests$ github.com/cli/cli/v2/acceptance  | tparse --all go test
set -o pipefail && GH_ACCEPTANCE_SCRIPT=pr-comment-edit-last-without-comments-errors.txtar     go test -tags acceptance -json -run ^TestPullRequests$ github.com/cli/cli/v2/acceptance  | tparse --all go test
```

</p>
</details> 


Patch:
diff --git a/pkg/cmd/pr/shared/commentable.go b/pkg/cmd/pr/shared/commentable.go
index 46e3072e2..f909c7559 100644
--- a/pkg/cmd/pr/shared/commentable.go
+++ b/pkg/cmd/pr/shared/commentable.go
@@ -92,26 +92,37 @@ func CommentableRun(opts *CommentableOptions) error {
 		return err
 	}
 	opts.Host = repo.RepoHost()
-	if opts.EditLast {
-		err := updateComment(commentable, opts)
-		if !errors.Is(err, errNoUserComments) {
+
+	// Create new comment, bail before complexities of updating the last comment
+	if !opts.EditLast {
+		return createComment(commentable, opts)
+	}
+
+	// Update the last comment, handling success or unexpected errors accordingly
+	err = updateComment(commentable, opts)
+	if err == nil {
+		return nil
+	}
+	if !errors.Is(err, errNoUserComments) {
+		return err
+	}
+
+	// Determine whether to create new comment, prompt user if interactive and missing option
+	if !opts.CreateIfNone && opts.Interactive {
+		opts.CreateIfNone, err = opts.ConfirmCreateIfNoneSurvey()
+		if err != nil {
 			return err
 		}
+	}
+	if !opts.CreateIfNone {
+		return errNoUserComments
+	}
 
-		if opts.Interactive {
-			if opts.CreateIfNone {
-				fmt.Fprintln(opts.IO.ErrOut, "No comments found. Creating a new comment.")
-			} else {
-				ok, err := opts.ConfirmCreateIfNoneSurvey()
-				if err != nil {
-					return err
-				}
-				if !ok {
-					return errNoUserComments
-				}
-			}
-		}
+	// Create new comment because updating the last comment failed due to no user comments
+	if opts.Interactive {
+		fmt.Fprintln(opts.IO.ErrOut, "No comments found. Creating a new comment.")
 	}
+
 	return createComment(commentable, opts)
 }
 


Test patch:
diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go
index b22929ed5..b8eff8389 100644
--- a/acceptance/acceptance_test.go
+++ b/acceptance/acceptance_test.go
@@ -69,7 +69,7 @@ func TestIssues(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	testscript.Run(t, testScriptParamsFor(tsEnv, "pr"))
+	testscript.Run(t, testScriptParamsFor(tsEnv, "issue"))
 }
 
 func TestLabels(t *testing.T) {
diff --git a/acceptance/testdata/issue/issue-comment-edit-last-with-comments.txtar b/acceptance/testdata/issue/issue-comment-edit-last-with-comments.txtar
new file mode 100644
index 000000000..a30286ce3
--- /dev/null
+++ b/acceptance/testdata/issue/issue-comment-edit-last-with-comments.txtar
@@ -0,0 +1,31 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Create an issue in the repo
+cd ${REPO}
+exec gh issue create --title 'Feature Request' --body 'Feature Body'
+stdout2env ISSUE_URL
+
+# Comment on the issue
+exec gh issue comment ${ISSUE_URL} --body 'Looks like a great feature!'
+
+# View the issue
+exec gh issue view ${ISSUE_URL} --comments
+stdout 'Looks like a great feature!'
+
+# Edit the last comment
+exec gh issue comment ${ISSUE_URL} --edit-last --body 'Looks like an amazing feature!'
+
+# View the issue
+exec gh issue view ${ISSUE_URL} --comments
+! stdout 'Looks like a great feature!'
+stdout 'Looks like an amazing feature!'
diff --git a/acceptance/testdata/issue/issue-comment-edit-last-without-comments-creates.txtar b/acceptance/testdata/issue/issue-comment-edit-last-without-comments-creates.txtar
new file mode 100644
index 000000000..44532680b
--- /dev/null
+++ b/acceptance/testdata/issue/issue-comment-edit-last-without-comments-creates.txtar
@@ -0,0 +1,23 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Create an issue in the repo
+cd ${REPO}
+exec gh issue create --title 'Feature Request' --body 'Feature Body'
+stdout2env ISSUE_URL
+
+# Comment on the issue
+exec gh issue comment ${ISSUE_URL} --edit-last --create-if-none --body 'Looks like a great feature!'
+
+# View the issue
+exec gh issue view ${ISSUE_URL} --comments
+stdout 'Looks like a great feature!'
diff --git a/acceptance/testdata/issue/issue-comment-edit-last-without-comments-errors.txtar b/acceptance/testdata/issue/issue-comment-edit-last-without-comments-errors.txtar
new file mode 100644
index 000000000..300131180
--- /dev/null
+++ b/acceptance/testdata/issue/issue-comment-edit-last-without-comments-errors.txtar
@@ -0,0 +1,20 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Create an issue in the repo
+cd ${REPO}
+exec gh issue create --title 'Feature Request' --body 'Feature Body'
+stdout2env ISSUE_URL
+
+# Comment on the issue
+! exec gh issue comment ${ISSUE_URL} --edit-last --body 'Looks like a great feature!'
+stderr 'no comments found for current user'
diff --git a/acceptance/testdata/issue/issue-comment-new.txtar b/acceptance/testdata/issue/issue-comment-new.txtar
new file mode 100644
index 000000000..12524b6d5
--- /dev/null
+++ b/acceptance/testdata/issue/issue-comment-new.txtar
@@ -0,0 +1,23 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Create an issue in the repo
+cd ${REPO}
+exec gh issue create --title 'Feature Request' --body 'Feature Body'
+stdout2env ISSUE_URL
+
+# Comment on the issue
+exec gh issue comment ${ISSUE_URL} --body 'Looks like a great feature!'
+
+# View the issue
+exec gh issue view ${ISSUE_URL} --comments
+stdout 'Looks like a great feature!'
diff --git a/acceptance/testdata/issue/issue-comment.txtar b/acceptance/testdata/issue/issue-comment.txtar
deleted file mode 100644
index f47bf619c..000000000
--- a/acceptance/testdata/issue/issue-comment.txtar
+++ /dev/null
@@ -1,20 +0,0 @@
-# Create a repository with a file so it has a default branch
-exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private
-
-# Defer repo cleanup
-defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING
-
-# Clone the repo
-exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING
-
-# Create an issue in the repo
-cd $SCRIPT_NAME-$RANDOM_STRING
-exec gh issue create --title 'Feature Request' --body 'Feature Body'
-stdout2env ISSUE_URL
-
-# Comment on the issue
-exec gh issue comment $ISSUE_URL --body 'Looks like a great feature!'
-
-# View the issue
-exec gh issue view $ISSUE_URL --comments
-stdout 'Looks like a great feature!'
diff --git a/acceptance/testdata/pr/pr-comment-edit-last-with-comments.txtar b/acceptance/testdata/pr/pr-comment-edit-last-with-comments.txtar
new file mode 100644
index 000000000..be4650ffa
--- /dev/null
+++ b/acceptance/testdata/pr/pr-comment-edit-last-with-comments.txtar
@@ -0,0 +1,40 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Use gh as a credential helper
+exec gh auth setup-git
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Prepare a branch to PR
+cd ${REPO}
+exec git checkout -b feature-branch
+exec git commit --allow-empty -m 'Empty Commit'
+exec git push -u origin feature-branch
+
+
+# Create the PR
+exec gh pr create --title 'Feature Title' --body 'Feature Body'
+stdout2env PR_URL
+
+# Comment on the PR
+exec gh pr comment ${PR_URL} --body 'Looks like a great feature!'
+
+# View the PR
+exec gh pr view ${PR_URL} --comments
+stdout 'Looks like a great feature!'
+
+# Edit the last comment
+exec gh pr comment ${PR_URL} --edit-last --body 'Looks like an amazing feature!'
+
+# View the PR
+exec gh pr view ${PR_URL} --comments
+! stdout 'Looks like a great feature!'
+stdout 'Looks like an amazing feature!'
diff --git a/acceptance/testdata/pr/pr-comment-edit-last-without-comments-creates.txtar b/acceptance/testdata/pr/pr-comment-edit-last-without-comments-creates.txtar
new file mode 100644
index 000000000..e6205737f
--- /dev/null
+++ b/acceptance/testdata/pr/pr-comment-edit-last-without-comments-creates.txtar
@@ -0,0 +1,32 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Use gh as a credential helper
+exec gh auth setup-git
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Prepare a branch to PR
+cd ${REPO}
+exec git checkout -b feature-branch
+exec git commit --allow-empty -m 'Empty Commit'
+exec git push -u origin feature-branch
+
+
+# Create the PR
+exec gh pr create --title 'Feature Title' --body 'Feature Body'
+stdout2env PR_URL
+
+# Comment on the PR
+exec gh pr comment ${PR_URL} --edit-last --create-if-none --body 'Looks like a great feature!'
+
+# View the PR
+exec gh pr view ${PR_URL} --comments
+stdout 'Looks like a great feature!'
diff --git a/acceptance/testdata/pr/pr-comment-edit-last-without-comments-errors.txtar b/acceptance/testdata/pr/pr-comment-edit-last-without-comments-errors.txtar
new file mode 100644
index 000000000..3a70adb72
--- /dev/null
+++ b/acceptance/testdata/pr/pr-comment-edit-last-without-comments-errors.txtar
@@ -0,0 +1,29 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
+# Use gh as a credential helper
+exec gh auth setup-git
+
+# Create a repository with a file so it has a default branch
+exec gh repo create ${ORG}/${REPO} --add-readme --private
+
+# Defer repo cleanup
+defer gh repo delete --yes ${ORG}/${REPO}
+
+# Clone the repo
+exec gh repo clone ${ORG}/${REPO}
+
+# Prepare a branch to PR
+cd ${REPO}
+exec git checkout -b feature-branch
+exec git commit --allow-empty -m 'Empty Commit'
+exec git push -u origin feature-branch
+
+
+# Create the PR
+exec gh pr create --title 'Feature Title' --body 'Feature Body'
+stdout2env PR_URL
+
+# Comment on the PR
+! exec gh pr comment ${PR_URL} --edit-last --body 'Looks like a great feature!'
+stderr 'no comments found for current user'
diff --git a/acceptance/testdata/pr/pr-comment.txtar b/acceptance/testdata/pr/pr-comment-new.txtar
similarity index 58%
rename from acceptance/testdata/pr/pr-comment.txtar
rename to acceptance/testdata/pr/pr-comment-new.txtar
index 2c4d488b5..c5b80314c 100644
--- a/acceptance/testdata/pr/pr-comment.txtar
+++ b/acceptance/testdata/pr/pr-comment-new.txtar
@@ -1,17 +1,20 @@
+# Setup environment variables used for testscript
+env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
+
 # Use gh as a credential helper
 exec gh auth setup-git
 
 # Create a repository with a file so it has a default branch
-exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private
+exec gh repo create ${ORG}/${REPO} --add-readme --private
 
 # Defer repo cleanup
-defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING
+defer gh repo delete --yes ${ORG}/${REPO}
 
 # Clone the repo
-exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING
+exec gh repo clone ${ORG}/${REPO}
 
 # Prepare a branch to PR
-cd $SCRIPT_NAME-$RANDOM_STRING
+cd ${REPO}
 exec git checkout -b feature-branch
 exec git commit --allow-empty -m 'Empty Commit'
 exec git push -u origin feature-branch
@@ -21,8 +24,8 @@ exec gh pr create --title 'Feature Title' --body 'Feature Body'
 stdout2env PR_URL
 
 # Comment on the PR
-exec gh pr comment $PR_URL --body 'Looks like a great feature!'
+exec gh pr comment ${PR_URL} --body 'Looks like a great feature!'
 
 # View the PR
-exec gh pr view $PR_URL --comments
+exec gh pr view ${PR_URL} --comments
 stdout 'Looks like a great feature!'
diff --git a/pkg/cmd/issue/comment/comment_test.go b/pkg/cmd/issue/comment/comment_test.go
index 461ae1065..794dafda4 100644
--- a/pkg/cmd/issue/comment/comment_test.go
+++ b/pkg/cmd/issue/comment/comment_test.go
@@ -223,9 +223,10 @@ func Test_commentRun(t *testing.T) {
 		httpStubs     func(*testing.T, *httpmock.Registry)
 		stdout        string
 		stderr        string
+		wantsErr      bool
 	}{
 		{
-			name: "interactive editor",
+			name: "creating new comment with interactive editor succeeds",
 			input: &shared.CommentableOptions{
 				Interactive: true,
 				InputType:   0,
@@ -234,13 +235,29 @@ func Test_commentRun(t *testing.T) {
 				InteractiveEditSurvey: func(string) (string, error) { return "comment body", nil },
 				ConfirmSubmitSurvey:   func() (bool, error) { return true, nil },
 			},
+			emptyComments: true,
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentCreate(t, reg)
 			},
 			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 		{
-			name: "interactive editor with edit last",
+			name: "updating last comment with interactive editor fails if there are no comments and decline prompt to create",
+			input: &shared.CommentableOptions{
+				Interactive: true,
+				InputType:   0,
+				Body:        "",
+				EditLast:    true,
+
+				InteractiveEditSurvey:     func(string) (string, error) { return "comment body", nil },
+				ConfirmSubmitSurvey:       func() (bool, error) { return true, nil },
+				ConfirmCreateIfNoneSurvey: func() (bool, error) { return false, nil },
+			},
+			emptyComments: true,
+			wantsErr:      true,
+		},
+		{
+			name: "updating last comment with interactive editor succeeds if there are comments",
 			input: &shared.CommentableOptions{
 				Interactive: true,
 				InputType:   0,
@@ -253,10 +270,11 @@ func Test_commentRun(t *testing.T) {
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentUpdate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
+			emptyComments: false,
+			stdout:        "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
 		},
 		{
-			name: "interactive editor with edit last and create if none",
+			name: "updating last comment with interactive editor creates new comment if there are no comments but --create-if-none",
 			input: &shared.CommentableOptions{
 				Interactive:  true,
 				InputType:    0,
@@ -269,12 +287,14 @@ func Test_commentRun(t *testing.T) {
 				ConfirmSubmitSurvey:       func() (bool, error) { return true, nil },
 			},
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
-				mockCommentUpdate(t, reg)
+				mockCommentCreate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
+			emptyComments: true,
+			stderr:        "No comments found. Creating a new comment.\n",
+			stdout:        "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive web",
+			name: "creating new comment with non-interactive web opens issue in browser focusing on new comment",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeWeb,
@@ -282,55 +302,38 @@ func Test_commentRun(t *testing.T) {
 
 				OpenInBrowser: func(string) error { return nil },
 			},
-			stderr: "Opening https://github.com/OWNER/REPO/issues/123 in your browser.\n",
+			emptyComments: true,
+			stderr:        "Opening https://github.com/OWNER/REPO/issues/123 in your browser.\n",
 		},
 		{
-			name: "non-interactive web with edit last",
+			name: "updating last comment with non-interactive web opens issue in browser focusing on the last comment",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeWeb,
 				Body:        "",
 				EditLast:    true,
 
-				OpenInBrowser: func(string) error { return nil },
-			},
-			stderr: "Opening https://github.com/OWNER/REPO/issues/123 in your browser.\n",
-		},
-		{
-			name: "non-interactive web with edit last and create if none for empty comments",
-			input: &shared.CommentableOptions{
-				Interactive:  false,
-				InputType:    shared.InputTypeWeb,
-				Body:         "",
-				EditLast:     true,
-				CreateIfNone: true,
-
 				OpenInBrowser: func(u string) error {
-					assert.Contains(t, u, "#issuecomment-new")
+					assert.Contains(t, u, "#issuecomment-111")
 					return nil
 				},
 			},
-			emptyComments: true,
+			emptyComments: false,
 			stderr:        "Opening https://github.com/OWNER/REPO/issues/123 in your browser.\n",
 		},
 		{
-			name: "non-interactive web with edit last and create if none",
+			name: "updating last comment with non-interactive web errors because there are no comments",
 			input: &shared.CommentableOptions{
-				Interactive:  false,
-				InputType:    shared.InputTypeWeb,
-				Body:         "",
-				EditLast:     true,
-				CreateIfNone: true,
-
-				OpenInBrowser: func(u string) error {
-					assert.Contains(t, u, "#issuecomment-111")
-					return nil
-				},
+				Interactive: false,
+				InputType:   shared.InputTypeWeb,
+				Body:        "",
+				EditLast:    true,
 			},
-			stderr: "Opening https://github.com/OWNER/REPO/issues/123 in your browser.\n",
+			emptyComments: true,
+			wantsErr:      true,
 		},
 		{
-			name: "non-interactive editor",
+			name: "creating new comment with non-interactive editor succeeds",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeEditor,
@@ -344,7 +347,20 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive editor with edit last",
+			name: "updating last comment with non-interactive editor fails if there are no comments",
+			input: &shared.CommentableOptions{
+				Interactive: false,
+				InputType:   shared.InputTypeEditor,
+				Body:        "",
+				EditLast:    true,
+
+				EditSurvey: func(string) (string, error) { return "comment body", nil },
+			},
+			emptyComments: true,
+			wantsErr:      true,
+		},
+		{
+			name: "updating last comment with non-interactive editor succeeds if there are comments",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeEditor,
@@ -356,10 +372,11 @@ func Test_commentRun(t *testing.T) {
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentUpdate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
+			emptyComments: false,
+			stdout:        "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
 		},
 		{
-			name: "non-interactive editor with edit last and create if none",
+			name: "updating last comment with non-interactive editor creates new comment if there are no comments but --create-if-none",
 			input: &shared.CommentableOptions{
 				Interactive:  false,
 				InputType:    shared.InputTypeEditor,
@@ -376,7 +393,7 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive inline",
+			name: "creating new comment with non-interactive inline succeeds if comment body is provided",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeInline,
@@ -388,7 +405,7 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive inline with edit last",
+			name: "updating last comment with non-interactive inline succeeds if there are comments and comment body is provided",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeInline,
@@ -398,7 +415,23 @@ func Test_commentRun(t *testing.T) {
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentUpdate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
+			emptyComments: false,
+			stdout:        "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
+		},
+		{
+			name: "updating last comment with non-interactive inline creates new comment if there are no comments but --create-if-none",
+			input: &shared.CommentableOptions{
+				Interactive:  false,
+				InputType:    shared.InputTypeInline,
+				Body:         "comment body",
+				EditLast:     true,
+				CreateIfNone: true,
+			},
+			emptyComments: true,
+			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
+				mockCommentCreate(t, reg)
+			},
+			stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
 		},
 	}
 	for _, tt := range tests {
@@ -437,6 +470,10 @@ func Test_commentRun(t *testing.T) {
 
 		t.Run(tt.name, func(t *testing.T) {
 			err := shared.CommentableRun(tt.input)
+			if tt.wantsErr {
+				assert.Error(t, err)
+				return
+			}
 			assert.NoError(t, err)
 			assert.Equal(t, tt.stdout, stdout.String())
 			assert.Equal(t, tt.stderr, stderr.String())
diff --git a/pkg/cmd/pr/comment/comment_test.go b/pkg/cmd/pr/comment/comment_test.go
index a6cc36abf..0941f2533 100644
--- a/pkg/cmd/pr/comment/comment_test.go
+++ b/pkg/cmd/pr/comment/comment_test.go
@@ -243,9 +243,10 @@ func Test_commentRun(t *testing.T) {
 		httpStubs     func(*testing.T, *httpmock.Registry)
 		stdout        string
 		stderr        string
+		wantsErr      bool
 	}{
 		{
-			name: "interactive editor",
+			name: "creating new comment with interactive editor succeeds",
 			input: &shared.CommentableOptions{
 				Interactive: true,
 				InputType:   0,
@@ -260,7 +261,22 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 		{
-			name: "interactive editor with edit last",
+			name: "updating last comment with interactive editor fails if there are no comments and decline prompt to create",
+			input: &shared.CommentableOptions{
+				Interactive: true,
+				InputType:   0,
+				Body:        "",
+				EditLast:    true,
+
+				InteractiveEditSurvey:     func(string) (string, error) { return "comment body", nil },
+				ConfirmSubmitSurvey:       func() (bool, error) { return true, nil },
+				ConfirmCreateIfNoneSurvey: func() (bool, error) { return false, nil },
+			},
+			emptyComments: true,
+			wantsErr:      true,
+		},
+		{
+			name: "updating last comment with interactive editor succeeds if there are comments",
 			input: &shared.CommentableOptions{
 				Interactive: true,
 				InputType:   0,
@@ -273,10 +289,11 @@ func Test_commentRun(t *testing.T) {
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentUpdate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
+			emptyComments: false,
+			stdout:        "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
 		},
 		{
-			name: "interactive editor with edit last and create if none",
+			name: "updating last comment with interactive editor creates new comment if there are no comments but --create-if-none",
 			input: &shared.CommentableOptions{
 				Interactive:  true,
 				InputType:    0,
@@ -289,12 +306,14 @@ func Test_commentRun(t *testing.T) {
 				ConfirmSubmitSurvey:       func() (bool, error) { return true, nil },
 			},
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
-				mockCommentUpdate(t, reg)
+				mockCommentCreate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
+			emptyComments: true,
+			stderr:        "No comments found. Creating a new comment.\n",
+			stdout:        "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive web",
+			name: "creating new comment with non-interactive web opens pull request in browser focusing on new comment",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeWeb,
@@ -302,10 +321,11 @@ func Test_commentRun(t *testing.T) {
 
 				OpenInBrowser: func(string) error { return nil },
 			},
-			stderr: "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
+			emptyComments: true,
+			stderr:        "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
 		},
 		{
-			name: "non-interactive web with edit last",
+			name: "updating last comment with non-interactive web opens pull request in browser focusing on the last comment",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeWeb,
@@ -317,57 +337,49 @@ func Test_commentRun(t *testing.T) {
 					return nil
 				},
 			},
-			stderr: "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
+			emptyComments: false,
+			stderr:        "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
 		},
 		{
-			name: "non-interactive web with edit last and create if none for empty comments",
+			name: "updating last comment with non-interactive web errors because there are no comments",
 			input: &shared.CommentableOptions{
-				Interactive:  false,
-				InputType:    shared.InputTypeWeb,
-				Body:         "",
-				EditLast:     true,
-				CreateIfNone: true,
-
-				OpenInBrowser: func(u string) error {
-					assert.Contains(t, u, "#issuecomment-new")
-					return nil
-				},
+				Interactive: false,
+				InputType:   shared.InputTypeWeb,
+				Body:        "",
+				EditLast:    true,
 			},
 			emptyComments: true,
-			stderr:        "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
+			wantsErr:      true,
 		},
 		{
-			name: "non-interactive web with edit last and create if none",
+			name: "creating new comment with non-interactive editor succeeds",
 			input: &shared.CommentableOptions{
-				Interactive:  false,
-				InputType:    shared.InputTypeWeb,
-				Body:         "",
-				EditLast:     true,
-				CreateIfNone: true,
+				Interactive: false,
+				InputType:   shared.InputTypeEditor,
+				Body:        "",
 
-				OpenInBrowser: func(u string) error {
-					assert.Contains(t, u, "#issuecomment-111")
-					return nil
-				},
+				EditSurvey: func(string) (string, error) { return "comment body", nil },
 			},
-			stderr: "Opening https://github.com/OWNER/REPO/pull/123 in your browser.\n",
+			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
+				mockCommentCreate(t, reg)
+			},
+			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive editor",
+			name: "updating last comment with non-interactive editor fails if there are no comments",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeEditor,
 				Body:        "",
+				EditLast:    true,
 
 				EditSurvey: func(string) (string, error) { return "comment body", nil },
 			},
-			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
-				mockCommentCreate(t, reg)
-			},
-			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
+			emptyComments: true,
+			wantsErr:      true,
 		},
 		{
-			name: "non-interactive editor with edit last",
+			name: "updating last comment with non-interactive editor succeeds if there are comments",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeEditor,
@@ -382,7 +394,7 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
 		},
 		{
-			name: "non-interactive editor with edit last and create if none",
+			name: "updating last comment with non-interactive editor creates new comment if there are no comments but --create-if-none",
 			input: &shared.CommentableOptions{
 				Interactive:  false,
 				InputType:    shared.InputTypeEditor,
@@ -399,7 +411,7 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive inline",
+			name: "creating new comment with non-interactive inline succeeds if comment body is provided",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeInline,
@@ -411,7 +423,7 @@ func Test_commentRun(t *testing.T) {
 			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 		{
-			name: "non-interactive inline with edit last",
+			name: "updating last comment with non-interactive inline succeeds if there are comments and comment body is provided",
 			input: &shared.CommentableOptions{
 				Interactive: false,
 				InputType:   shared.InputTypeInline,
@@ -421,7 +433,23 @@ func Test_commentRun(t *testing.T) {
 			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
 				mockCommentUpdate(t, reg)
 			},
-			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
+			emptyComments: false,
+			stdout:        "https://github.com/OWNER/REPO/pull/123#issuecomment-111\n",
+		},
+		{
+			name: "updating last comment with non-interactive inline creates new comment if there are no comments but --create-if-none",
+			input: &shared.CommentableOptions{
+				Interactive:  false,
+				InputType:    shared.InputTypeInline,
+				Body:         "comment body",
+				EditLast:     true,
+				CreateIfNone: true,
+			},
+			emptyComments: true,
+			httpStubs: func(t *testing.T, reg *httpmock.Registry) {
+				mockCommentCreate(t, reg)
+			},
+			stdout: "https://github.com/OWNER/REPO/pull/123#issuecomment-456\n",
 		},
 	}
 	for _, tt := range tests {
@@ -459,6 +487,10 @@ func Test_commentRun(t *testing.T) {
 
 		t.Run(tt.name, func(t *testing.T) {
 			err := shared.CommentableRun(tt.input)
+			if tt.wantsErr {
+				assert.Error(t, err)
+				return
+			}
 			assert.NoError(t, err)
 			assert.Equal(t, tt.stdout, stdout.String())
 			assert.Equal(t, tt.stderr, stderr.String())