From d4dc6404b18225d3011c44d854545cf4468a8b87 Mon Sep 17 00:00:00 2001 From: Raghav Kaul Date: Tue, 19 Mar 2024 00:09:01 +0000 Subject: [PATCH 1/5] Add ProjectPackageClient interface and deps.dev default client Signed-off-by: Raghav Kaul --- clients/depsdev.go | 89 +++++++++++++++++++++++++++++++++++++++++++++ e2e/depsdev_test.go | 55 ++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 clients/depsdev.go create mode 100644 e2e/depsdev_test.go diff --git a/clients/depsdev.go b/clients/depsdev.go new file mode 100644 index 00000000000..54633dab9d9 --- /dev/null +++ b/clients/depsdev.go @@ -0,0 +1,89 @@ +// Copyright 2024 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 clients + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" +) + +// This interface lets Scorecard look up package manager metadata for a project. +type ProjectPackageClient interface { + GetProjectPackageVersions(ctx context.Context, host, project string) (*ProjectPackageVersions, error) +} + +type depsDevClient struct { + client *http.Client +} + +type ProjectPackageVersions struct { + // field alignment + //nolint:govet + Versions []struct { + VersionKey struct { + System string `json:"system"` + Name string `json:"name"` + Version string `json:"version"` + } `json:"versionKey"` + SLSAProvenances []struct { + SourceRepository string `json:"sourceRepository"` + Commit string `json:"commit"` + Verified bool `json:"verified"` + } `json:"slsaProvenances"` + RelationType string `json:"relationType"` + RelationProvenance string `json:"relationProvenance"` + } `json:"versions"` +} + +func CreateDepsDevClient() ProjectPackageClient { + return depsDevClient{ + client: &http.Client{}, + } +} + +func (d depsDevClient) GetProjectPackageVersions( + ctx context.Context, host, project string, +) (*ProjectPackageVersions, error) { + path := fmt.Sprintf("%s/%s", host, project) + query := fmt.Sprintf("https://api.deps.dev/v3/projects/%s:packageversions", url.QueryEscape(path)) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, query, nil) + if err != nil { + return nil, fmt.Errorf("http.NewRequestWithContext: %w", err) + } + + resp, err := d.client.Do(req) + if err != nil { + return nil, fmt.Errorf("deps.dev GetProjectPackageVersions: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("resp.Body.Read: %w", err) + } + + var res ProjectPackageVersions + err = json.Unmarshal(body, &res) + if err != nil { + return nil, fmt.Errorf("json.Unmarshal from deps.dev: %w", err) + } + + return &res, nil +} diff --git a/e2e/depsdev_test.go b/e2e/depsdev_test.go new file mode 100644 index 00000000000..966ce86a53f --- /dev/null +++ b/e2e/depsdev_test.go @@ -0,0 +1,55 @@ +// Copyright 2024 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 e2e + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/ossf/scorecard/v4/clients" +) + +var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { + var client clients.ProjectPackageClient + + Context("E2E TEST: Confirm ProjectPackageClient works", func() { + It("Should receive a non-empty response from deps.dev for existing projects", func() { + client = clients.CreateDepsDevClient() + versions, err := client.GetProjectPackageVersions( + context.Background(), "github.com", "ossf/scorecard", + ) + Expect(err).Should(BeNil()) + Expect(len(versions.Versions)).Should(BeNumerically(">", 0)) + }) + It("Should error from deps.dev for nonexistent projects", func() { + client = clients.CreateDepsDevClient() + versions, err := client.GetProjectPackageVersions( + context.Background(), "github.com", "ossf/scorecard-E2E-TEST-DOES-NOT-EXIST", + ) + Expect(err).ShouldNot(BeNil()) + Expect(versions).Should(BeNil()) + }) + It("Should receive a non-empty response from deps.dev for existing projects", func() { + client = clients.CreateDepsDevClient() + versions, err := client.GetProjectPackageVersions( + context.Background(), "gitlab.com", "libtiff/libtiff", + ) + Expect(err).Should(BeNil()) + Expect(len(versions.Versions)).Should(BeNumerically(">", 0)) + }) + }) +}) From 5f1f4b200394e08b43648492460366c8b9d0789f Mon Sep 17 00:00:00 2001 From: Raghav Kaul Date: Tue, 16 Apr 2024 23:01:47 +0000 Subject: [PATCH 2/5] v4 -> v5 Signed-off-by: Raghav Kaul --- e2e/depsdev_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/depsdev_test.go b/e2e/depsdev_test.go index 966ce86a53f..750c55c82f3 100644 --- a/e2e/depsdev_test.go +++ b/e2e/depsdev_test.go @@ -20,7 +20,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/ossf/scorecard/v4/clients" + "github.com/ossf/scorecard/v5/clients" ) var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { From b71528f146f4f0d634883b0c23a4ca06a026b415 Mon Sep 17 00:00:00 2001 From: Raghav Kaul Date: Wed, 8 May 2024 18:18:08 +0000 Subject: [PATCH 3/5] Move to internal Signed-off-by: Raghav Kaul --- clients/{ => internal}/depsdev.go | 2 +- {e2e => clients/internal}/depsdev_test.go | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) rename clients/{ => internal}/depsdev.go (99%) rename {e2e => clients/internal}/depsdev_test.go (88%) diff --git a/clients/depsdev.go b/clients/internal/depsdev.go similarity index 99% rename from clients/depsdev.go rename to clients/internal/depsdev.go index 54633dab9d9..933e3d9fc63 100644 --- a/clients/depsdev.go +++ b/clients/internal/depsdev.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package clients +package internal import ( "context" diff --git a/e2e/depsdev_test.go b/clients/internal/depsdev_test.go similarity index 88% rename from e2e/depsdev_test.go rename to clients/internal/depsdev_test.go index 750c55c82f3..ced7becb4e7 100644 --- a/e2e/depsdev_test.go +++ b/clients/internal/depsdev_test.go @@ -12,23 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -package e2e +package internal import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - - "github.com/ossf/scorecard/v5/clients" ) var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { - var client clients.ProjectPackageClient + var client ProjectPackageClient Context("E2E TEST: Confirm ProjectPackageClient works", func() { It("Should receive a non-empty response from deps.dev for existing projects", func() { - client = clients.CreateDepsDevClient() + client = CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "github.com", "ossf/scorecard", ) @@ -36,7 +34,7 @@ var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { Expect(len(versions.Versions)).Should(BeNumerically(">", 0)) }) It("Should error from deps.dev for nonexistent projects", func() { - client = clients.CreateDepsDevClient() + client = CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "github.com", "ossf/scorecard-E2E-TEST-DOES-NOT-EXIST", ) @@ -44,7 +42,7 @@ var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { Expect(versions).Should(BeNil()) }) It("Should receive a non-empty response from deps.dev for existing projects", func() { - client = clients.CreateDepsDevClient() + client = CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "gitlab.com", "libtiff/libtiff", ) From 14d6ab5f313c6511d6624068f4d2a8a7ea12472b Mon Sep 17 00:00:00 2001 From: Raghav Kaul Date: Wed, 8 May 2024 19:58:26 +0000 Subject: [PATCH 4/5] move internal to higher-level w/ shared root Signed-off-by: Raghav Kaul --- {clients/internal => internal/packageclient}/depsdev.go | 2 +- {clients/internal => internal/packageclient}/depsdev_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {clients/internal => internal/packageclient}/depsdev.go (99%) rename {clients/internal => internal/packageclient}/depsdev_test.go (98%) diff --git a/clients/internal/depsdev.go b/internal/packageclient/depsdev.go similarity index 99% rename from clients/internal/depsdev.go rename to internal/packageclient/depsdev.go index 933e3d9fc63..b816296c2fc 100644 --- a/clients/internal/depsdev.go +++ b/internal/packageclient/depsdev.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package internal +package packageclient import ( "context" diff --git a/clients/internal/depsdev_test.go b/internal/packageclient/depsdev_test.go similarity index 98% rename from clients/internal/depsdev_test.go rename to internal/packageclient/depsdev_test.go index ced7becb4e7..805d38fed7c 100644 --- a/clients/internal/depsdev_test.go +++ b/internal/packageclient/depsdev_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package internal +package packageclient import ( "context" From b3eee3b83ce38ace5249a6a0a4489a6abb8e5249 Mon Sep 17 00:00:00 2001 From: Raghav Kaul Date: Wed, 8 May 2024 20:33:15 +0000 Subject: [PATCH 5/5] update Signed-off-by: Raghav Kaul --- {internal/packageclient => e2e}/depsdev_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) rename {internal/packageclient => e2e}/depsdev_test.go (87%) diff --git a/internal/packageclient/depsdev_test.go b/e2e/depsdev_test.go similarity index 87% rename from internal/packageclient/depsdev_test.go rename to e2e/depsdev_test.go index 805d38fed7c..00323bf0781 100644 --- a/internal/packageclient/depsdev_test.go +++ b/e2e/depsdev_test.go @@ -12,21 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -package packageclient +package e2e import ( "context" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + "github.com/ossf/scorecard/v5/internal/packageclient" ) var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { - var client ProjectPackageClient + var client packageclient.ProjectPackageClient Context("E2E TEST: Confirm ProjectPackageClient works", func() { It("Should receive a non-empty response from deps.dev for existing projects", func() { - client = CreateDepsDevClient() + client = packageclient.CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "github.com", "ossf/scorecard", ) @@ -34,7 +36,7 @@ var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { Expect(len(versions.Versions)).Should(BeNumerically(">", 0)) }) It("Should error from deps.dev for nonexistent projects", func() { - client = CreateDepsDevClient() + client = packageclient.CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "github.com", "ossf/scorecard-E2E-TEST-DOES-NOT-EXIST", ) @@ -42,7 +44,7 @@ var _ = Describe("E2E TEST: depsdevclient.GetProjectPackageVersions", func() { Expect(versions).Should(BeNil()) }) It("Should receive a non-empty response from deps.dev for existing projects", func() { - client = CreateDepsDevClient() + client = packageclient.CreateDepsDevClient() versions, err := client.GetProjectPackageVersions( context.Background(), "gitlab.com", "libtiff/libtiff", )