feat: gitea client

This commit is contained in:
2026-02-12 20:58:55 +01:00
parent 8583ab48ce
commit 9d49d94eff
13 changed files with 334 additions and 54 deletions

View File

@@ -0,0 +1,31 @@
package baseadapter
import (
"fmt"
"io"
"net/http"
"net/url"
)
type Rest struct {
baseURL string
bearerToken string
}
func (b *Rest) createRequest(method string, body io.Reader, path ...string) (r *http.Request, err error) {
target, err := url.JoinPath(b.baseURL, path...)
if err != nil {
err = fmt.Errorf("can not parse path: %w", err)
return
}
req, err := http.NewRequest(method, target, body)
if err != nil {
return nil, err
}
if b.bearerToken != "" {
req.Header.Set("Authorization", "Bearer "+b.bearerToken)
}
return req, nil
}

View File

@@ -4,6 +4,8 @@ import (
"fmt"
"io"
"net/http"
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/pierre"
)
type BitbucketAdapter struct {
@@ -36,3 +38,9 @@ func (b *BitbucketAdapter) GetDiff(projectKey, repositorySlug string, pullReques
diff = response.Body
return
}
func (b *BitbucketAdapter) AddComment(projectKey, repositorySlug string, pullRequestID int, comment pierre.Comment) error {
fmt.Printf("[MOCK BITBUCKET] Adding comment to PR %s/%s #%d: %s at %s:%d\n",
projectKey, repositorySlug, pullRequestID, comment.Message, comment.File, comment.Line)
return nil
}

View File

@@ -0,0 +1,46 @@
package gitea
import (
"bytes"
"io"
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/pierre"
"code.gitea.io/sdk/gitea"
)
type Adapter struct {
client *gitea.Client
}
func New(baseURL, token string) (*Adapter, error) {
client, err := gitea.NewClient(baseURL, gitea.SetToken(token))
if err != nil {
return nil, err
}
return &Adapter{
client: client,
}, nil
}
func (g *Adapter) GetDiff(owner, repo string, prID int) (io.Reader, error) {
diff, _, err := g.client.GetPullRequestDiff(owner, repo, int64(prID), gitea.PullRequestDiffOptions{})
if err != nil {
return nil, err
}
return bytes.NewReader(diff), nil
}
func (g *Adapter) AddComment(owner, repo string, prID int, comment pierre.Comment) error {
opts := gitea.CreatePullReviewOptions{
State: gitea.ReviewStateComment,
Comments: []gitea.CreatePullReviewComment{
{
Path: comment.File,
Body: comment.Message,
NewLineNum: int64(comment.Line),
},
},
}
_, _, err := g.client.CreatePullReview(owner, repo, int64(prID), opts)
return err
}

View File

@@ -1 +0,0 @@
package gitadapters

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"io"
"bitbucket.bit.admin.ch/scm/~u80859501/pierre-bot/internal/chatter"
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
)
type Comment struct {
@@ -14,28 +14,24 @@ type Comment struct {
Message string `json:"message"`
}
type ChatAdapter interface {
GenerateStructured(ctx context.Context, messages []chatter.Message, target interface{}) error
}
func JudgePR(ctx context.Context, chat ChatAdapter, diff io.Reader) (comments []Comment, err error) {
func (s *Service) judgePR(ctx context.Context, diff io.Reader) (comments []Comment, err error) {
diffBytes, err := io.ReadAll(diff)
if err != nil {
return nil, fmt.Errorf("failed to read diff: %w", err)
}
err = chat.GenerateStructured(ctx, []chatter.Message{
err = s.chat.GenerateStructured(ctx, []chatter.Message{
{
Role: chatter.RoleSystem,
Content: `
You are a very strict senior software architect.
You review **only** newly added or modified lines in a unified diff (lines prefixed with “+”), together with the immediate hunk context.
You review **only** newly added or modified lines in a unified diff, together with the immediate hunk context.
You do **not** report issues that appear **solely** in deleted lines (“-”) or that have already been fixed by the change.
No comments are made on pure formatting/whitespace changes or reordering that does not alter the programs behavior.
`,
},
{
Role: chatter.RoleUser,
Content: fmt.Sprintf("Hello please review my PR.\n Here is the git diff of it: %s", string(diffBytes)),
Content: fmt.Sprintf("Hello please review my PR. Write comments where improvements are necessary in new lines.\n Here is the git diff of it: %s", string(diffBytes)),
},
}, &comments)

View File

@@ -0,0 +1,29 @@
package pierre
import (
"context"
"io"
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
)
type Service struct {
git GitAdapter
chat ChatAdapter
}
func New(chat ChatAdapter, git GitAdapter) *Service {
return &Service{
git: git,
chat: chat,
}
}
type GitAdapter interface {
GetDiff(owner, repo string, prID int) (io.Reader, error)
AddComment(owner, repo string, prID int, comment Comment) error
}
type ChatAdapter interface {
GenerateStructured(ctx context.Context, messages []chatter.Message, target interface{}) error
}

34
internal/pierre/review.go Normal file
View File

@@ -0,0 +1,34 @@
package pierre
import (
"context"
"fmt"
"log"
)
func (s *Service) MakeReview(ctx context.Context, organisation string, repo string, prID int) error {
// Fetch Diff using positional args from shared RepoArgs
diff, err := s.git.GetDiff(organisation, repo, prID)
if err != nil {
return fmt.Errorf("error fetching diff: %w", err)
}
// Run Logic
comments, err := s.judgePR(ctx, diff)
if err != nil {
return fmt.Errorf("error judging PR: %w", err)
}
fmt.Printf("Analysis complete. Found %d issues.\n---\n", len(comments))
for _, c := range comments {
fmt.Printf("File: %s\nLine: %d\nMessage: %s\n%s\n",
c.File, c.Line, c.Message, "---")
if err := s.git.AddComment(organisation, repo, prID, c); err != nil {
log.Printf("Failed to add comment: %v", err)
}
}
return nil
}