Repository: reviewdog/reviewdog
Pull request #1903 (2024-08-25 09:30:41)

Adjust paths with GitRelWorkdir for all GitHub reporters
- [x] Updated Unreleased section in [CHANGELOG](https://github.com/reviewdog/reviewdog/blob/master/CHANGELOG.md) or it's not notable changes.

---

Currently, reviewdog adjusts result paths only with the `github-pr-review` reporter within GitHub reporters. This is required if the linting is executed inside a sub directory and the result contains path(s) relative to that directory. The following line is where the `github-pr-review` reporter adjusts the paths:
https://github.com/reviewdog/reviewdog/blob/v0.20.1/service/github/github.go#L107-L108

This PR tries to fix this by adding the same procedure for `githubservice.Check` (`github-check` and `github-pr-check`) as well as adding `githubservice.Log` that just does this adjustment. Note that adding this procedure to `githubutils.GitHubActionLogWriter` would break the fallback flow, which is why I added new `githubservice.Log` instead.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 838ec1ec..36a27854 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - [#1867](https://github.com/reviewdog/reviewdog/pull/1867) Tool name was incorrect for github-[pr-]check reporters and check API does not work correctly for project config based run
 - [#1867](https://github.com/reviewdog/reviewdog/pull/1867) Deletion of outdated comment didn't work properly with github-pr-review reporter since tool name isn't correctly configured for project config based run
 - [#1894](https://github.com/reviewdog/reviewdog/pull/1894) fix error when repository uses multiselect custom-properties [#1881](https://github.com/reviewdog/reviewdog/issues/1881)
+- [#1903](https://github.com/reviewdog/reviewdog/pull/1903) Adjust result paths for github-[pr-]check and github-pr-annotaions reporters relative to the git directory
 
 ### :rotating_light: Breaking changes
 - [#1858](https://github.com/reviewdog/reviewdog/pull/1858) Remove original_output from rdjson/rdjsonl reporters' output
diff --git a/cmd/reviewdog/main.go b/cmd/reviewdog/main.go
index 85a532bb..564e9bfc 100644
--- a/cmd/reviewdog/main.go
+++ b/cmd/reviewdog/main.go
@@ -35,7 +35,6 @@ import (
 	gerritservice "github.com/reviewdog/reviewdog/service/gerrit"
 	giteaservice "github.com/reviewdog/reviewdog/service/gitea"
 	githubservice "github.com/reviewdog/reviewdog/service/github"
-	"github.com/reviewdog/reviewdog/service/github/githubutils"
 	gitlabservice "github.com/reviewdog/reviewdog/service/gitlab"
 )
 
@@ -324,22 +323,11 @@ func run(r io.Reader, w io.Writer, opt *option) error {
 		ds = ghDiffService
 		cs = reviewdog.MultiCommentService(checkService, cs)
 	case "github-pr-annotations":
-		g, client, err := githubBuildInfoWithClient(ctx)
+		var err error
+		cs, ds, err = githubActionLogService(ctx, opt)
 		if err != nil {
 			return err
 		}
-		ds = &reviewdog.EmptyDiff{}
-		if g.PullRequest != 0 {
-			ds = &githubservice.PullRequestDiffService{
-				Cli:              client,
-				Owner:            g.Owner,
-				Repo:             g.Repo,
-				PR:               g.PullRequest,
-				SHA:              g.SHA,
-				FallBackToGitCLI: true,
-			}
-		}
-		cs = githubutils.NewGitHubActionLogWriter(opt.level)
 	case "github-pr-review":
 		gs, isPR, err := githubService(ctx, opt)
 		if err != nil {
@@ -685,15 +673,34 @@ func githubCheckService(ctx context.Context, opt *option) (reviewdog.CommentServ
 			FallBackToGitCLI: true,
 		}
 	}
-	return &githubservice.Check{
-		CLI:      client,
-		Owner:    g.Owner,
-		Repo:     g.Repo,
-		PR:       g.PullRequest,
-		SHA:      g.SHA,
-		ToolName: opt.name,
-		Level:    opt.level,
-	}, ds, nil
+	cs, err := githubservice.NewGitHubCheck(client, g.Owner, g.Repo, g.PullRequest, g.SHA, opt.level, toolName(opt))
+	if err != nil {
+		return nil, nil, err
+	}
+	return cs, ds, nil
+}
+
+func githubActionLogService(ctx context.Context, opt *option) (reviewdog.CommentService, reviewdog.DiffService, error) {
+	g, client, err := githubBuildInfoWithClient(ctx)
+	if err != nil {
+		return nil, nil, err
+	}
+	var ds reviewdog.DiffService = &reviewdog.EmptyDiff{}
+	if g.PullRequest != 0 {
+		ds = &githubservice.PullRequestDiffService{
+			Cli:              client,
+			Owner:            g.Owner,
+			Repo:             g.Repo,
+			PR:               g.PullRequest,
+			SHA:              g.SHA,
+			FallBackToGitCLI: true,
+		}
+	}
+	cs, err := githubservice.NewGitHubActionLog(opt.level)
+	if err != nil {
+		return nil, nil, err
+	}
+	return cs, ds, nil
 }
 
 func githubBuildInfoWithClient(ctx context.Context) (*cienv.BuildInfo, *github.Client, error) {
diff --git a/service/github/check.go b/service/github/check.go
index 2fac45aa..c5a72eae 100644
--- a/service/github/check.go
+++ b/service/github/check.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"net/http"
+	"path/filepath"
 	"strings"
 	"sync"
 	"time"
@@ -14,6 +15,7 @@ import (
 	"github.com/reviewdog/reviewdog/filter"
 	"github.com/reviewdog/reviewdog/proto/rdf"
 	"github.com/reviewdog/reviewdog/service/github/githubutils"
+	"github.com/reviewdog/reviewdog/service/serviceutil"
 )
 
 // GitHub check runs API cannot handle too large requests.
@@ -47,6 +49,9 @@ type Check struct {
 
 	muResult sync.Mutex
 	result   *CheckResult
+
+	// wd is working directory relative to root of repository.
+	wd string
 }
 
 // CheckResult represents result of Check.
@@ -55,8 +60,28 @@ type CheckResult struct {
 	Conclusion string
 }
 
+// NewGitHubCheck returns a new Check service.
+func NewGitHubCheck(cli *github.Client, owner, repo string, pr int, sha, level, toolName string) (*Check, error) {
+	workDir, err := serviceutil.GitRelWorkdir()
+	if err != nil {
+		return nil, err
+	}
+	return &Check{
+		CLI:      cli,
+		Owner:    owner,
+		Repo:     repo,
+		PR:       pr,
+		SHA:      sha,
+		Level:    level,
+		ToolName: toolName,
+		wd:       workDir,
+	}, nil
+}
+
 // Post posts a reviewdog comment.
 func (ch *Check) Post(_ context.Context, c *reviewdog.Comment) error {
+	c.Result.Diagnostic.GetLocation().Path = filepath.ToSlash(filepath.Join(ch.wd,
+		c.Result.Diagnostic.GetLocation().GetPath()))
 	ch.muComments.Lock()
 	defer ch.muComments.Unlock()
 	ch.postComments = append(ch.postComments, c)
diff --git a/service/github/github.go b/service/github/github.go
index 2c96964b..bc81106f 100644
--- a/service/github/github.go
+++ b/service/github/github.go
@@ -75,7 +75,6 @@ type PullRequest struct {
 }
 
 // NewGitHubPullRequest returns a new PullRequest service.
-// PullRequest service needs git command in $PATH.
 //
 // The GitHub Token generated by GitHub Actions may not have the necessary permissions.
 // For example, in the case of a PR from a forked repository, or when write permission is prohibited in the repository settings [1].
@@ -87,7 +86,7 @@ type PullRequest struct {
 func NewGitHubPullRequest(cli *github.Client, owner, repo string, pr int, sha, level, toolName string) (*PullRequest, error) {
 	workDir, err := serviceutil.GitRelWorkdir()
 	if err != nil {
-		return nil, fmt.Errorf("PullRequest needs 'git' command: %w", err)
+		return nil, err
 	}
 	return &PullRequest{
 		cli:       cli,
diff --git a/service/github/log.go b/service/github/log.go
new file mode 100644
index 00000000..1d5ad2d8
--- /dev/null
+++ b/service/github/log.go
@@ -0,0 +1,44 @@
+package github
+
+import (
+	"context"
+	"path/filepath"
+
+	"github.com/reviewdog/reviewdog"
+	"github.com/reviewdog/reviewdog/service/github/githubutils"
+	"github.com/reviewdog/reviewdog/service/serviceutil"
+)
+
+var _ reviewdog.CommentService = (*Log)(nil)
+
+// Log is a logging service for GitHub Actions.
+type Log struct {
+	logWriter *githubutils.GitHubActionLogWriter
+
+	// wd is working directory relative to root of repository.
+	wd string
+}
+
+// NewGitHubActionLog returns a new Log service.
+func NewGitHubActionLog(level string) (*Log, error) {
+	workDir, err := serviceutil.GitRelWorkdir()
+	if err != nil {
+		return nil, err
+	}
+	return &Log{
+		logWriter: githubutils.NewGitHubActionLogWriter(level),
+		wd:        workDir,
+	}, nil
+}
+
+// Post writes a log.
+func (g *Log) Post(ctx context.Context, c *reviewdog.Comment) error {
+	c.Result.Diagnostic.GetLocation().Path = filepath.ToSlash(filepath.Join(g.wd,
+		c.Result.Diagnostic.GetLocation().GetPath()))
+	return g.logWriter.Post(ctx, c)
+}
+
+// Flush checks overall error at last.
+func (g *Log) Flush(ctx context.Context) error {
+	return g.logWriter.Flush(ctx)
+}


Test patch:
diff --git a/service/github/check_test.go b/service/github/check_test.go
index 0a649189..f58854ed 100644
--- a/service/github/check_test.go
+++ b/service/github/check_test.go
@@ -6,6 +6,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"os"
 	"strings"
 	"testing"
 
@@ -29,6 +30,16 @@ func TestCheck_OK(t *testing.T) {
 		wantCheckID = 1414
 	)
 
+	cwd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Chdir(cwd)
+	err = os.Chdir("../../diff/testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+
 	comments := []*reviewdog.Comment{
 		{
 			Result: &filter.FilteredDiagnostic{
@@ -72,14 +83,9 @@ func TestCheck_OK(t *testing.T) {
 	cli := github.NewClient(nil)
 	cli.BaseURL, _ = url.Parse(ts.URL + "/")
 
-	check := &Check{
-		CLI:      cli,
-		Owner:    owner,
-		Repo:     repo,
-		PR:       prNum,
-		SHA:      sha,
-		ToolName: name,
-		Level:    level,
+	check, err := NewGitHubCheck(cli, owner, repo, prNum, sha, level, name)
+	if err != nil {
+		t.Fatal(err)
 	}
 
 	for _, c := range comments {
@@ -114,6 +120,16 @@ func TestCheck_OK_multiple_update_runs(t *testing.T) {
 		wantCheckID = 1414
 	)
 
+	cwd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Chdir(cwd)
+	err = os.Chdir("../../diff/testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+
 	mux := http.NewServeMux()
 	mux.HandleFunc("/repos/haya14busa/reviewdog/check-runs", func(w http.ResponseWriter, r *http.Request) {
 		if err := json.NewEncoder(w).Encode(&github.CheckRun{ID: github.Int64(wantCheckID)}); err != nil {
@@ -142,14 +158,9 @@ func TestCheck_OK_multiple_update_runs(t *testing.T) {
 	cli := github.NewClient(nil)
 	cli.BaseURL, _ = url.Parse(ts.URL + "/")
 
-	check := &Check{
-		CLI:      cli,
-		Owner:    owner,
-		Repo:     repo,
-		PR:       prNum,
-		SHA:      sha,
-		ToolName: name,
-		Level:    level,
+	check, err := NewGitHubCheck(cli, owner, repo, prNum, sha, level, name)
+	if err != nil {
+		t.Fatal(err)
 	}
 
 	for i := 0; i < 101; i++ {
@@ -189,6 +200,16 @@ func TestCheck_fail_check_with_403_in_GitHub_Actions(t *testing.T) {
 		level       = "warning"
 		wantCheckID = 1414
 	)
+	cwd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Chdir(cwd)
+	err = os.Chdir("../../diff/testdata")
+	if err != nil {
+		t.Fatal(err)
+	}
+
 	mux := http.NewServeMux()
 	mux.HandleFunc("/repos/haya14busa/reviewdog/check-runs", func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusForbidden)
@@ -197,14 +218,10 @@ func TestCheck_fail_check_with_403_in_GitHub_Actions(t *testing.T) {
 	defer ts.Close()
 	cli := github.NewClient(nil)
 	cli.BaseURL, _ = url.Parse(ts.URL + "/")
-	check := &Check{
-		CLI:      cli,
-		Owner:    owner,
-		Repo:     repo,
-		PR:       prNum,
-		SHA:      sha,
-		ToolName: name,
-		Level:    level,
+
+	check, err := NewGitHubCheck(cli, owner, repo, prNum, sha, level, name)
+	if err != nil {
+		t.Fatal(err)
 	}
 	if err := check.Flush(context.Background()); err != nil {
 		t.Error(err)