Skip to content

Commit

Permalink
Merge branch 'main' into feat/rawcii
Browse files Browse the repository at this point in the history
  • Loading branch information
laurentsimon committed Apr 14, 2022
2 parents 19edc33 + 4d1c531 commit 8317afc
Show file tree
Hide file tree
Showing 17 changed files with 466 additions and 218 deletions.
14 changes: 12 additions & 2 deletions .github/workflows/integration.yml
Expand Up @@ -74,15 +74,25 @@ jobs:
run: |
go mod download
- name: Run E2E #using retry because the GitHub token is being throttled.
- name: Run GITHUB_TOKEN E2E #using retry because the GitHub token is being throttled.
uses: nick-invision/retry@7f8f3d9f0f62fe5925341be21c2e8314fd4f7c7c
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
max_attempts: 3
retry_on: error
timeout_minutes: 30
command: make e2e-gh-token

- name: Run PAT E2E #using retry because the GitHub token is being throttled.
uses: nick-invision/retry@7f8f3d9f0f62fe5925341be21c2e8314fd4f7c7c
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GH_AUTH_TOKEN }}
with:
max_attempts: 3
retry_on: error
timeout_minutes: 30
command: make e2e
command: make e2e-pat

- name: codecov
uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 # 2.1.0
Expand Down
13 changes: 9 additions & 4 deletions Makefile
Expand Up @@ -277,7 +277,7 @@ cron-github-server-docker:

##@ Tests
################################# make test ###################################
test-targets = unit-test e2e ci-e2e
test-targets = unit-test e2e-pat e2e-gh-token ci-e2e
.PHONY: test $(test-targets)
test: $(test-targets)

Expand All @@ -293,8 +293,13 @@ ifndef GITHUB_AUTH_TOKEN
$(error GITHUB_AUTH_TOKEN is undefined)
endif

e2e: ## Runs e2e tests. Requires GITHUB_AUTH_TOKEN env var to be set to GitHub personal access token
e2e: build-scorecard check-env | $(GINKGO)
e2e-pat: ## Runs e2e tests. Requires GITHUB_AUTH_TOKEN env var to be set to GitHub personal access token
e2e-pat: build-scorecard check-env | $(GINKGO)
# Run e2e tests. GITHUB_AUTH_TOKEN with personal access token must be exported to run this
$(GINKGO) --race -p -v -cover -coverprofile=e2e-coverage.out ./...
TOKEN_TYPE="PAT" $(GINKGO) --race -p -v -cover -coverprofile=e2e-coverage.out ./...

e2e-gh-token: ## Runs e2e tests. Requires GITHUB_AUTH_TOKEN env var to be set to default GITHUB_TOKEN
e2e-gh-token: build-scorecard check-env | $(GINKGO)
# Run e2e tests. GITHUB_AUTH_TOKEN set to secrets.GITHUB_TOKEN must be used to run this.
TOKEN_TYPE="GITHUB_TOKEN" $(GINKGO) --race -p -v -cover -coverprofile=e2e-coverage.out ./...
###############################################################################
7 changes: 7 additions & 0 deletions checker/raw_result.go
Expand Up @@ -30,6 +30,7 @@ type RawResults struct {
WebhookResults WebhooksData
MaintainedResults MaintainedData
SignedReleasesResults SignedReleasesData
LicenseResults LicenseData
}

// MaintainedData contains the raw results
Expand All @@ -40,6 +41,12 @@ type MaintainedData struct {
ArchivedStatus ArchivedStatus
}

// LicenseData contains the raw results
// for the License check.
type LicenseData struct {
Files []File
}

// CodeReviewData contains the raw results
// for the Code-Review check.
type CodeReviewData struct {
Expand Down
45 changes: 45 additions & 0 deletions checks/evaluation/license.go
@@ -0,0 +1,45 @@
// Copyright 2021 Security 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 evaluation

import (
"github.com/ossf/scorecard/v4/checker"
sce "github.com/ossf/scorecard/v4/errors"
)

// License applies the score policy for the License check.
func License(name string, dl checker.DetailLogger,
r *checker.LicenseData,
) checker.CheckResult {
if r == nil {
e := sce.WithMessage(sce.ErrScorecardInternal, "empty raw data")
return checker.CreateRuntimeErrorResult(name, e)
}

// Apply the policy evaluation.
if r.Files == nil || len(r.Files) == 0 {
return checker.CreateMinScoreResult(name, "license file not detected")
}

for _, f := range r.Files {
dl.Info(&checker.LogMessage{
Path: f.Path,
Type: checker.FileTypeSource,
Offset: 1,
})
}

return checker.CreateMaxScoreResult(name, "license file detected")
}
135 changes: 13 additions & 122 deletions checks/license.go
Expand Up @@ -15,22 +15,12 @@
package checks

import (
"fmt"
"regexp"
"strings"

"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/checks/fileparser"
"github.com/ossf/scorecard/v4/checks/evaluation"
"github.com/ossf/scorecard/v4/checks/raw"
sce "github.com/ossf/scorecard/v4/errors"
)

type check func(str string, extCheck []string) bool

type checks struct {
rstr string // regex string
f check
p []string
}

// CheckLicense is the registered name for License.
const CheckLicense = "License"

Expand All @@ -40,123 +30,24 @@ func init() {
checker.FileBased,
checker.CommitBased,
}
if err := registerCheck(CheckLicense, LicenseCheck, supportedRequestTypes); err != nil {
if err := registerCheck(CheckLicense, License, supportedRequestTypes); err != nil {
// this should never happen
panic(err)
}
}

const (
copying = "copy(ing|right)"
license = "(un)?licen[sc]e"
preferredExt = "*\\.(md|markdown|html)$"
anyExt = ".[^./]"
ofl = "ofl"
patents = "patents"
)

// Regex converted from
// https://github.com/licensee/licensee/blob/master/lib/licensee/project_files/license_file.rb
var (
extensions = []string{"xml", "go", "gemspec"}
regexChecks = []checks{
{rstr: copying, f: nil},
{rstr: license, f: nil},
{rstr: license + preferredExt, f: nil},
{rstr: copying + preferredExt, f: nil},
{rstr: copying + anyExt, f: nil},
{rstr: ofl, f: nil},
{rstr: ofl + preferredExt, f: nil},
{rstr: patents, f: nil},
{rstr: license, f: extensionMatch, p: []string{"spdx", "header"}},
{rstr: license + "[-_][^.]*", f: extensionMatch, p: extensions},
{rstr: copying + "[-_][^.]*", f: extensionMatch, p: extensions},
{rstr: "\\w+[-_]" + license + "[^.]*", f: extensionMatch, p: extensions},
{rstr: "\\w+[-_]" + copying + "[^.]*", f: extensionMatch, p: extensions},
{rstr: ofl, f: extensionMatch, p: extensions},
}
)

// ExtensionMatch to check for matching extension.
func extensionMatch(f string, exts []string) bool {
s := strings.Split(f, ".")

if len(s) <= 1 {
return false
}

fext := s[len(s)-1]

found := false
for _, ext := range exts {
if ext == fext {
found = true
break
}
}

return found
}

// TestLicenseCheck used for testing purposes.
func testLicenseCheck(name string) bool {
return checkLicense(name)
}

// LicenseCheck runs LicenseCheck check.
func LicenseCheck(c *checker.CheckRequest) checker.CheckResult {
var s string

err := fileparser.OnAllFilesDo(c.RepoClient, isLicenseFile, &s)
// License runs License check.
func License(c *checker.CheckRequest) checker.CheckResult {
rawData, err := raw.License(c)
if err != nil {
return checker.CreateRuntimeErrorResult(CheckLicense, err)
}
if s != "" {
c.Dlogger.Info(&checker.LogMessage{
Path: s,
Type: checker.FileTypeSource,
Offset: 1,
})
return checker.CreateMaxScoreResult(CheckLicense, "license file detected")
e := sce.WithMessage(sce.ErrScorecardInternal, err.Error())
return checker.CreateRuntimeErrorResult(CheckLicense, e)
}
return checker.CreateMinScoreResult(CheckLicense, "license file not detected")
}

var isLicenseFile fileparser.DoWhileTrueOnFilename = func(name string, args ...interface{}) (bool, error) {
if len(args) != 1 {
return false, fmt.Errorf("isLicenseFile requires exactly one argument: %w", errInvalidArgLength)
// Set the raw results.
if c.RawResults != nil {
c.RawResults.LicenseResults = rawData
}
s, ok := args[0].(*string)
if !ok {
return false, fmt.Errorf("isLicenseFile requires argument of type: *string: %w", errInvalidArgType)
}
if checkLicense(name) {
if s != nil {
*s = name
}
return false, nil
}
return true, nil
}

// CheckLicense to check whether the name parameter fulfill license file criteria.
func checkLicense(name string) bool {
for _, check := range regexChecks {
rg := regexp.MustCompile(check.rstr)

nameLower := strings.ToLower(name)
t := rg.MatchString(nameLower)
if t {
extFound := true

// check extension calling f function.
// f function will always be func extensionMatch(..)
if check.f != nil {
extFound = check.f(nameLower, check.p)
}

return extFound
}
}
return false
return evaluation.License(CheckLicense, c.Dlogger, &rawData)
}
82 changes: 1 addition & 81 deletions checks/license_test.go
Expand Up @@ -28,86 +28,6 @@ import (
scut "github.com/ossf/scorecard/v4/utests"
)

func TestLicenseFileCheck(t *testing.T) {
t.Parallel()

tests := []struct {
name string
filename string
}{
{
name: "LICENSE.md",
filename: "LICENSE.md",
},
{
name: "LICENSE",
filename: "LICENSE",
},
{
name: "COPYING",
filename: "COPYING",
},
{
name: "COPYING.md",
filename: "COPYING.md",
},
{
name: "LICENSE.textile",
filename: "LICENSE.textile",
},
{
name: "COPYING.textile",
filename: "COPYING.textile",
},
{
name: "LICENSE-MIT",
filename: "LICENSE-MIT",
},
{
name: "COPYING-MIT",
filename: "COPYING-MIT",
},
{
name: "MIT-LICENSE-MIT",
filename: "MIT-LICENSE-MIT",
},
{
name: "MIT-COPYING",
filename: "MIT-COPYING",
},
{
name: "OFL.md",
filename: "OFL.md",
},
{
name: "OFL.textile",
filename: "OFL.textile",
},
{
name: "OFL",
filename: "OFL",
},
{
name: "PATENTS",
filename: "PATENTS",
},
{
name: "PATENTS.txt",
filename: "PATENTS.txt",
},
}
for _, tt := range tests {
tt := tt // Re-initializing variable so it is not changed while executing the closure below
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
s := testLicenseCheck(tt.filename)
if !s {
t.Fail()
}
})
}
}

func TestLicenseFileSubdirectory(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -167,7 +87,7 @@ func TestLicenseFileSubdirectory(t *testing.T) {
Dlogger: &dl,
}

res := LicenseCheck(&req)
res := License(&req)

if !scut.ValidateTestReturn(t, tt.name, &tt.expected, &res, &dl) {
t.Fail()
Expand Down

0 comments on commit 8317afc

Please sign in to comment.