mirror of
https://github.com/ossf/scorecard.git
synced 2024-09-11 08:55:27 +03:00
🌱 Refactor to make it testable
- Related to https://github.com/ossf/scorecard/issues/1568 Signed-off-by: naveensrinivasan <172697+naveensrinivasan@users.noreply.github.com>
This commit is contained in:
parent
f2a132a430
commit
1995bc3b9c
6
Makefile
6
Makefile
@ -110,7 +110,7 @@ cron/data/metadata.pb.go: cron/data/metadata.proto | $(PROTOC)
|
||||
protoc --go_out=../../../ cron/data/metadata.proto
|
||||
|
||||
generate-mocks: ## Compiles and generates all mocks using mockgen.
|
||||
generate-mocks: clients/mockclients/repo_client.go clients/mockclients/repo.go clients/mockclients/cii_client.go checks/mockclients/vulnerabilities.go
|
||||
generate-mocks: clients/mockclients/repo_client.go clients/mockclients/repo.go clients/mockclients/cii_client.go checks/mockclients/vulnerabilities.go checks/mockclients/packagemanager.go
|
||||
clients/mockclients/repo_client.go: clients/repo_client.go
|
||||
# Generating MockRepoClient
|
||||
$(MOCKGEN) -source=clients/repo_client.go -destination=clients/mockclients/repo_client.go -package=mockrepo -copyright_file=clients/mockclients/license.txt
|
||||
@ -123,7 +123,9 @@ clients/mockclients/cii_client.go: clients/cii_client.go
|
||||
checks/mockclients/vulnerabilities.go: clients/vulnerabilities.go
|
||||
# Generating MockCIIClient
|
||||
$(MOCKGEN) -source=clients/vulnerabilities.go -destination=clients/mockclients/vulnerabilities.go -package=mockrepo -copyright_file=clients/mockclients/license.txt
|
||||
|
||||
checks/mockclients/packagemanager.go: cmd/packagemanager_client.go
|
||||
# Generating MockPackageManagerClient
|
||||
$(MOCKGEN) -source=cmd/packagemanager_client.go -destination=clients/mockclients/packagemanager.go -package=mockrepo -copyright_file=clients/mockclients/license.txt
|
||||
generate-docs: ## Generates docs
|
||||
generate-docs: validate-docs docs/checks.md
|
||||
docs/checks.md: docs/checks/internal/checks.yaml docs/checks/internal/*.go docs/checks/internal/generate/*.go
|
||||
|
65
clients/mockclients/packagemanager.go
Normal file
65
clients/mockclients/packagemanager.go
Normal file
@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
//
|
||||
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: cmd/packagemanager_client.go
|
||||
|
||||
// Package mockrepo is a generated GoMock package.
|
||||
package mockrepo
|
||||
|
||||
import (
|
||||
http "net/http"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockpackageManagerClient is a mock of packageManagerClient interface.
|
||||
type MockpackageManagerClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockpackageManagerClientMockRecorder
|
||||
}
|
||||
|
||||
// MockpackageManagerClientMockRecorder is the mock recorder for MockpackageManagerClient.
|
||||
type MockpackageManagerClientMockRecorder struct {
|
||||
mock *MockpackageManagerClient
|
||||
}
|
||||
|
||||
// NewMockpackageManagerClient creates a new mock instance.
|
||||
func NewMockpackageManagerClient(ctrl *gomock.Controller) *MockpackageManagerClient {
|
||||
mock := &MockpackageManagerClient{ctrl: ctrl}
|
||||
mock.recorder = &MockpackageManagerClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockpackageManagerClient) EXPECT() *MockpackageManagerClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockpackageManagerClient) Get(URI, packagename string) (*http.Response, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", URI, packagename)
|
||||
ret0, _ := ret[0].(*http.Response)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockpackageManagerClientMockRecorder) Get(URI, packagename interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockpackageManagerClient)(nil).Get), URI, packagename)
|
||||
}
|
@ -15,7 +15,9 @@
|
||||
// Package clients defines the interface for RepoClient and related structs.
|
||||
package clients
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrUnsupportedFeature indicates an API that is not supported by the client.
|
||||
var ErrUnsupportedFeature = errors.New("unsupported feature")
|
||||
|
@ -18,8 +18,6 @@ package cmd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
sce "github.com/ossf/scorecard/v4/errors"
|
||||
)
|
||||
@ -29,24 +27,24 @@ type packageMangerResponse struct {
|
||||
exists bool
|
||||
}
|
||||
|
||||
// TODO(#1568): Add unit tests for this.
|
||||
func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems string) (packageMangerResponse, error) {
|
||||
func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems string,
|
||||
manager packageManagerClient) (packageMangerResponse, error) {
|
||||
if npm != "" {
|
||||
gitRepo, err := fetchGitRepositoryFromNPM(npm)
|
||||
gitRepo, err := fetchGitRepositoryFromNPM(npm, manager)
|
||||
return packageMangerResponse{
|
||||
exists: true,
|
||||
associatedRepo: gitRepo,
|
||||
}, err
|
||||
}
|
||||
if pypi != "" {
|
||||
gitRepo, err := fetchGitRepositoryFromPYPI(pypi)
|
||||
gitRepo, err := fetchGitRepositoryFromPYPI(pypi, manager)
|
||||
return packageMangerResponse{
|
||||
exists: true,
|
||||
associatedRepo: gitRepo,
|
||||
}, err
|
||||
}
|
||||
if rubygems != "" {
|
||||
gitRepo, err := fetchGitRepositoryFromRubyGems(rubygems)
|
||||
gitRepo, err := fetchGitRepositoryFromRubyGems(rubygems, manager)
|
||||
return packageMangerResponse{
|
||||
exists: true,
|
||||
associatedRepo: gitRepo,
|
||||
@ -79,14 +77,9 @@ type rubyGemsSearchResults struct {
|
||||
}
|
||||
|
||||
// Gets the GitHub repository URL for the npm package.
|
||||
// nolint: noctx
|
||||
func fetchGitRepositoryFromNPM(packageName string) (string, error) {
|
||||
func fetchGitRepositoryFromNPM(packageName string, packageManager packageManagerClient) (string, error) {
|
||||
npmSearchURL := "https://registry.npmjs.org/-/v1/search?text=%s&size=1"
|
||||
const timeout = 10
|
||||
client := &http.Client{
|
||||
Timeout: timeout * time.Second,
|
||||
}
|
||||
resp, err := client.Get(fmt.Sprintf(npmSearchURL, packageName))
|
||||
resp, err := packageManager.Get(npmSearchURL, packageName)
|
||||
if err != nil {
|
||||
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get npm package json: %v", err))
|
||||
}
|
||||
@ -105,14 +98,9 @@ func fetchGitRepositoryFromNPM(packageName string) (string, error) {
|
||||
}
|
||||
|
||||
// Gets the GitHub repository URL for the pypi package.
|
||||
// nolint: noctx
|
||||
func fetchGitRepositoryFromPYPI(packageName string) (string, error) {
|
||||
func fetchGitRepositoryFromPYPI(packageName string, manager packageManagerClient) (string, error) {
|
||||
pypiSearchURL := "https://pypi.org/pypi/%s/json"
|
||||
const timeout = 10
|
||||
client := &http.Client{
|
||||
Timeout: timeout * time.Second,
|
||||
}
|
||||
resp, err := client.Get(fmt.Sprintf(pypiSearchURL, packageName))
|
||||
resp, err := manager.Get(pypiSearchURL, packageName)
|
||||
if err != nil {
|
||||
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get pypi package json: %v", err))
|
||||
}
|
||||
@ -131,14 +119,9 @@ func fetchGitRepositoryFromPYPI(packageName string) (string, error) {
|
||||
}
|
||||
|
||||
// Gets the GitHub repository URL for the rubygems package.
|
||||
// nolint: noctx
|
||||
func fetchGitRepositoryFromRubyGems(packageName string) (string, error) {
|
||||
func fetchGitRepositoryFromRubyGems(packageName string, manager packageManagerClient) (string, error) {
|
||||
rubyGemsSearchURL := "https://rubygems.org/api/v1/gems/%s.json"
|
||||
const timeout = 10
|
||||
client := &http.Client{
|
||||
Timeout: timeout * time.Second,
|
||||
}
|
||||
resp, err := client.Get(fmt.Sprintf(rubyGemsSearchURL, packageName))
|
||||
resp, err := manager.Get(rubyGemsSearchURL, packageName)
|
||||
if err != nil {
|
||||
return "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get ruby gem json: %v", err))
|
||||
}
|
||||
|
710
cmd/package_managers_test.go
Normal file
710
cmd/package_managers_test.go
Normal file
@ -0,0 +1,710 @@
|
||||
// Copyright 2020 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 cmd implements Scorecard commandline.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
|
||||
mockrepo "github.com/ossf/scorecard/v4/clients/mockclients"
|
||||
)
|
||||
|
||||
func Test_fetchGitRepositoryFromNPM(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
packageName string
|
||||
result string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: `
|
||||
{
|
||||
"objects": [
|
||||
{
|
||||
"package": {
|
||||
"name": "@pulumi/pulumi",
|
||||
"scope": "pulumi",
|
||||
"version": "3.26.0",
|
||||
"description": "Pulumi's Node.js SDK",
|
||||
"date": "2022-03-09T14:05:40.682Z",
|
||||
"links": {
|
||||
"homepage": "https://github.com/pulumi/pulumi#readme",
|
||||
"repository": "https://github.com/pulumi/pulumi",
|
||||
"bugs": "https://github.com/pulumi/pulumi/issues"
|
||||
},
|
||||
"publisher": {
|
||||
"username": "pulumi-bot",
|
||||
"email": "bot@pulumi.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"username": "joeduffy",
|
||||
"email": "joe@pulumi.com"
|
||||
},
|
||||
{
|
||||
"username": "pulumi-bot",
|
||||
"email": "bot@pulumi.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"score": {
|
||||
"final": 0.4056031974977145,
|
||||
"detail": {
|
||||
"quality": 0.7308571951451065,
|
||||
"popularity": 0.19908392082147397,
|
||||
"maintenance": 0.3333333333333333
|
||||
}
|
||||
},
|
||||
"searchScore": 0.00090895034
|
||||
}
|
||||
],
|
||||
"total": 380,
|
||||
"time": "Wed Mar 09 2022 18:11:10 GMT+0000 (Coordinated Universal Time)"
|
||||
}
|
||||
`,
|
||||
},
|
||||
want: "https://github.com/pulumi/pulumi",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "foo",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: `
|
||||
{
|
||||
"objects": [],
|
||||
"total": 380,
|
||||
"time": "Wed Mar 09 2022 18:11:10 GMT+0000 (Coordinated Universal Time)"
|
||||
}
|
||||
`,
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctrl := gomock.NewController(t)
|
||||
p := mockrepo.NewMockpackageManagerClient(ctrl)
|
||||
p.EXPECT().Get(gomock.Any(), tt.args.packageName).
|
||||
DoAndReturn(func(url, packageName string) (*http.Response, error) {
|
||||
if tt.wantErr && tt.args.result == "" {
|
||||
//nolint
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(tt.args.result)),
|
||||
}, nil
|
||||
}).AnyTimes()
|
||||
got, err := fetchGitRepositoryFromNPM(tt.args.packageName, p)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("fetchGitRepositoryFromNPM() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("fetchGitRepositoryFromNPM() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_fetchGitRepositoryFromPYPI(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
packageName string
|
||||
result string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "fetchGitRepositoryFromPYPI",
|
||||
//nolint
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
//nolint
|
||||
result: `
|
||||
{
|
||||
"info": {
|
||||
"author": "Hüseyin Tekinaslan",
|
||||
"author_email": "htaslan@bil.omu.edu.tr",
|
||||
"bugtrack_url": null,
|
||||
"classifiers": [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.2",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules"
|
||||
],
|
||||
"description": "UNKNOWN",
|
||||
"description_content_type": null,
|
||||
"docs_url": null,
|
||||
"downoad_url": null,
|
||||
"downloads": {
|
||||
"last_day": -1,
|
||||
"last_month": -1,
|
||||
"last_week": -1
|
||||
},
|
||||
"home_page": "http://github.com/htaslan/color",
|
||||
"keywords": "colorize pycolorize color pycolor",
|
||||
"license": "MIT",
|
||||
"maintainer": null,
|
||||
"maintainer_email": null,
|
||||
"name": "color",
|
||||
"package_url": "https://pypi.org/project/color/",
|
||||
"platform": "UNKNOWN",
|
||||
"project_url": "https://pypi.org/project/color/",
|
||||
"project_urls": {
|
||||
"Homepage": "http://github.com/htaslan/color",
|
||||
"Source": "foo"
|
||||
},
|
||||
"release_url": "https://pypi.org/project/color/0.1/",
|
||||
"requires_dist": null,
|
||||
"requires_python": null,
|
||||
"summary": "python module for colorize string",
|
||||
"version": "0.1",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
},
|
||||
"last_serial": 2041956,
|
||||
"releases": {
|
||||
"0.1": [
|
||||
{
|
||||
"comment_text": "a python module of colorize string",
|
||||
"digests": {
|
||||
"md5": "1a4577069c636b28d85052db9a384b95",
|
||||
"sha256": "de5b51fea834cb067631beaa1ec11d7753f1e3615e836e2e4c34dcf2b343eac2"
|
||||
},
|
||||
"downloads": -1,
|
||||
"filename": "color-0.1.1.tar.gz",
|
||||
"has_sig": false,
|
||||
"md5_digest": "1a4577069c636b28d85052db9a384b95",
|
||||
"packagetype": "sdist",
|
||||
"python_version": "source",
|
||||
"requires_python": null,
|
||||
"size": 3568,
|
||||
"upload_time": "2016-04-01T13:23:25",
|
||||
"upload_time_iso_8601": "2016-04-01T13:23:25.284973Z",
|
||||
"url": "https://files.pythonhosted.org/packages/88/04/0defd6f424e5bafb5abc75510cbe119a85d80b5505f1de5cd9a16d89ba8c/color-0.1.1.tar.gz",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"urls": [
|
||||
{
|
||||
"comment_text": "a python module of colorize string",
|
||||
"digests": {
|
||||
"md5": "1a4577069c636b28d85052db9a384b95",
|
||||
"sha256": "de5b51fea834cb067631beaa1ec11d7753f1e3615e836e2e4c34dcf2b343eac2"
|
||||
},
|
||||
"downloads": -1,
|
||||
"filename": "color-0.1.1.tar.gz",
|
||||
"has_sig": false,
|
||||
"md5_digest": "1a4577069c636b28d85052db9a384b95",
|
||||
"packagetype": "sdist",
|
||||
"python_version": "source",
|
||||
"requires_python": null,
|
||||
"size": 3568,
|
||||
"upload_time": "2016-04-01T13:23:25",
|
||||
"upload_time_iso_8601": "2016-04-01T13:23:25.284973Z",
|
||||
"url": "https://files.pythonhosted.org/packages/88/04/0defd6f424e5bafb5abc75510cbe119a85d80b5505f1de5cd9a16d89ba8c/color-0.1.1.tar.gz",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
}
|
||||
],
|
||||
"vulnerabilities": []
|
||||
}
|
||||
|
||||
`,
|
||||
},
|
||||
want: "foo",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "foo",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty project url",
|
||||
//nolint
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
//nolint
|
||||
result: `
|
||||
{
|
||||
"info": {
|
||||
"author": "Hüseyin Tekinaslan",
|
||||
"author_email": "htaslan@bil.omu.edu.tr",
|
||||
"bugtrack_url": null,
|
||||
"classifiers": [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.2",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules"
|
||||
],
|
||||
"description": "UNKNOWN",
|
||||
"description_content_type": null,
|
||||
"docs_url": null,
|
||||
"downoad_url": null,
|
||||
"downloads": {
|
||||
"last_day": -1,
|
||||
"last_month": -1,
|
||||
"last_week": -1
|
||||
},
|
||||
"home_page": "http://github.com/htaslan/color",
|
||||
"keywords": "colorize pycolorize color pycolor",
|
||||
"license": "MIT",
|
||||
"maintainer": null,
|
||||
"maintainer_email": null,
|
||||
"name": "color",
|
||||
"package_url": "https://pypi.org/project/color/",
|
||||
"platform": "UNKNOWN",
|
||||
"project_url": "https://pypi.org/project/color/",
|
||||
"project_urls": {
|
||||
"Homepage": "http://github.com/htaslan/color",
|
||||
"Source": ""
|
||||
},
|
||||
"release_url": "https://pypi.org/project/color/0.1/",
|
||||
"requires_dist": null,
|
||||
"requires_python": null,
|
||||
"summary": "python module for colorize string",
|
||||
"version": "0.1",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
},
|
||||
"last_serial": 2041956,
|
||||
"releases": {
|
||||
"0.1": [
|
||||
{
|
||||
"comment_text": "a python module of colorize string",
|
||||
"digests": {
|
||||
"md5": "1a4577069c636b28d85052db9a384b95",
|
||||
"sha256": "de5b51fea834cb067631beaa1ec11d7753f1e3615e836e2e4c34dcf2b343eac2"
|
||||
},
|
||||
"downloads": -1,
|
||||
"filename": "color-0.1.1.tar.gz",
|
||||
"has_sig": false,
|
||||
"md5_digest": "1a4577069c636b28d85052db9a384b95",
|
||||
"packagetype": "sdist",
|
||||
"python_version": "source",
|
||||
"requires_python": null,
|
||||
"size": 3568,
|
||||
"upload_time": "2016-04-01T13:23:25",
|
||||
"upload_time_iso_8601": "2016-04-01T13:23:25.284973Z",
|
||||
"url": "https://files.pythonhosted.org/packages/88/04/0defd6f424e5bafb5abc75510cbe119a85d80b5505f1de5cd9a16d89ba8c/color-0.1.1.tar.gz",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"urls": [
|
||||
{
|
||||
"comment_text": "a python module of colorize string",
|
||||
"digests": {
|
||||
"md5": "1a4577069c636b28d85052db9a384b95",
|
||||
"sha256": "de5b51fea834cb067631beaa1ec11d7753f1e3615e836e2e4c34dcf2b343eac2"
|
||||
},
|
||||
"downloads": -1,
|
||||
"filename": "color-0.1.1.tar.gz",
|
||||
"has_sig": false,
|
||||
"md5_digest": "1a4577069c636b28d85052db9a384b95",
|
||||
"packagetype": "sdist",
|
||||
"python_version": "source",
|
||||
"requires_python": null,
|
||||
"size": 3568,
|
||||
"upload_time": "2016-04-01T13:23:25",
|
||||
"upload_time_iso_8601": "2016-04-01T13:23:25.284973Z",
|
||||
"url": "https://files.pythonhosted.org/packages/88/04/0defd6f424e5bafb5abc75510cbe119a85d80b5505f1de5cd9a16d89ba8c/color-0.1.1.tar.gz",
|
||||
"yanked": false,
|
||||
"yanked_reason": null
|
||||
}
|
||||
],
|
||||
"vulnerabilities": []
|
||||
}
|
||||
`,
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctrl := gomock.NewController(t)
|
||||
p := mockrepo.NewMockpackageManagerClient(ctrl)
|
||||
p.EXPECT().Get(gomock.Any(), tt.args.packageName).
|
||||
DoAndReturn(func(url, packageName string) (*http.Response, error) {
|
||||
if tt.wantErr && tt.args.result == "" {
|
||||
//nolint
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(tt.args.result)),
|
||||
}, nil
|
||||
}).AnyTimes()
|
||||
got, err := fetchGitRepositoryFromPYPI(tt.args.packageName, p)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("fetchGitRepositoryFromPYPI() error = %v, wantErr %v testcase name %v", err, tt.wantErr, tt.name)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("fetchGitRepositoryFromPYPI() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_fetchGitRepositoryFromRubyGems(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
packageName string
|
||||
result string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "fetchGitRepositoryFromPYPI",
|
||||
//nolint
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
//nolint
|
||||
result: `
|
||||
{
|
||||
"name": "color",
|
||||
"downloads": 8177801,
|
||||
"version": "1.8",
|
||||
"version_created_at": "2015-10-26T05:03:11.976Z",
|
||||
"version_downloads": 4558362,
|
||||
"platform": "ruby",
|
||||
"authors": "Austin Ziegler, Matt Lyon",
|
||||
"info": "Color is a Ruby library to provide basic RGB, CMYK, HSL, and other colourspace\nmanipulation support to applications that require it. It also provides 152\nnamed RGB colours (184 with spelling variations) that are commonly supported in\nHTML, SVG, and X11 applications. A technique for generating monochromatic\ncontrasting palettes is also included.\n\nThe Color library performs purely mathematical manipulation of the colours\nbased on colour theory without reference to colour profiles (such as sRGB or\nAdobe RGB). For most purposes, when working with RGB and HSL colour spaces,\nthis won't matter. Absolute colour spaces (like CIE L*a*b* and XYZ) and cannot\nbe reliably converted to relative colour spaces (like RGB) without colour\nprofiles.\n\nColor 1.8 adds an alpha parameter to all <tt>#css_rgba</tt> calls, fixes a bug\nexposed by new constant lookup semantics in Ruby 2, and ensures that\n<tt>Color.equivalent?</tt> can only be called on Color instances.\n\nBarring bugs introduced in this release, this (really) is the last version of\ncolor that supports Ruby 1.8, so make sure that your gem specification is set\nproperly (to <tt>~> 1.8</tt>) if that matters for your application. This\nversion will no longer be supported one year after the release of color 2.0.",
|
||||
"licenses": [
|
||||
"MIT"
|
||||
],
|
||||
"metadata": {},
|
||||
"yanked": false,
|
||||
"sha": "0a8512ecf6a8fe14928707f7d2766680c955b3a2224de198c1e25c837cd36f82",
|
||||
"project_uri": "https://rubygems.org/gems/color",
|
||||
"gem_uri": "https://rubygems.org/gems/color-1.8.gem",
|
||||
"homepage_uri": "https://github.com/halostatue/color",
|
||||
"wiki_uri": null,
|
||||
"documentation_uri": "https://www.rubydoc.info/gems/color/1.8",
|
||||
"mailing_list_uri": null,
|
||||
"source_code_uri": "foo",
|
||||
"bug_tracker_uri": null,
|
||||
"changelog_uri": null,
|
||||
"funding_uri": null,
|
||||
"dependencies": {
|
||||
"development": [
|
||||
{
|
||||
"name": "hoe",
|
||||
"requirements": "~> 3.14"
|
||||
},
|
||||
{
|
||||
"name": "hoe-doofus",
|
||||
"requirements": "~> 1.0"
|
||||
},
|
||||
{
|
||||
"name": "hoe-gemspec2",
|
||||
"requirements": "~> 1.1"
|
||||
},
|
||||
{
|
||||
"name": "hoe-git",
|
||||
"requirements": "~> 1.6"
|
||||
},
|
||||
{
|
||||
"name": "hoe-travis",
|
||||
"requirements": "~> 1.2"
|
||||
},
|
||||
{
|
||||
"name": "minitest",
|
||||
"requirements": "~> 5.8"
|
||||
},
|
||||
{
|
||||
"name": "minitest-around",
|
||||
"requirements": "~> 0.3"
|
||||
},
|
||||
{
|
||||
"name": "minitest-autotest",
|
||||
"requirements": "~> 1.0"
|
||||
},
|
||||
{
|
||||
"name": "minitest-bisect",
|
||||
"requirements": "~> 1.2"
|
||||
},
|
||||
{
|
||||
"name": "minitest-focus",
|
||||
"requirements": "~> 1.1"
|
||||
},
|
||||
{
|
||||
"name": "minitest-moar",
|
||||
"requirements": "~> 0.0"
|
||||
},
|
||||
{
|
||||
"name": "minitest-pretty_diff",
|
||||
"requirements": "~> 0.1"
|
||||
},
|
||||
{
|
||||
"name": "rake",
|
||||
"requirements": "~> 10.0"
|
||||
},
|
||||
{
|
||||
"name": "rdoc",
|
||||
"requirements": "~> 4.0"
|
||||
},
|
||||
{
|
||||
"name": "simplecov",
|
||||
"requirements": "~> 0.7"
|
||||
}
|
||||
],
|
||||
"runtime": []
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
want: "foo",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "fetchGitRepositoryFromNPM_error",
|
||||
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
result: "foo",
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty project url",
|
||||
//nolint
|
||||
args: args{
|
||||
packageName: "npm-package",
|
||||
//nolint
|
||||
result: `
|
||||
{
|
||||
"name": "color",
|
||||
"downloads": 8177801,
|
||||
"version": "1.8",
|
||||
"version_created_at": "2015-10-26T05:03:11.976Z",
|
||||
"version_downloads": 4558362,
|
||||
"platform": "ruby",
|
||||
"authors": "Austin Ziegler, Matt Lyon",
|
||||
"info": "Color is a Ruby library to provide basic RGB, CMYK, HSL, and other colourspace\nmanipulation support to applications that require it. It also provides 152\nnamed RGB colours (184 with spelling variations) that are commonly supported in\nHTML, SVG, and X11 applications. A technique for generating monochromatic\ncontrasting palettes is also included.\n\nThe Color library performs purely mathematical manipulation of the colours\nbased on colour theory without reference to colour profiles (such as sRGB or\nAdobe RGB). For most purposes, when working with RGB and HSL colour spaces,\nthis won't matter. Absolute colour spaces (like CIE L*a*b* and XYZ) and cannot\nbe reliably converted to relative colour spaces (like RGB) without colour\nprofiles.\n\nColor 1.8 adds an alpha parameter to all <tt>#css_rgba</tt> calls, fixes a bug\nexposed by new constant lookup semantics in Ruby 2, and ensures that\n<tt>Color.equivalent?</tt> can only be called on Color instances.\n\nBarring bugs introduced in this release, this (really) is the last version of\ncolor that supports Ruby 1.8, so make sure that your gem specification is set\nproperly (to <tt>~> 1.8</tt>) if that matters for your application. This\nversion will no longer be supported one year after the release of color 2.0.",
|
||||
"licenses": [
|
||||
"MIT"
|
||||
],
|
||||
"metadata": {},
|
||||
"yanked": false,
|
||||
"sha": "0a8512ecf6a8fe14928707f7d2766680c955b3a2224de198c1e25c837cd36f82",
|
||||
"project_uri": "https://rubygems.org/gems/color",
|
||||
"gem_uri": "https://rubygems.org/gems/color-1.8.gem",
|
||||
"homepage_uri": "https://github.com/halostatue/color",
|
||||
"wiki_uri": null,
|
||||
"documentation_uri": "https://www.rubydoc.info/gems/color/1.8",
|
||||
"mailing_list_uri": null,
|
||||
"source_code_uri": "",
|
||||
"bug_tracker_uri": null,
|
||||
"changelog_uri": null,
|
||||
"funding_uri": null,
|
||||
"dependencies": {
|
||||
"development": [
|
||||
{
|
||||
"name": "hoe",
|
||||
"requirements": "~> 3.14"
|
||||
},
|
||||
{
|
||||
"name": "hoe-doofus",
|
||||
"requirements": "~> 1.0"
|
||||
},
|
||||
{
|
||||
"name": "hoe-gemspec2",
|
||||
"requirements": "~> 1.1"
|
||||
},
|
||||
{
|
||||
"name": "hoe-git",
|
||||
"requirements": "~> 1.6"
|
||||
},
|
||||
{
|
||||
"name": "hoe-travis",
|
||||
"requirements": "~> 1.2"
|
||||
},
|
||||
{
|
||||
"name": "minitest",
|
||||
"requirements": "~> 5.8"
|
||||
},
|
||||
{
|
||||
"name": "minitest-around",
|
||||
"requirements": "~> 0.3"
|
||||
},
|
||||
{
|
||||
"name": "minitest-autotest",
|
||||
"requirements": "~> 1.0"
|
||||
},
|
||||
{
|
||||
"name": "minitest-bisect",
|
||||
"requirements": "~> 1.2"
|
||||
},
|
||||
{
|
||||
"name": "minitest-focus",
|
||||
"requirements": "~> 1.1"
|
||||
},
|
||||
{
|
||||
"name": "minitest-moar",
|
||||
"requirements": "~> 0.0"
|
||||
},
|
||||
{
|
||||
"name": "minitest-pretty_diff",
|
||||
"requirements": "~> 0.1"
|
||||
},
|
||||
{
|
||||
"name": "rake",
|
||||
"requirements": "~> 10.0"
|
||||
},
|
||||
{
|
||||
"name": "rdoc",
|
||||
"requirements": "~> 4.0"
|
||||
},
|
||||
{
|
||||
"name": "simplecov",
|
||||
"requirements": "~> 0.7"
|
||||
}
|
||||
],
|
||||
"runtime": []
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctrl := gomock.NewController(t)
|
||||
p := mockrepo.NewMockpackageManagerClient(ctrl)
|
||||
p.EXPECT().Get(gomock.Any(), tt.args.packageName).
|
||||
DoAndReturn(func(url, packageName string) (*http.Response, error) {
|
||||
if tt.wantErr && tt.args.result == "" {
|
||||
//nolint
|
||||
return nil, errors.New("error")
|
||||
}
|
||||
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(tt.args.result)),
|
||||
}, nil
|
||||
}).AnyTimes()
|
||||
got, err := fetchGitRepositoryFromRubyGems(tt.args.packageName, p)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("fetchGitRepositoryFromRubyGems() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("fetchGitRepositoryFromRubyGems() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
23
cmd/packagemanager_client.go
Normal file
23
cmd/packagemanager_client.go
Normal file
@ -0,0 +1,23 @@
|
||||
// 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 cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type packageManagerClient interface {
|
||||
Get(URI string, packagename string) (*http.Response, error)
|
||||
}
|
17
cmd/root.go
17
cmd/root.go
@ -19,9 +19,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/release-utils/version"
|
||||
@ -71,10 +73,23 @@ func New(o *options.Options) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
type packageManager struct{}
|
||||
|
||||
// nolint: noctx
|
||||
func (c *packageManager) Get(url, packageName string) (*http.Response, error) {
|
||||
const timeout = 10
|
||||
client := &http.Client{
|
||||
Timeout: timeout * time.Second,
|
||||
}
|
||||
//nolint
|
||||
return client.Get(fmt.Sprintf(url, packageName))
|
||||
}
|
||||
|
||||
// rootCmd runs scorecard checks given a set of arguments.
|
||||
func rootCmd(o *options.Options) {
|
||||
p := &packageManager{}
|
||||
// Set `repo` from package managers.
|
||||
pkgResp, err := fetchGitRepositoryFromPackageManagers(o.NPM, o.PyPI, o.RubyGems)
|
||||
pkgResp, err := fetchGitRepositoryFromPackageManagers(o.NPM, o.PyPI, o.RubyGems, p)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user