mirror of
https://gitea.com/gitea/tea.git
synced 2026-07-16 02:57:40 +02:00
Add reply to code review (#978)
Follow https://gitea.com/gitea/go-sdk/pulls/784 Reviewed-on: https://gitea.com/gitea/tea/pulls/978
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
teagit "gitea.dev/tea/modules/git"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTeaCheckoutRemoteReferenceKeepsWorktreeClean(t *testing.T) {
|
||||
clonePath := setupGitCheckoutTestRepo(t)
|
||||
t.Chdir(clonePath)
|
||||
|
||||
repo, err := teagit.RepoFromPath(clonePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = repo.TeaCheckout(teagit.NewRemoteReferenceName("origin", "feature/test-branch"))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Empty(t, gitOutput(t, clonePath, "status", "--porcelain"))
|
||||
assert.Equal(t, "HEAD", gitOutput(t, clonePath, "rev-parse", "--abbrev-ref", "HEAD"))
|
||||
}
|
||||
|
||||
func TestTeaCreateBranchTracksRemoteBranch(t *testing.T) {
|
||||
clonePath := setupGitCheckoutTestRepo(t)
|
||||
t.Chdir(clonePath)
|
||||
|
||||
repo, err := teagit.RepoFromPath(clonePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = repo.TeaCreateBranch("pulls/123", "feature/test-branch", "origin")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = repo.TeaCheckout(teagit.NewBranchReferenceName("pulls/123"))
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Empty(t, gitOutput(t, clonePath, "status", "--porcelain"))
|
||||
assert.Equal(t, "origin", gitOutput(t, clonePath, "config", "--get", "branch.pulls/123.remote"))
|
||||
assert.Equal(t, "refs/heads/feature/test-branch", gitOutput(t, clonePath, "config", "--get", "branch.pulls/123.merge"))
|
||||
assert.Equal(t, "pulls/123", gitOutput(t, clonePath, "rev-parse", "--abbrev-ref", "HEAD"))
|
||||
}
|
||||
|
||||
func setupGitCheckoutTestRepo(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
remotePath := filepath.Join(tmpDir, "remote.git")
|
||||
seedPath := filepath.Join(tmpDir, "seed")
|
||||
clonePath := filepath.Join(tmpDir, "clone")
|
||||
|
||||
runGit(t, tmpDir, "init", "--bare", remotePath)
|
||||
runGit(t, tmpDir, "init", seedPath)
|
||||
runGit(t, seedPath, "config", "user.email", "test@example.com")
|
||||
runGit(t, seedPath, "config", "user.name", "Test User")
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join(seedPath, "README.md"), []byte("# Test Repo\n"), 0o644))
|
||||
runGit(t, seedPath, "add", "README.md")
|
||||
runGit(t, seedPath, "commit", "-m", "Initial commit")
|
||||
runGit(t, seedPath, "branch", "-M", "main")
|
||||
runGit(t, seedPath, "remote", "add", "origin", remotePath)
|
||||
runGit(t, seedPath, "push", "-u", "origin", "main")
|
||||
|
||||
runGit(t, seedPath, "checkout", "-b", "feature/test-branch")
|
||||
require.NoError(t, os.WriteFile(filepath.Join(seedPath, "feature.txt"), []byte("feature\n"), 0o644))
|
||||
runGit(t, seedPath, "add", "feature.txt")
|
||||
runGit(t, seedPath, "commit", "-m", "Add feature")
|
||||
runGit(t, seedPath, "push", "-u", "origin", "feature/test-branch")
|
||||
|
||||
runGit(t, tmpDir, "clone", remotePath, clonePath)
|
||||
return clonePath
|
||||
}
|
||||
|
||||
func runGit(t *testing.T, dir string, args ...string) {
|
||||
t.Helper()
|
||||
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
require.NoErrorf(t, err, "git %s failed: %s", strings.Join(args, " "), strings.TrimSpace(string(output)))
|
||||
}
|
||||
|
||||
func gitOutput(t *testing.T, dir string, args ...string) string {
|
||||
t.Helper()
|
||||
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
require.NoErrorf(t, err, "git %s failed: %s", strings.Join(args, " "), strings.TrimSpace(string(output)))
|
||||
return strings.TrimSpace(string(output))
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dev/tea/cmd/pulls"
|
||||
|
||||
gitea "gitea.dev/sdk"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestPullsReply(t *testing.T) {
|
||||
login := createIntegrationLogin(t)
|
||||
client := login.Client()
|
||||
timestamp := time.Now().UnixNano()
|
||||
repoName := fmt.Sprintf("tea-pr-reply-%d", timestamp)
|
||||
featureBranch := fmt.Sprintf("reply-test-%d", timestamp)
|
||||
replyBody := fmt.Sprintf("Thanks for the review %d", timestamp)
|
||||
|
||||
repo, _, err := client.Repositories.CreateRepo(t.Context(), gitea.CreateRepoOption{
|
||||
Name: repoName,
|
||||
AutoInit: true,
|
||||
DefaultBranch: "main",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
if _, delErr := client.Repositories.DeleteRepo(t.Context(), login.User, repoName); delErr != nil {
|
||||
t.Logf("failed to delete integration test repo %q: %v", repoName, delErr)
|
||||
}
|
||||
})
|
||||
|
||||
baseBranch := repo.DefaultBranch
|
||||
if baseBranch == "" {
|
||||
baseBranch = "main"
|
||||
}
|
||||
|
||||
_, _, err = client.Repositories.CreateFile(t.Context(), login.User, repoName, "review.txt", gitea.CreateFileOptions{
|
||||
FileOptions: gitea.FileOptions{
|
||||
Message: "add review target",
|
||||
BranchName: baseBranch,
|
||||
NewBranchName: featureBranch,
|
||||
},
|
||||
Content: base64.StdEncoding.EncodeToString([]byte("line for review\n")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
pr, _, err := client.PullRequests.CreatePullRequest(t.Context(), login.User, repoName, gitea.CreatePullRequestOption{
|
||||
Base: baseBranch,
|
||||
Head: featureBranch,
|
||||
Title: "Integration test for pr reply",
|
||||
Body: "Adds a file so we can reply to a review comment.",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
review, _, err := client.PullRequests.CreatePullReview(t.Context(), login.User, repoName, pr.Index, gitea.CreatePullReviewOptions{
|
||||
State: gitea.ReviewStateComment,
|
||||
Body: "Please take another look.",
|
||||
Comments: []gitea.CreatePullReviewComment{{
|
||||
Path: "review.txt",
|
||||
Body: "Could you clarify this line?",
|
||||
NewLineNum: 1,
|
||||
}},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
comments, _, err := client.PullRequests.ListPullReviewComments(t.Context(), login.User, repoName, pr.Index, review.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, comments, 1)
|
||||
|
||||
pullsCmd := &cli.Command{
|
||||
Name: "pulls",
|
||||
Commands: []*cli.Command{&pulls.CmdPullsReply},
|
||||
}
|
||||
|
||||
err = pullsCmd.Run(context.Background(), []string{
|
||||
"pulls",
|
||||
"reply",
|
||||
strconv.FormatInt(pr.Index, 10),
|
||||
strconv.FormatInt(comments[0].ID, 10),
|
||||
replyBody,
|
||||
"--login",
|
||||
login.Name,
|
||||
"--repo",
|
||||
repo.FullName,
|
||||
})
|
||||
if err != nil && strings.Contains(err.Error(), "unknown API error: 405") {
|
||||
t.Skip("pull review comment replies are not supported by this integration Gitea instance")
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
reviewComments, _, listErr := client.PullRequests.ListPullReviewComments(t.Context(), login.User, repoName, pr.Index, review.ID)
|
||||
if listErr != nil {
|
||||
t.Logf("failed to list review comments: %v", listErr)
|
||||
return false
|
||||
}
|
||||
for _, reviewComment := range reviewComments {
|
||||
if reviewComment.Body == replyBody && reviewComment.ReviewID == review.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}, 10*time.Second, 500*time.Millisecond)
|
||||
}
|
||||
Reference in New Issue
Block a user