From 2e12c397866e81a0a8d75211a52f75aff7c20b8e Mon Sep 17 00:00:00 2001 From: u80864958 Date: Fri, 13 Feb 2026 17:44:56 +0100 Subject: [PATCH] feat: add logs --- cmd/pierre/main.go | 33 +++++++++++--------- internal/gitadapters/bitbucket/controller.go | 12 +++++++ internal/gitadapters/gitea/adapter.go | 18 +++++++++-- internal/pierre/judge.go | 4 +++ internal/pierre/review.go | 12 +++---- 5 files changed, 56 insertions(+), 23 deletions(-) diff --git a/cmd/pierre/main.go b/cmd/pierre/main.go index 332be03..73e51e8 100644 --- a/cmd/pierre/main.go +++ b/cmd/pierre/main.go @@ -3,8 +3,10 @@ package main import ( "context" "log" + "log/slog" "os" "path/filepath" + "strings" "git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter" "git.schreifuchs.ch/schreifuchs/pierre-bot/internal/gitadapters/bitbucket" @@ -46,11 +48,7 @@ type ReviewConfig struct { } type Config struct { - // Deprecated flags (no prefix). Retained for backward compatibility. - // These will be mapped to the embedded ReviewConfig if provided. - MaxChunkSize int `help:"Deprecated: use --review-max-chunk-size"` - Guidelines []string `help:"Deprecated: use --review-guidelines" sep:","` - DisableComments bool `help:"Deprecated: use --review-disable-comments"` + LogLevel string `help:"Log verbosity: debug, info, warn, error"` // Embedding ReviewConfig with a prefix changes flag names to `--review-…`. // Existing configuration files using the old flag names will need to be updated. @@ -81,17 +79,24 @@ func main() { kong.Configuration(kongyaml.Loader, "config.yaml", defaultConfig), ) - // Backwards compatibility: map deprecated flag values (if any) to the embedded ReviewConfig. - if cfg.MaxChunkSize != 0 { - cfg.Review.MaxChunkSize = cfg.MaxChunkSize - } - if len(cfg.Guidelines) > 0 { - cfg.Review.Guidelines = cfg.Guidelines - } - if cfg.DisableComments { - cfg.Review.DisableComments = cfg.DisableComments + // Configure global slog logger based on the --log-level flag + lvl := slog.LevelInfo + switch strings.ToLower(cfg.LogLevel) { + case "debug": + lvl = slog.LevelDebug + case "info": + lvl = slog.LevelInfo + case "warn": + lvl = slog.LevelWarn + case "error": + lvl = slog.LevelError } + // Logs are sent to stderr so that stdout can be safely piped. + // The review output (fmt.Printf) stays on stdout unchanged. + logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: lvl})) + slog.SetDefault(logger) + // Auto-detect provider provider := cfg.GitProvider if provider == "" { diff --git a/internal/gitadapters/bitbucket/controller.go b/internal/gitadapters/bitbucket/controller.go index 64c3fee..6cad802 100644 --- a/internal/gitadapters/bitbucket/controller.go +++ b/internal/gitadapters/bitbucket/controller.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "strconv" "strings" @@ -13,6 +14,7 @@ import ( ) func (b *BitbucketAdapter) GetDiff(ctx context.Context, projectKey, repositorySlug string, pullRequestID int) (diff io.ReadCloser, err error) { + slog.Debug("Bitbucket GetDiff start", "project", projectKey, "repo", repositorySlug, "pr", pullRequestID) r, err := b.CreateRequest( ctx, http.MethodGet, @@ -39,6 +41,7 @@ func (b *BitbucketAdapter) GetDiff(ctx context.Context, projectKey, repositorySl } func (b *BitbucketAdapter) GetPR(ctx context.Context, projectKey, repositorySlug string, pullRequestID int) (pr PullRequest, err error) { + slog.Debug("Bitbucket GetPR start", "project", projectKey, "repo", repositorySlug, "pr", pullRequestID) r, err := b.CreateRequest( ctx, http.MethodGet, @@ -53,11 +56,17 @@ func (b *BitbucketAdapter) GetPR(ctx context.Context, projectKey, repositorySlug defer response.Body.Close() // Add this err = json.NewDecoder(response.Body).Decode(&pr) + if err != nil { + slog.Error("Bitbucket GetPR decode error", "err", err) + return + } + slog.Info("Bitbucket GetPR success", "id", pullRequestID) return } func (b *BitbucketAdapter) AddComment(ctx context.Context, owner, repo string, prID int, comment pierre.Comment) (err error) { + slog.Debug("Bitbucket AddComment start", "owner", owner, "repo", repo, "pr", prID, "file", comment.File, "line", comment.Line) // pr, err := b.GetPR(ctx, owner, repo, prID) // if err != nil { // return @@ -95,6 +104,9 @@ func (b *BitbucketAdapter) AddComment(ctx context.Context, owner, repo string, p sb := &strings.Builder{} io.Copy(sb, response.Body) err = fmt.Errorf("error while creating comment staus %d, body %s", response.StatusCode, sb.String()) + slog.Error("Bitbucket AddComment failed", "status", response.StatusCode, "err", err) + } else { + slog.Info("Bitbucket AddComment succeeded", "pr", prID) } return err diff --git a/internal/gitadapters/gitea/adapter.go b/internal/gitadapters/gitea/adapter.go index 5674de1..0c943f9 100644 --- a/internal/gitadapters/gitea/adapter.go +++ b/internal/gitadapters/gitea/adapter.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io" + "log/slog" "code.gitea.io/sdk/gitea" "git.schreifuchs.ch/schreifuchs/pierre-bot/internal/pierre" @@ -25,15 +26,19 @@ func New(baseURL, token string) (*Adapter, error) { } func (g *Adapter) GetDiff(ctx context.Context, owner, repo string, prID int) (io.ReadCloser, error) { + slog.Debug("Gitea GetDiff start", "owner", owner, "repo", repo, "pr", prID) g.client.SetContext(ctx) diff, _, err := g.client.GetPullRequestDiff(owner, repo, int64(prID), gitea.PullRequestDiffOptions{}) if err != nil { return nil, err } - return io.NopCloser(bytes.NewReader(diff)), nil + rc := io.NopCloser(bytes.NewReader(diff)) + slog.Info("Gitea GetDiff success", "owner", owner, "repo", repo, "pr", prID, "bytes", len(diff)) + return rc, nil } func (g *Adapter) AddComment(ctx context.Context, owner, repo string, prID int, comment pierre.Comment) error { + slog.Debug("Gitea AddComment start", "owner", owner, "repo", repo, "pr", prID, "file", comment.File, "line", comment.Line) g.client.SetContext(ctx) opts := gitea.CreatePullReviewOptions{ State: gitea.ReviewStateComment, @@ -46,22 +51,30 @@ func (g *Adapter) AddComment(ctx context.Context, owner, repo string, prID int, }, } _, _, err := g.client.CreatePullReview(owner, repo, int64(prID), opts) - return err + if err != nil { + slog.Error("Gitea AddComment failed", "err", err) + return err + } + slog.Info("Gitea AddComment succeeded", "pr", prID) + return nil } // GetFileContent returns the file content at a given path and ref (commit SHA). func (g *Adapter) GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error) { + slog.Debug("Gitea GetFileContent start", "owner", owner, "repo", repo, "path", path, "ref", ref) g.client.SetContext(ctx) // The SDK's GetFile returns the raw bytes of the file. data, _, err := g.client.GetFile(owner, repo, ref, path) if err != nil { return "", err } + slog.Info("Gitea GetFileContent success", "bytes", len(data)) return string(data), nil } // GetPRHeadSHA fetches the pull request and returns the head commit SHA. func (g *Adapter) GetPRHeadSHA(ctx context.Context, owner, repo string, prID int) (string, error) { + slog.Debug("Gitea GetPRHeadSHA start", "owner", owner, "repo", repo, "pr", prID) g.client.SetContext(ctx) // GetPullRequest returns the detailed PR information. pr, _, err := g.client.GetPullRequest(owner, repo, int64(prID)) @@ -71,5 +84,6 @@ func (g *Adapter) GetPRHeadSHA(ctx context.Context, owner, repo string, prID int if pr == nil || pr.Head == nil { return "", fmt.Errorf("pull request %d has no head information", prID) } + slog.Info("Gitea GetPRHeadSHA success", "sha", pr.Head.Sha) return pr.Head.Sha, nil } diff --git a/internal/pierre/judge.go b/internal/pierre/judge.go index 7ae4f77..c768100 100644 --- a/internal/pierre/judge.go +++ b/internal/pierre/judge.go @@ -1,6 +1,8 @@ package pierre import ( + "log/slog" + "context" "fmt" "io" @@ -19,6 +21,7 @@ type Comment struct { } func (s *Service) judgePR(ctx context.Context, diff io.Reader) (comments []Comment, err error) { + slog.Info("judgePR started") diffBytes, err := io.ReadAll(diff) if err != nil { return nil, fmt.Errorf("failed to read diff: %w", err) @@ -81,6 +84,7 @@ If project guidelines are provided, treat them as hard rules that must be respec for _, v := range unique { comments = append(comments, v) } + slog.Info("judgePR finished", "comments", len(comments)) return } diff --git a/internal/pierre/review.go b/internal/pierre/review.go index e243e31..06bc6bb 100644 --- a/internal/pierre/review.go +++ b/internal/pierre/review.go @@ -69,13 +69,11 @@ func (s *Service) MakeReview(ctx context.Context, organisation string, repo stri for _, c := range comments { c.Message = fmt.Sprintf("%s (Generated by: %s)", c.Message, model) - if s.disableComments { - // Dry‑run: just log what would have been posted. - log.Printf("dry‑run: %s:%d => %s", c.File, c.Line, c.Message) - } else { - // Normal mode: print to stdout and post the comment to the VCS. - fmt.Printf("File: %s\nLine: %d\nMessage: %s\n%s\n", - c.File, c.Line, c.Message, "---") + // Normal mode: print to stdout and post the comment to the VCS. + fmt.Printf("File: %s\nLine: %d\nMessage: %s\n%s\n", + c.File, c.Line, c.Message, "---") + + if !s.disableComments { if err := s.git.AddComment(ctx, organisation, repo, prID, c); err != nil { log.Printf("Failed to add comment: %v", err) }