Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ add --nuget package manager flag #3020

Merged
Merged
Show file tree
Hide file tree
Changes from 124 commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
1ae5016
add nuget package manager
balteravishay May 16, 2023
5d7efcf
fix pat test messages (#2987)
raghavkaul May 10, 2023
bd90f2a
:seedling: Bump slsa-framework/slsa-github-generator from 1.5.0 to 1.6.0
dependabot[bot] May 11, 2023
9457c6b
:seedling: Bump cloud.google.com/go/bigquery from 1.51.1 to 1.51.2 (#…
dependabot[bot] May 11, 2023
8d33096
:seedling: Bump golang.org/x/tools from 0.9.0 to 0.9.1
dependabot[bot] May 11, 2023
bf91591
:bug: Update osv-scanner dependency to include Vulnerabilities check …
laurentS May 11, 2023
bf477b3
:seedling: Bump github.com/docker/distribution in /tools (#2993)
dependabot[bot] May 11, 2023
e723862
🌱 Gitlab: e2e test fixes in main (#2992)
raghavkaul May 11, 2023
be0c93a
:seedling: Unit tests log/log.go (#2980)
naveensrinivasan May 11, 2023
79727dc
:seedling: Bump github.com/cloudflare/circl in /tools (#2995)
dependabot[bot] May 12, 2023
9a35527
:sparkles: Add releasing workflow for semantic-release (#2989)
travi May 12, 2023
8230512
:seedling: Bump slsa-framework/slsa-verifier from 2.2.0 to 2.3.0
dependabot[bot] May 12, 2023
ab84d92
:seedling: Bump github.com/cloudflare/circl from 1.1.0 to 1.3.3 (#2994)
dependabot[bot] May 12, 2023
6575af0
:seedling: Additional e2e clients/githubrepo/checkruns.go (#2934)
naveensrinivasan May 13, 2023
256822d
:seedling: E2E for clients/githubrepo/contributors.go (#2939)
naveensrinivasan May 13, 2023
33094e9
:book: Clarify that AI/ML doesn't count as human code review (#2953)
david-a-wheeler May 14, 2023
3173415
:seedling: Bump golang from `31a8f92` to `685a22e` in /cron/internal/cii
dependabot[bot] May 15, 2023
c0fc01c
:seedling: Bump golang in /cron/internal/controller
dependabot[bot] May 15, 2023
157867f
:seedling: Bump golang in /cron/internal/worker
dependabot[bot] May 15, 2023
0094ff3
:seedling: Bump golang in /clients/githubrepo/roundtripper/tokens/server
dependabot[bot] May 15, 2023
6c981cd
:seedling: Bump golang from `31a8f92` to `685a22e`
dependabot[bot] May 15, 2023
f540afc
:seedling: Bump golang from `31a8f92` to `685a22e` in /cron/internal/bq
dependabot[bot] May 15, 2023
86613ea
:seedling: Bump golang in /cron/internal/webhook
dependabot[bot] May 15, 2023
1b0d674
Clarify AI/ML not human code review - in .yml file (#3012)
david-a-wheeler May 15, 2023
342c0d8
:seedling: Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 (#3005)
dependabot[bot] May 15, 2023
71d3fc8
:seedling: Unit tests for checks/raw/maintained.go (#2996)
naveensrinivasan May 15, 2023
519d99e
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.4 to 2.9.5 in /tools
dependabot[bot] May 16, 2023
ae5b8a9
:seedling: Bump actions/setup-go from 4.0.0 to 4.0.1
dependabot[bot] May 16, 2023
f41be31
:seedling: Bump codecov/codecov-action from 3.1.3 to 3.1.4
dependabot[bot] May 16, 2023
d2c32cf
:seedling: Unit tests for Policy.go (#3003)
naveensrinivasan May 16, 2023
bd7ebc4
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.4 to 2.9.5
dependabot[bot] May 17, 2023
1ea3461
:seedling: Bump sigstore/cosign-installer from 3.0.3 to 3.0.4
dependabot[bot] May 17, 2023
f8815b2
:seedling: Bump github.com/google/go-containerregistry (#3025)
dependabot[bot] May 17, 2023
82c672c
:seedling: Bump github.com/sirupsen/logrus from 1.9.0 to 1.9.1
dependabot[bot] May 17, 2023
21f3338
:seedling: Included e2e tests for push to main (#2951)
naveensrinivasan May 17, 2023
c621e04
:seedling: Included directories that don't require coverage (#3002)
naveensrinivasan May 17, 2023
dac89b7
:seedling: Unit tests for checks/raw/contributors.go (#2998)
naveensrinivasan May 17, 2023
a164f60
✨ GitLab: Code Review check (#2764)
raghavkaul May 17, 2023
fb0a542
gitlab: license check (#2834)
raghavkaul May 17, 2023
fb9628e
:seedling: Bump github.com/sirupsen/logrus from 1.9.1 to 1.9.2 (#3031)
dependabot[bot] May 18, 2023
022b863
:seedling: Bump github.com/google/osv-scanner
dependabot[bot] May 18, 2023
f226172
:seedling: Bump sigstore/cosign-installer from 3.0.4 to 3.0.5 (#3029)
dependabot[bot] May 18, 2023
6206d05
:seedling: Bump arduino/setup-protoc from 1.1.2 to 1.2.0
dependabot[bot] May 18, 2023
9a31ad8
:sparkles: Add support for github GHES (#2999)
patelniketm May 18, 2023
dfe4b2d
Change Facilitators to Maintainers (#3039)
jeffmendoza May 18, 2023
5a9803e
:bug: Gitlab: Commit/Commitor Exceptions (#3026)
jimrobison May 19, 2023
f048afa
:seedling: Bump github.com/onsi/gomega from 1.27.6 to 1.27.7 (#3040)
dependabot[bot] May 19, 2023
e168089
:book: Make all StepSecurity app endpoint references consistent (#3042)
ashishkurmi May 19, 2023
8a01a8d
📖 Update checks.md to show the benefit of >=2 reviewers (#3013)
joycebrum May 19, 2023
8a0e9d7
:seedling: Improve workflow pinning remediation tests (#3021)
naveensrinivasan May 22, 2023
73feed8
:seedling: E2E tests for clients/githubrepo/languages_e2e_test.go (#3…
naveensrinivasan May 22, 2023
a9b6650
:seedling: Unit tests for pkg/json_raw_results (#3044)
naveensrinivasan May 22, 2023
7ddbece
✨ [experimental] Add probe code and support for Tool-Update-Dependen…
laurentsimon May 23, 2023
c29689d
add zoom link and agenda link (#3050)
hythloda May 23, 2023
109989f
:seedling: Run E2E PAT test for push to main (#3046)
naveensrinivasan May 23, 2023
1ea0325
Update main.yml (#3054)
naveensrinivasan May 23, 2023
2b68f39
only run e2e pat on push (#3056)
spencerschrock May 24, 2023
90c478b
:seedling: Bump github.com/go-git/go-git/v5 from 5.6.1 to 5.7.0 (#3057)
dependabot[bot] May 24, 2023
4cabadc
:book: :ghost: fix anchor link to the code review section (#3058)
dasfreak May 24, 2023
71726e1
🐛 Gitlab: Tests (#3027)
raghavkaul May 24, 2023
4887d43
:seedling: Bump github.com/goreleaser/nfpm/v2 in /tools (#3060)
dependabot[bot] May 24, 2023
11086a5
✨ Gitlab: Add projects to cron (#2936)
raghavkaul May 24, 2023
ea5ae54
:seedling: Simplify caching in docker workflow (#3061)
spencerschrock May 24, 2023
6e0e3cd
:seedling: Bump github/codeql-action from 2.3.3 to 2.3.4 (#3064)
dependabot[bot] May 25, 2023
229291c
:seedling: Bump cloud.google.com/go/pubsub from 1.30.1 to 1.31.0 (#3065)
dependabot[bot] May 25, 2023
c49f444
🐛 gitlab: cron (#3070)
raghavkaul May 25, 2023
7106659
:seedling: Bump github/codeql-action from 2.3.4 to 2.3.5 (#3072)
dependabot[bot] May 26, 2023
f343f36
:seedling: Bump tj-actions/changed-files from 35.9.2 to 36.0.3 (#3071)
dependabot[bot] May 26, 2023
ae8d092
🐛 Gitlab status updates (#3052)
jimrobison May 26, 2023
e99e4ed
:seedling: Bump github.com/sigstore/rekor from 1.1.1 to 1.2.0 in /too…
dependabot[bot] May 27, 2023
b13a8d0
get nuget latest version from registration URL
balteravishay May 28, 2023
2533a2c
better coverage
balteravishay May 29, 2023
82d5ea8
sign
balteravishay May 29, 2023
8074043
fix tests
balteravishay May 29, 2023
aa6b39b
more tests
balteravishay May 29, 2023
5d5d0a0
client tests
balteravishay May 29, 2023
9cf1ad8
lint
balteravishay May 29, 2023
fe2d2b7
Apply suggestions from code review
balteravishay May 30, 2023
3d25365
:seedling: Bump golang from `685a22e` to `690e413` (#3080)
dependabot[bot] May 29, 2023
0479f90
:seedling: Bump golang from `685a22e` to `690e413` in /cron/internal/cii
dependabot[bot] May 29, 2023
cffa031
:seedling: Bump golang in /cron/internal/controller
dependabot[bot] May 29, 2023
3503098
:seedling: Bump golang in /cron/internal/worker
dependabot[bot] May 29, 2023
de55482
:seedling: Bump golang in /clients/githubrepo/roundtripper/tokens/server
dependabot[bot] May 29, 2023
173b36d
:seedling: Bump golang in /cron/internal/webhook
dependabot[bot] May 29, 2023
c7d7be6
:seedling: Bump golang from `685a22e` to `690e413` in /cron/internal/bq
dependabot[bot] May 30, 2023
ac19c49
:seedling: Bump arduino/setup-protoc from 1.2.0 to 1.3.0 (#3089)
dependabot[bot] May 30, 2023
c4c24cc
:seedling: Bump tj-actions/changed-files from 36.0.3 to 36.0.9 (#3088)
dependabot[bot] May 30, 2023
e3eaabf
pr iteration 2
balteravishay May 31, 2023
12ad52e
pr iteration 3
balteravishay Jun 1, 2023
ca3f9f5
switch security policy e2e test to ossf-tests repo. (#3090)
spencerschrock May 31, 2023
fbac2db
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.5 to 2.9.7 in /too…
dependabot[bot] May 31, 2023
c01ce9e
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.5 to 2.9.7 (#3093)
dependabot[bot] May 31, 2023
a96e6d7
:seedling: Bump actions/dependency-review-action from 3.0.4 to 3.0.6 …
dependabot[bot] Jun 1, 2023
ce38745
:seedling: Bump tj-actions/changed-files from 36.0.9 to 36.0.12 (#3108)
dependabot[bot] Jun 1, 2023
528535c
:seedling: Bump github.com/xanzy/go-gitlab from 0.83.0 to 0.84.0 (#3106)
dependabot[bot] Jun 1, 2023
66d0c33
:seedling: Bump golang.org/x/tools from 0.9.1 to 0.9.2
dependabot[bot] Jun 1, 2023
b6c6846
✨ GitLab: enable more checks in cron (#3097)
raghavkaul Jun 1, 2023
8c90426
:book: agenda link change (#3111)
hythloda Jun 1, 2023
fdda440
:seedling: Bump github/codeql-action from 2.3.5 to 2.3.6 (#3112)
dependabot[bot] Jun 2, 2023
581fd85
:seedling: Bump tj-actions/changed-files from 36.0.12 to 36.0.15 (#3116)
dependabot[bot] Jun 2, 2023
c1f38ae
:seedling: Bump golang.org/x/tools from 0.9.2 to 0.9.3
dependabot[bot] Jun 2, 2023
c88ae03
:seedling: Unit tests for option (#3109)
naveensrinivasan Jun 2, 2023
050f373
🌱 GitLab: add gitlab auth token to cron worker env (#3117)
raghavkaul Jun 2, 2023
e8bc0ce
Don't run pat e2e on dependabot merges (#3119)
raghavkaul Jun 3, 2023
8222dbe
✨ Detect fast-check PBT library for fuzz section (#3073)
dubzzz Jun 4, 2023
1c54bd3
:seedling: temporarily disable failing e2e tests so we don't block al…
spencerschrock Jun 6, 2023
94aa7ff
pr comments
balteravishay Jun 11, 2023
08d6f6c
:seedling: Bump github.com/sirupsen/logrus from 1.9.2 to 1.9.3 (#3121)
dependabot[bot] Jun 7, 2023
3e0d6f3
i:seedling: Ignore all pb files for test (#3127)
naveensrinivasan Jun 7, 2023
ab13c32
:seedling: Deprecate dependencydiff package and add access token requ…
naveensrinivasan Jun 7, 2023
2330e72
✨ [experimental] Support for new `--format probe` (#3048)
laurentsimon Jun 7, 2023
4630eb2
:seedling: Bump distroless/base (#3122)
dependabot[bot] Jun 7, 2023
5bde964
:seedling: Ignore deprecation warning for dependencydiff tests. (#3136)
spencerschrock Jun 7, 2023
f8fca32
:seedling: Bump tj-actions/changed-files from 36.0.15 to 36.0.18
dependabot[bot] Jun 8, 2023
9a1108c
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.7 to 2.10.0 in /to…
dependabot[bot] Jun 8, 2023
fda3e29
:seedling: Bump github.com/google/osv-scanner from 1.3.3 to 1.3.4
dependabot[bot] Jun 8, 2023
5ebc489
:seedling: Bump github.com/onsi/ginkgo/v2 from 2.9.7 to 2.10.0
dependabot[bot] Jun 8, 2023
c89cb24
:seedling: Bump github.com/onsi/gomega from 1.27.7 to 1.27.8
dependabot[bot] Jun 8, 2023
943e447
:seedling: Bump slsa-framework/slsa-github-generator from 1.6.0 to 1.…
dependabot[bot] Jun 8, 2023
db069a4
:seedling: Increase test coverage for finding outcomes (#3142)
naveensrinivasan Jun 8, 2023
48171a8
:seedling: Bump tj-actions/changed-files from 36.0.18 to 36.1.0 (#3143)
dependabot[bot] Jun 9, 2023
a5332ec
:seedling: Re-enable skipped e2e tests. Switch to smaller code review…
spencerschrock Jun 9, 2023
b65e463
Merge branch 'main' into avbalter/support-nuget-package-manager
balteravishay Jun 11, 2023
6d24d1b
add license header
balteravishay Jun 11, 2023
5afadc6
pr comments
balteravishay Jun 14, 2023
390806f
Merge branch 'main' into avbalter/support-nuget-package-manager
balteravishay Jun 14, 2023
dc3049c
making the packages internal
balteravishay Jun 15, 2023
94860aa
generate mocks
balteravishay Jun 15, 2023
aad8ef0
Merge branch 'main' into avbalter/support-nuget-package-manager
spencerschrock Jun 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ scorecard --repo=org/repo

##### Using a Package manager

For projects in the `--npm`, `--pypi`, or `--rubygems` ecosystems, you have the
For projects in the `--npm`, `--pypi`, `--rubygems`, or `--nuget` ecosystems, you have the
option to run Scorecard using a package manager. Provide the package name to
run the checks on the corresponding GitHub source code.

Expand Down
278 changes: 278 additions & 0 deletions cmd/nuget.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
// Copyright 2020 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 cmd implements Scorecard commandline.
package cmd

import (
"encoding/json"
"encoding/xml"
"fmt"
"regexp"
"strings"

"golang.org/x/exp/slices"

sce "github.com/ossf/scorecard/v4/errors"
)

type nugetClient struct {
manager packageManagerClient
}

type nugetIndexResult struct {
ID string `json:"@id"`
Type string `json:"@type"`
}

type nugetIndexResults struct {
Resources []nugetIndexResult `json:"resources"`
}

func (n nugetIndexResults) getFieldFromIndexResults(resultType string) (string, error) {
balteravishay marked this conversation as resolved.
Show resolved Hide resolved
resourceIndex := slices.IndexFunc(n.Resources,
func(n nugetIndexResult) bool { return n.Type == resultType })
if resourceIndex == -1 {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to find %v URI at nuget index json", resultType))
}

return n.Resources[resourceIndex].ID, nil
}

type nugetPackageRegistrationCatalogRoot struct {
Pages []nugetPackageRegistrationCatalogPage `json:"items"`
}

func (n nugetPackageRegistrationCatalogRoot) LatestVersion(manager packageManagerClient) (string, error) {
for pageIndex := len(n.Pages) - 1; pageIndex >= 0; pageIndex-- {
page := n.Pages[pageIndex]
if page.Packages == nil {
respPage, err := manager.GetURI(page.ID)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to get nuget package registration page: %v", err))
}
defer respPage.Body.Close()
err = json.NewDecoder(respPage.Body).Decode(&page)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to parse nuget package registration page: %v", err))
}
}
for packageIndex := len(page.Packages) - 1; packageIndex >= 0; packageIndex-- {
base, preReleaseSuffix := getNugetSemVer(page.Packages[packageIndex].Entry.Version)
// skipping non listed and pre-releases
if page.Packages[packageIndex].Entry.Listed && len(strings.TrimSpace(preReleaseSuffix)) == 0 {
return base, nil
}
}
}
return "", sce.WithMessage(sce.ErrScorecardInternal, "failed to get a listed version for package")
}

type nugetPackageRegistrationCatalogPage struct {
ID string `json:"@id"`
Packages []nugetPackageRegistrationPackage `json:"items"`
}

type nugetPackageRegistrationPackage struct {
Entry nugetPackageRegistrationCatalogEntry `json:"catalogEntry"`
}

type nugetPackageRegistrationCatalogEntry struct {
Version string `json:"version"`
Listed bool `json:"listed"`
}

func (e *nugetPackageRegistrationCatalogEntry) UnmarshalJSON(text []byte) error {
type Alias nugetPackageRegistrationCatalogEntry
aux := Alias{
Listed: true, // set the default value before parsing JSON
}
if err := json.Unmarshal(text, &aux); err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to unmarshal json: %v", err))
}
*e = nugetPackageRegistrationCatalogEntry(aux)
return nil
}

type nugetNuspec struct {
XMLName xml.Name `xml:"package"`
Metadata nuspecMetadata `xml:"metadata"`
}

type nuspecMetadata struct {
XMLName xml.Name `xml:"metadata"`
ProjectURL string `xml:"projectUrl"`
Repository nuspecRepository `xml:"repository"`
}

type nuspecRepository struct {
XMLName xml.Name `xml:"repository"`
URL string `xml:"url,attr"`
}

func (c *nugetClient) getPackageSpec(packageBaseURL, registrationBaseURL, packageName string) (nugetNuspec, error) {
lowerCasePackageName := strings.ToLower(packageName)
lastPackageVersion, err := getLatestListedVersion(registrationBaseURL,
lowerCasePackageName, c.manager)
if err != nil {
return nugetNuspec{}, err
}

respPackageSpec, err := c.manager.Get(
packageBaseURL+"%[1]v/"+lastPackageVersion+"/%[1]v.nuspec", lowerCasePackageName)
if err != nil {
return nugetNuspec{}, sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to get nuget package spec json: %v", err))
}
defer respPackageSpec.Body.Close()

packageSpecResults := &nugetNuspec{}
err = xml.NewDecoder(respPackageSpec.Body).Decode(packageSpecResults)
if err != nil {
return nugetNuspec{}, sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to parse nuget nuspec xml: %v", err))
}
if packageSpecResults.Metadata == (nuspecMetadata{}) {
return nugetNuspec{}, sce.WithMessage(sce.ErrScorecardInternal,
"Nuget nuspec xml Metadata is empty")
}

return *packageSpecResults, nil
}

func getProjectURLFromPackageSpec(p *nugetNuspec, packageName string) (string, error) {
var projectURL string
if strings.TrimSpace(p.Metadata.Repository.URL) != "" {
projectURL = p.Metadata.Repository.URL
}
if strings.TrimSpace(p.Metadata.ProjectURL) != "" {
projectURL = p.Metadata.ProjectURL
}
if isSupportedProjectURL(projectURL) {
return strings.TrimSuffix(projectURL, ".git"), nil
}
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("source repo is not defined for nuget package %v", packageName))
}

func (c *nugetClient) fetchGitRepositoryForPackage(packageName string) (string, error) {
nugetPackageBaseURL, nugetRegistrationBaseURL, err := c.getNugetBaseUrls()
if err != nil {
return "", err
}

packageSpec, err := c.getPackageSpec(nugetPackageBaseURL, nugetRegistrationBaseURL, packageName)
if err != nil {
return "", err
}
packageURL, err := getProjectURLFromPackageSpec(&packageSpec, packageName)
if err != nil {
return "", err
}
return packageURL, nil
}

func (c *nugetClient) getNugetBaseUrls() (string, string, error) {
nugetIndexURL := "https://api.nuget.org/v3/index.json"
respIndex, err := c.manager.GetURI(nugetIndexURL)
if err != nil {
return "", "", sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("failed to get nuget index json: %v", err))
}
defer respIndex.Body.Close()
nugetIndexResults := &nugetIndexResults{}
err = json.NewDecoder(respIndex.Body).Decode(nugetIndexResults)
if err != nil {
return "", "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to parse nuget index json: %v", err))
}
nugetPackageBaseURL, err := nugetIndexResults.getFieldFromIndexResults("PackageBaseAddress/3.0.0")
if err != nil {
return "", "", err
}
nugetRegistrationBaseURL, err := nugetIndexResults.getFieldFromIndexResults("RegistrationsBaseUrl/3.6.0")
if err != nil {
return "", "", err
}
return nugetPackageBaseURL, nugetRegistrationBaseURL, nil
}

func isSupportedProjectURL(projectURL string) bool {
pattern := `^(?:https?://)?(?:www\.)?(?:github|gitlab)\.com/([A-Za-z0-9_\.-]+)/([A-Za-z0-9_\./-]+)$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(projectURL)
}

// Gets the latest listed nuget version of a package, based on the protocol defined at
// https://learn.microsoft.com/en-us/nuget/api/package-base-address-resource#enumerate-package-versions
func getLatestListedVersion(baseURL, packageName string, manager packageManagerClient) (string, error) {
resPackageRegistrationIndex, err := manager.Get(baseURL+"%s/index.json", packageName)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to get nuget package registration index json: %v", err))
}
defer resPackageRegistrationIndex.Body.Close()
packageRegistrationCatalogRoot := &nugetPackageRegistrationCatalogRoot{}
err = json.NewDecoder(resPackageRegistrationIndex.Body).Decode(packageRegistrationCatalogRoot)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to parse package registration index json: %v", err))
}
return getLatestListedVersionFromPackageRegistrationPages(packageRegistrationCatalogRoot.Pages, manager)
}

func getLatestListedVersionFromPackageRegistrationPages(pages []nugetPackageRegistrationCatalogPage,
manager packageManagerClient,
) (string, error) {
for pageIndex := len(pages) - 1; pageIndex >= 0; pageIndex-- {
page := pages[pageIndex]
if page.Packages == nil {
respPage, err := manager.GetURI(page.ID)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to get nuget package registration page: %v", err))
}
defer respPage.Body.Close()
err = json.NewDecoder(respPage.Body).Decode(&page)
if err != nil {
return "", sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("failed to parse nuget package registration page: %v", err))
}
}
for packageIndex := len(page.Packages) - 1; packageIndex >= 0; packageIndex-- {
semVerString, preRelease := getNugetSemVer(page.Packages[packageIndex].Entry.Version)
// skipping non listed and pre-releases
if page.Packages[packageIndex].Entry.Listed && len(strings.TrimSpace(preRelease)) == 0 {
return semVerString, nil
}
}
}
return "", sce.WithMessage(sce.ErrScorecardInternal,
"failed to get a listed version for package")
}

// Nuget semver diverges from Semantic Versioning.
// This method returns the Nuget represntation of version and pre release strings.
// nolint: lll // long URL
// more info: https://learn.microsoft.com/en-us/nuget/concepts/package-versioning#where-nugetversion-diverges-from-semantic-versioning
func getNugetSemVer(versionString string) (base, preReleaseSuffix string) {
metadataAndVersion := strings.Split(versionString, "+")
prereleaseAndVersions := strings.Split(metadataAndVersion[0], "-")
if len(prereleaseAndVersions) == 1 {
return prereleaseAndVersions[0], ""
}
return prereleaseAndVersions[0], prereleaseAndVersions[1]
}
15 changes: 14 additions & 1 deletion cmd/package_managers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type packageMangerResponse struct {
exists bool
}

func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems string,
func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems, nuget string,
manager packageManagerClient,
) (packageMangerResponse, error) {
if npm != "" {
Expand All @@ -51,6 +51,13 @@ func fetchGitRepositoryFromPackageManagers(npm, pypi, rubygems string,
associatedRepo: gitRepo,
}, err
}
if nuget != "" {
gitRepo, err := fetchGitRepositoryFromNuget(nuget, manager)
return packageMangerResponse{
exists: true,
associatedRepo: gitRepo,
}, err
}

return packageMangerResponse{}, nil
}
Expand Down Expand Up @@ -138,3 +145,9 @@ func fetchGitRepositoryFromRubyGems(packageName string, manager packageManagerCl
}
return v.SourceCodeURI, nil
}

// Gets the GitHub repository URL for the nuget package.
func fetchGitRepositoryFromNuget(packageName string, manager packageManagerClient) (string, error) {
balteravishay marked this conversation as resolved.
Show resolved Hide resolved
nugetClient := &nugetClient{manager: manager}
return nugetClient.fetchGitRepositoryForPackage(packageName)
}
Loading