diff --git a/scanner/gitlab.go b/scanner/gitlab.go index 7a4016b..ccef845 100644 --- a/scanner/gitlab.go +++ b/scanner/gitlab.go @@ -24,9 +24,9 @@ func (scanner GitLabScanner) List( ) error { log.Debugf("GitLabScanner.List(%s)", url.String()) - apiURL, _ := url.Parse("/api/v4") + apiURL := gitlabAPIURL(url) - git, err := gitlab.NewClient(os.Getenv("GITLAB_TOKEN"), gitlab.WithBaseURL(apiURL.String())) + git, err := gitlab.NewClient(os.Getenv("GITLAB_TOKEN"), gitlab.WithBaseURL(apiURL)) if err != nil { return err } @@ -80,9 +80,9 @@ func (scanner GitLabScanner) Scan( ) error { log.Debugf("GitLabScanner.Scan(%s)", url.String()) - apiURL, _ := url.Parse("/api/v4") + apiURL := gitlabAPIURL(url) - git, err := gitlab.NewClient(os.Getenv("GITLAB_TOKEN"), gitlab.WithBaseURL(apiURL.String())) + git, err := gitlab.NewClient(os.Getenv("GITLAB_TOKEN"), gitlab.WithBaseURL(apiURL)) if err != nil { return err } @@ -97,6 +97,14 @@ func (scanner GitLabScanner) Scan( return addProject(&url, *prj, publisher, repositories) } +func gitlabAPIURL(gitlabURL url.URL) string { + return (&url.URL{ + Scheme: gitlabURL.Scheme, + Host: gitlabURL.Host, + Path: "/api/v4", + }).String() +} + // isGitlabGroup returns true if the API URL points to a group. func isGitlabGroup(gitlabURL url.URL) bool { return ( diff --git a/scanner/gitlab_test.go b/scanner/gitlab_test.go index 72636d3..f7356e0 100644 --- a/scanner/gitlab_test.go +++ b/scanner/gitlab_test.go @@ -1,13 +1,62 @@ package scanner import ( + "net/http" + "net/http/httptest" "net/url" + "strings" "testing" + "github.com/italia/publiccode-crawler/v4/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func TestGitLabScannerUsesTargetInstanceAPI(t *testing.T) { + requests := make([]string, 0, 4) + expectedHost := "" + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, expectedHost, r.Host) + assert.True(t, strings.HasPrefix(r.URL.Path, "/api/v4/"), r.URL.Path) + requests = append(requests, r.URL.EscapedPath()) + + switch r.URL.EscapedPath() { + case "/api/v4/groups/example": + _, _ = w.Write([]byte(`{"id": 1}`)) + case "/api/v4/groups/1/projects", "/api/v4/groups/1/descendant_groups": + _, _ = w.Write([]byte(`[]`)) + case "/api/v4/projects/example%2Fproject": + _, _ = w.Write([]byte(`{}`)) + default: + t.Errorf("unexpected GitLab API request: %s", r.URL.EscapedPath()) + http.NotFound(w, r) + } + })) + defer server.Close() + expectedHost = strings.TrimPrefix(server.URL, "http://") + + instanceURL, err := url.Parse(server.URL) + require.NoError(t, err) + + scanner := NewGitLabScanner() + repositories := make(chan common.Repository) + + groupURL := *instanceURL + groupURL.Path = "/example" + require.NoError(t, scanner.List(groupURL, common.Publisher{}, repositories)) + + projectURL := *instanceURL + projectURL.Path = "/example/project" + require.NoError(t, scanner.Scan(projectURL, common.Publisher{}, repositories)) + + assert.Equal(t, []string{ + "/api/v4/groups/example", + "/api/v4/groups/1/projects", + "/api/v4/groups/1/descendant_groups", + "/api/v4/projects/example%2Fproject", + }, requests) +} + func TestIsGitlabGroup(t *testing.T) { tests := []struct { rawURL string