diff --git a/checks/fileparser/listing.go b/checks/fileparser/listing.go index 5224df7b289..a7381236e9f 100644 --- a/checks/fileparser/listing.go +++ b/checks/fileparser/listing.go @@ -140,7 +140,7 @@ func onMatchingFileDo(repoClient clients.RepoClient, matchPathTo PathMatcher, return sce.WithMessage(sce.ErrScorecardInternal, msg) } if err != nil { - return err + return fmt.Errorf("%s: %w", file, err) } if !continueIter { diff --git a/checks/fileparser/listing_test.go b/checks/fileparser/listing_test.go index 0f2c3538cb3..23dc27ac0e6 100644 --- a/checks/fileparser/listing_test.go +++ b/checks/fileparser/listing_test.go @@ -537,6 +537,33 @@ func TestOnMatchingFileContent(t *testing.T) { } } +func TestOnMatchingFileContentIncludesFilePathOnCallbackError(t *testing.T) { + t.Parallel() + + const workflowPath = ".github/workflows/bad.yaml" + ctrl := gomock.NewController(t) + mockRepo := mockrepo.NewMockRepoClient(ctrl) + mockRepo.EXPECT().ListFiles(gomock.Any()).Return([]string{workflowPath}, nil) + mockRepo.EXPECT().GetFileReader(workflowPath).Return(io.NopCloser(strings.NewReader("")), nil) + + err := OnMatchingFileContentDo(mockRepo, PathMatcher{ + Pattern: ".github/workflows/*", + CaseSensitive: false, + }, func(string, []byte, ...interface{}) (bool, error) { + return false, errTest + }) + + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), workflowPath) { + t.Fatalf("expected error to include %q, got %q", workflowPath, err) + } + if !errors.Is(err, errTest) { + t.Fatalf("expected error to wrap errTest, got %q", err) + } +} + // TestOnAllFilesDo tests the OnAllFilesDo function. func TestOnAllFilesDo(t *testing.T) { t.Parallel() diff --git a/checks/raw/github/packaging.go b/checks/raw/github/packaging.go index 5aa02bd8bd9..a483a27a8b7 100644 --- a/checks/raw/github/packaging.go +++ b/checks/raw/github/packaging.go @@ -32,9 +32,6 @@ import ( func Packaging(c *checker.CheckRequest) (checker.PackagingData, error) { var data checker.PackagingData matchedFiles, err := c.RepoClient.ListFiles(fileparser.IsGithubWorkflowFileCb) - if err != nil { - return data, fmt.Errorf("%w", err) - } if err != nil { return data, fmt.Errorf("RepoClient.ListFiles: %w", err) } @@ -53,7 +50,7 @@ func Packaging(c *checker.CheckRequest) (checker.PackagingData, error) { workflow, errs := actionlint.Parse(fc) if len(errs) > 0 && workflow == nil { e := fileparser.FormatActionlintError(errs) - return data, e + return data, fmt.Errorf("%s: %w", fp, e) } // Check if it's a packaging workflow. diff --git a/checks/raw/github/packaging_test.go b/checks/raw/github/packaging_test.go new file mode 100644 index 00000000000..e0248609485 --- /dev/null +++ b/checks/raw/github/packaging_test.go @@ -0,0 +1,47 @@ +// Copyright 2026 OpenSSF Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package github + +import ( + "io" + "strings" + "testing" + + "go.uber.org/mock/gomock" + + "github.com/ossf/scorecard/v5/checker" + mockrepo "github.com/ossf/scorecard/v5/clients/mockclients" +) + +func TestPackagingIncludesWorkflowPathOnParseError(t *testing.T) { + t.Parallel() + + const workflowPath = ".github/workflows/bad.yaml" + ctrl := gomock.NewController(t) + mockRepo := mockrepo.NewMockRepoClient(ctrl) + mockRepo.EXPECT().ListFiles(gomock.Any()).Return([]string{workflowPath}, nil) + mockRepo.EXPECT().GetFileReader(workflowPath).Return( + io.NopCloser(strings.NewReader("name: bad\non: [push\n")), + nil, + ) + + _, err := Packaging(&checker.CheckRequest{RepoClient: mockRepo}) + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), workflowPath) { + t.Fatalf("expected error to include %q, got %q", workflowPath, err) + } +}