diff --git a/internal/services/report/service.go b/internal/services/report/service.go index ce28c2c8..ce4aa55c 100644 --- a/internal/services/report/service.go +++ b/internal/services/report/service.go @@ -205,6 +205,11 @@ func (s *Service) parseReportResponse(responseBody []byte, opts Options, warning } if !queryResponse.Data.CreateArtifact.Ok { + if queryResponse.Data.CreateArtifact.Error == "" { + err := fmt.Errorf("reporting failed with empty error, raw response: %s", string(responseBody)) + s.capture(err) + return nil, err + } err := errors.New(queryResponse.Data.CreateArtifact.Error) s.capture(err) return nil, fmt.Errorf("Reporting failed: %s", queryResponse.Data.CreateArtifact.Error) diff --git a/internal/services/report/service_test.go b/internal/services/report/service_test.go index 2aa898c8..c93d9e39 100644 --- a/internal/services/report/service_test.go +++ b/internal/services/report/service_test.go @@ -283,6 +283,92 @@ func TestReportSkipCertVerification(t *testing.T) { assert.Error(t, err) } +func TestReportCreateArtifactError(t *testing.T) { + tempDir := t.TempDir() + artifactPath := filepath.Join(tempDir, "coverage.xml") + assert.NoError(t, os.WriteFile(artifactPath, []byte(""), 0o644)) + + httpClient := &mockHTTPClient{DoFunc: func(req *http.Request) (*http.Response, error) { + body, _ := io.ReadAll(req.Body) + _ = req.Body.Close() + if bytes.Contains(body, []byte("ArtifactMetadataInput")) { + payload := `{"data":{"__type":{"inputFields":[]}}}` + return httpResponse(200, payload), nil + } + if bytes.Contains(body, []byte("createArtifact")) { + payload := `{"data":{"createArtifact":{"ok":false,"message":"","error":"Invalid repository"}}}` + return httpResponse(200, payload), nil + } + return httpResponse(400, `{"error":"unexpected"}`), nil + }} + + git := adapters.NewMockGitClient() + git.SetHead("abc123", "") + env := adapters.NewMockEnvironment() + env.Set("DEEPSOURCE_DSN", "https://token@localhost:8080") + + svc := NewService(ServiceDeps{ + GitClient: git, + HTTPClient: httpClient, + FileSystem: adapters.NewOSFileSystem(), + Environment: env, + Sentry: adapters.NewNoOpSentry(), + Output: adapters.NewBufferOutput(), + Workdir: func() (string, error) { return tempDir, nil }, + }) + + _, err := svc.Report(context.Background(), Options{ + Analyzer: "test-coverage", + Key: "python", + ValueFile: artifactPath, + }) + assert.Error(t, err) + assert.Contains(t, err.Error(), "Invalid repository") +} + +func TestReportCreateArtifactEmptyError(t *testing.T) { + tempDir := t.TempDir() + artifactPath := filepath.Join(tempDir, "coverage.xml") + assert.NoError(t, os.WriteFile(artifactPath, []byte(""), 0o644)) + + httpClient := &mockHTTPClient{DoFunc: func(req *http.Request) (*http.Response, error) { + body, _ := io.ReadAll(req.Body) + _ = req.Body.Close() + if bytes.Contains(body, []byte("ArtifactMetadataInput")) { + payload := `{"data":{"__type":{"inputFields":[]}}}` + return httpResponse(200, payload), nil + } + if bytes.Contains(body, []byte("createArtifact")) { + payload := `{"data":{"createArtifact":{"ok":false,"message":"","error":""}}}` + return httpResponse(200, payload), nil + } + return httpResponse(400, `{"error":"unexpected"}`), nil + }} + + git := adapters.NewMockGitClient() + git.SetHead("abc123", "") + env := adapters.NewMockEnvironment() + env.Set("DEEPSOURCE_DSN", "https://token@localhost:8080") + + svc := NewService(ServiceDeps{ + GitClient: git, + HTTPClient: httpClient, + FileSystem: adapters.NewOSFileSystem(), + Environment: env, + Sentry: adapters.NewNoOpSentry(), + Output: adapters.NewBufferOutput(), + Workdir: func() (string, error) { return tempDir, nil }, + }) + + _, err := svc.Report(context.Background(), Options{ + Analyzer: "test-coverage", + Key: "python", + ValueFile: artifactPath, + }) + assert.Error(t, err) + assert.Contains(t, err.Error(), "raw response") +} + func TestCaptureSkipsUserErrors(t *testing.T) { captured := false mockSentry := &captureSentry{onCapture: func(_ error) { captured = true }}