Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit727a942

Browse files
authored
GitHub: Dependency Submission API (#159)
1 parent2c47d29 commit727a942

File tree

14 files changed

+264
-36
lines changed

14 files changed

+264
-36
lines changed

‎README.md‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Currently supported providers are: [GitHub](#github), [Bitbucket Server](#bitbuc
7676
-[CommitAndPushFiles](#commit-and-push-files)
7777
-[Merge Pull Request](#merge-pull-request)
7878
-[Create Pull Request Detailed](#create-pull-request-detailed)
79+
-[Upload Snapshot To Dependency Graph](#upload-snapshot-to-dependency-graph)
7980
-[Webhook Parser](#webhook-parser)
8081

8182
###VCS Clients
@@ -1058,6 +1059,52 @@ description := "Pull request description"
10581059
prInfo,err := client.CreatePullRequestDetailed(ctx, owner, repository, sourceBranch, targetBranch, title, description)
10591060
```
10601061

1062+
####UploadSnapshotToDependencyGraph
1063+
1064+
Notice -UploadSnapshotToDependencyGraph is currently supported onGitHub only.
1065+
1066+
```go
1067+
// Go context
1068+
ctx := context.Background()
1069+
// Organization or username
1070+
owner := "jfrog"
1071+
// VCS repository
1072+
repository := "jfrog-cli"
1073+
// SBOM snapshot containing dependency information
1074+
snapshot := &vcsclient.SbomSnapshot{
1075+
Version: 0,
1076+
Sha: "5c05522fecf8d93a11752ff255c99fcb0f0557cd",
1077+
Ref: "refs/heads/main",
1078+
Job: &vcsclient.JobInfo{
1079+
Correlator: "job-correlator",
1080+
ID: "job-id",
1081+
},
1082+
Detector: &vcsclient.DetectorInfo{
1083+
Name: "detector-name",
1084+
Version: "1.0.0",
1085+
Url: "https://example.com/detector",
1086+
},
1087+
Scanned: time.Now(),
1088+
Manifests: map[string]*vcsclient.Manifest{
1089+
"package.json": {
1090+
Name: "package.json",
1091+
File: &vcsclient.FileInfo{
1092+
SourceLocation: "package.json",
1093+
},
1094+
Resolved: map[string]*vcsclient.ResolvedDependency{
1095+
"lodash": {
1096+
PackageURL: "pkg:npm/lodash@4.17.21",
1097+
Dependencies: []string{},
1098+
},
1099+
},
1100+
},
1101+
},
1102+
}
1103+
1104+
// Uploads the SBOM snapshot to the GitHub dependency graph tab
1105+
err := client.UploadSnapshotToDependencyGraph(ctx, owner, repository, snapshot)
1106+
```
1107+
10611108
###WebhookParser
10621109

10631110
```go

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.23.0
55
require (
66
github.com/gfleury/go-bitbucket-v1v0.0.0-20230825095122-9bc1711434ab
77
github.com/go-git/go-git/v5v5.16.0
8-
github.com/google/go-github/v56v56.0.0
8+
github.com/google/go-github/v62v62.0.0
99
github.com/google/uuidv1.6.0
1010
github.com/grokify/mogov0.64.12
1111
github.com/jfrog/gofrogv1.7.6

‎go.sum‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
4444
github.com/google/go-cmpv0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
4545
github.com/google/go-cmpv0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4646
github.com/google/go-cmpv0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
47-
github.com/google/go-github/v56v56.0.0 h1:TysL7dMa/r7wsQi44BjqlwaHvwlFlqkK8CtBWCX3gb4=
48-
github.com/google/go-github/v56v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0=
47+
github.com/google/go-github/v62v62.0.0 h1:/6mGCaRywZz9MuHyw9gD1CwsbmBX8GWsbFkwMmHdhl4=
48+
github.com/google/go-github/v62v62.0.0/go.mod h1:EMxeUqGJq2xRu9DYBMwel/mr7kZrzUOfQmmpYrZn2a4=
4949
github.com/google/go-querystringv1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
5050
github.com/google/go-querystringv1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
5151
github.com/google/uuidv1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

‎vcsclient/azurerepos.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,10 @@ func (client *AzureReposClient) CreatePullRequestDetailed(ctx context.Context, o
785785
returnCreatedPullRequestInfo{},getUnsupportedInAzureError("create pull request detailed")
786786
}
787787

788+
func (client*AzureReposClient)UploadSnapshotToDependencyGraph(ctx context.Context,owner,repostring,snapshot*SbomSnapshot)error {
789+
returngetUnsupportedInAzureError("uploading snapshot to dependency graph UI")
790+
}
791+
788792
funcparsePullRequestDetails(client*AzureReposClient,pullRequest git.GitPullRequest,owner,repositorystring,withBodybool)PullRequestInfo {
789793
// Trim the branches prefix and get the actual branches name
790794
shortSourceName:=plumbing.ReferenceName(*pullRequest.SourceRefName).Short()

‎vcsclient/bitbucketcloud.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,10 @@ func (client *BitbucketCloudClient) CreatePullRequestDetailed(ctx context.Contex
743743
returnCreatedPullRequestInfo{},errBitbucketCreatePullRequestDetailedNotSupported
744744
}
745745

746+
func (client*BitbucketCloudClient)UploadSnapshotToDependencyGraph(ctx context.Context,owner,repostring,snapshot*SbomSnapshot)error {
747+
returnerrBitbucketUploadSnapshotToDependencyGraphNotSupported
748+
}
749+
746750
typepullRequestsResponsestruct {
747751
Values []pullRequestsDetails`json:"values"`
748752
}

‎vcsclient/bitbucketcommon.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
errBitbucketMergePullRequestNotSupported=fmt.Errorf("merge pull request is %s",notSupportedOnBitbucket)
3636
errBitbucketListAppReposNotSupported=fmt.Errorf("list app repositories is %s",notSupportedOnBitbucket)
3737
errBitbucketCreatePullRequestDetailedNotSupported=fmt.Errorf("creating pull request detailed is %s",notSupportedOnBitbucket)
38+
errBitbucketUploadSnapshotToDependencyGraphNotSupported=fmt.Errorf("uploading snapshot to dependency graph UI is %s",notSupportedOnBitbucket)
3839
)
3940

4041
typeBitbucketCommitInfostruct {

‎vcsclient/bitbucketserver.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,10 @@ func (client *BitbucketServerClient) CreatePullRequestDetailed(ctx context.Conte
935935
returnCreatedPullRequestInfo{},errBitbucketCreatePullRequestDetailedNotSupported
936936
}
937937

938+
func (client*BitbucketServerClient)UploadSnapshotToDependencyGraph(ctx context.Context,owner,repostring,snapshot*SbomSnapshot)error {
939+
returnerrBitbucketUploadSnapshotToDependencyGraphNotSupported
940+
}
941+
938942
funcgetBitbucketServerRepositoryVisibility(publicbool)RepositoryVisibility {
939943
ifpublic {
940944
returnPublic

‎vcsclient/github.go‎

Lines changed: 93 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,8 @@ import (
44
"context"
55
"crypto/rand"
66
base64Utils"encoding/base64"
7-
"encoding/json"
87
"errors"
98
"fmt"
10-
"github.com/google/go-github/v56/github"
11-
"github.com/grokify/mogo/encoding/base64"
12-
"github.com/jfrog/froggit-go/vcsutils"
13-
"github.com/jfrog/gofrog/datastructures"
14-
"github.com/mitchellh/mapstructure"
15-
"golang.org/x/crypto/nacl/box"
16-
"golang.org/x/exp/slices"
17-
"golang.org/x/oauth2"
189
"io"
1910
"net/http"
2011
"net/url"
@@ -23,6 +14,15 @@ import (
2314
"strconv"
2415
"strings"
2516
"time"
17+
18+
"github.com/google/go-github/v62/github"
19+
"github.com/grokify/mogo/encoding/base64"
20+
"github.com/jfrog/froggit-go/vcsutils"
21+
"github.com/jfrog/gofrog/datastructures"
22+
"github.com/mitchellh/mapstructure"
23+
"golang.org/x/crypto/nacl/box"
24+
"golang.org/x/exp/slices"
25+
"golang.org/x/oauth2"
2626
)
2727

2828
const (
@@ -156,8 +156,8 @@ func (client *GitHubClient) ListRepositories(ctx context.Context) (results map[s
156156
}
157157

158158
func (client*GitHubClient)executeListRepositoriesInPage(ctx context.Context,pageint) ([]*github.Repository,*github.Response,error) {
159-
options:=&github.RepositoryListOptions{ListOptions: github.ListOptions{Page:page}}
160-
returnclient.ghClient.Repositories.List(ctx,"",options)
159+
options:=&github.RepositoryListByAuthenticatedUserOptions{ListOptions: github.ListOptions{Page:page}}
160+
returnclient.ghClient.Repositories.ListByAuthenticatedUser(ctx,options)
161161
}
162162

163163
// ListBranches on GitHub
@@ -1001,24 +1001,15 @@ func (client *GitHubClient) executeUploadCodeScanning(ctx context.Context, owner
10011001
return
10021002
}
10031003

1004-
id,err=handleGitHubUploadSarifID(sarifID,err)
1004+
id=extractIdFronSarifIDIfExists(sarifID)
10051005
return
10061006
}
10071007

1008-
funchandleGitHubUploadSarifID(sarifID*github.SarifID,uploadSarifErrerror) (idstring,errerror) {
1008+
funcextractIdFronSarifIDIfExists(sarifID*github.SarifID)string {
10091009
ifsarifID!=nil&&*sarifID.ID!="" {
1010-
id=*sarifID.ID
1011-
return
1012-
}
1013-
varresultmap[string]string
1014-
varghAcceptedError*github.AcceptedError
1015-
iferrors.As(uploadSarifErr,&ghAcceptedError) {
1016-
iferr=json.Unmarshal(ghAcceptedError.Raw,&result);err!=nil {
1017-
return
1018-
}
1019-
id=result["id"]
1010+
return*sarifID.ID
10201011
}
1021-
return
1012+
return""
10221013
}
10231014

10241015
// DownloadFileFromRepo on GitHub
@@ -1448,12 +1439,13 @@ func extractGitHubEnvironmentReviewers(environment *github.Environment) ([]strin
14481439
}
14491440

14501441
funccreateGitHubHook(token,payloadURLstring,webhookEvents...vcsutils.WebhookEvent)*github.Hook {
1442+
contentType:="json"
14511443
return&github.Hook{
14521444
Events:getGitHubWebhookEvents(webhookEvents...),
1453-
Config:map[string]interface{}{
1454-
"url":payloadURL,
1455-
"content_type":"json",
1456-
"secret":token,
1445+
Config:&github.HookConfig{
1446+
ContentType:&contentType,
1447+
URL:&payloadURL,
1448+
Secret:&token,
14571449
},
14581450
}
14591451
}
@@ -1639,3 +1631,76 @@ func (client *GitHubClient) ListAppRepositories(ctx context.Context) ([]AppRepos
16391631

16401632
returnresults,nil
16411633
}
1634+
func (client*GitHubClient)UploadSnapshotToDependencyGraph(ctx context.Context,owner,repostring,snapshot*SbomSnapshot)error {
1635+
ifsnapshot==nil {
1636+
returnfmt.Errorf("provided snapshot is nil")
1637+
}
1638+
ghSnapshot,err:=convertToGitHubSnapshot(snapshot)
1639+
iferr!=nil {
1640+
returnfmt.Errorf("failed to convert snapshot to GitHub format: %w",err)
1641+
}
1642+
1643+
_,ghResponse,err:=client.ghClient.DependencyGraph.CreateSnapshot(ctx,owner,repo,ghSnapshot)
1644+
iferr!=nil {
1645+
returnfmt.Errorf("failed to upload snapshot to dependency graph: %w",err)
1646+
}
1647+
1648+
client.logger.Info(vcsutils.SuccessfulSnapshotUpload,ghResponse.StatusCode)
1649+
returnnil
1650+
}
1651+
1652+
funcconvertToGitHubSnapshot(snapshot*SbomSnapshot) (*github.DependencyGraphSnapshot,error) {
1653+
ghSnapshot:=&github.DependencyGraphSnapshot{
1654+
Version:snapshot.Version,
1655+
Sha:&snapshot.Sha,
1656+
Ref:&snapshot.Ref,
1657+
Scanned:&github.Timestamp{Time:snapshot.Scanned},// Use current time if not provided
1658+
}
1659+
1660+
ifsnapshot.Job==nil {
1661+
returnnil,fmt.Errorf("job information is required in the snapshot")
1662+
}
1663+
ghSnapshot.Job=&github.DependencyGraphSnapshotJob{
1664+
Correlator:&snapshot.Job.Correlator,
1665+
ID:&snapshot.Job.ID,
1666+
}
1667+
1668+
ifsnapshot.Detector==nil {
1669+
returnnil,fmt.Errorf("detector information is required in the snapshot")
1670+
}
1671+
ghSnapshot.Detector=&github.DependencyGraphSnapshotDetector{
1672+
Name:&snapshot.Detector.Name,
1673+
Version:&snapshot.Detector.Version,
1674+
URL:&snapshot.Detector.Url,
1675+
}
1676+
1677+
iflen(snapshot.Manifests)==0 {
1678+
returnnil,fmt.Errorf("at least one manifest is required in the snapshot")
1679+
}
1680+
ghSnapshot.Manifests=make(map[string]*github.DependencyGraphSnapshotManifest)
1681+
formanifestName,manifest:=rangesnapshot.Manifests {
1682+
ghManifest:=&github.DependencyGraphSnapshotManifest{
1683+
Name:&manifest.Name,
1684+
}
1685+
1686+
ifmanifest.File==nil {
1687+
returnnil,fmt.Errorf("manifest '%s' is missing file information",manifestName)
1688+
}
1689+
ghManifest.File=&github.DependencyGraphSnapshotManifestFile{SourceLocation:&manifest.File.SourceLocation}
1690+
1691+
iflen(manifest.Resolved)==0 {
1692+
returnnil,fmt.Errorf("manifest '%s' must have at least one resolved dependency",manifestName)
1693+
}
1694+
ghManifest.Resolved=make(map[string]*github.DependencyGraphSnapshotResolvedDependency)
1695+
fordepName,dep:=rangemanifest.Resolved {
1696+
ghDep:=&github.DependencyGraphSnapshotResolvedDependency{
1697+
PackageURL:&dep.PackageURL,
1698+
Dependencies:dep.Dependencies,
1699+
}
1700+
ghManifest.Resolved[depName]=ghDep
1701+
}
1702+
1703+
ghSnapshot.Manifests[manifestName]=ghManifest
1704+
}
1705+
returnghSnapshot,nil
1706+
}

‎vcsclient/github_test.go‎

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"testing"
1919
"time"
2020

21-
"github.com/google/go-github/v56/github"
21+
"github.com/google/go-github/v62/github"
2222
"github.com/jfrog/froggit-go/vcsutils"
2323
"github.com/stretchr/testify/assert"
2424
)
@@ -849,14 +849,13 @@ func TestGitHubClient_UploadScanningAnalysis(t *testing.T) {
849849
scan:="{\n\"version\":\"2.1.0\",\n\"$schema\":\"https://json.schemastore.org/sarif-2.1.0-rtm.5.json\",\n\"runs\": [\n {\n\"tool\": {\n\"driver\": {\n\"informationUri\":\"https://jfrog.com/xray/\",\n\"name\":\"Xray\",\n\"rules\": [\n {\n\"id\":\"XRAY-174176\",\n\"shortDescription\": null,\n\"fullDescription\": {\n\"text\":\"json Package for Node.js lib/json.js _parseString() Function -d Argument Handling Local Code Execution Weakness\"\n },\n\"properties\": {\n\"security-severity\":\"8\"\n }\n }\n ]\n }\n },\n\"results\": [\n {\n\"ruleId\":\"XRAY-174176\",\n\"ruleIndex\": 1,\n\"message\": {\n\"text\":\"json 9.0.6. Fixed in Versions: [11.0.0]\"\n },\n\"locations\": [\n {\n\"physicalLocation\": {\n\"artifactLocation\": {\n\"uri\":\"package.json\"\n }\n }\n }\n ]\n }\n ]\n }\n ]\n }"
850850
response,err:=os.ReadFile(filepath.Join("testdata","github","commit_list_response.json"))
851851
assert.NoError(t,err)
852-
expectedUploadSarifID:="b16b0368-01b9-11ed-90a3-cabff0b8ad31"
853852
client,cleanUp:=createServerAndClient(t,vcsutils.GitHub,false,response,
854853
fmt.Sprintf("/repos/%s/%s/commits?page=1&per_page=50&sha=master",owner,repo1),createGitHubSarifUploadHandler)
855854
defercleanUp()
856855

857856
sarifID,err:=client.UploadCodeScanning(ctx,owner,repo1,"master",scan)
858857
assert.NoError(t,err)
859-
assert.Equal(t,expectedUploadSarifID,sarifID)
858+
assert.Equal(t,"",sarifID)
860859

861860
_,err=createBadGitHubClient(t).UploadCodeScanning(ctx,owner,repo1,"master",scan)
862861
assert.Error(t,err)
@@ -1558,3 +1557,54 @@ func TestGitHubClient_ListAppRepositories(t *testing.T) {
15581557
_,err=createBadGitHubClient(t).ListAppRepositories(ctx)
15591558
assert.Error(t,err)
15601559
}
1560+
1561+
funcTestGithubClient_UploadSnapshotToDependencyGraph(t*testing.T) {
1562+
ctx:=context.Background()
1563+
expectedURI:=fmt.Sprintf("/repos/%s/%s/dependency-graph/snapshots",owner,repo1)
1564+
1565+
resolvedPackages:=make(map[string]*ResolvedDependency)
1566+
resolvedPackages["@actions/core"]=&ResolvedDependency{
1567+
PackageURL:"pkg:/npm/%40actions/core@1.1.9",
1568+
Relationship:"direct",
1569+
Dependencies: []string{"@actions/http-client"},
1570+
}
1571+
resolvedPackages["@actions/http-client"]=&ResolvedDependency{
1572+
PackageURL:"pkg:/npm/%40actions/http-client@1.0.1",
1573+
Relationship:"direct",
1574+
Dependencies: []string{"tunnel"},
1575+
}
1576+
resolvedPackages["tunnel"]=&ResolvedDependency{
1577+
PackageURL:"pkg:/npm/tunnel@0.0.6",
1578+
Relationship:"indirect",
1579+
}
1580+
1581+
manifests:=make(map[string]*Manifest)
1582+
manifests["package-lock.json"]=&Manifest{
1583+
Name:"package-lock.json",
1584+
File:&FileInfo{SourceLocation:"src/package-lock.json"},
1585+
Resolved:resolvedPackages,
1586+
}
1587+
1588+
snapshot:=SbomSnapshot{
1589+
Version:0,
1590+
Sha:"ce587453ced02b1526dfb4cb910479d431683101",
1591+
Ref:"refs/heads/master",
1592+
Job:&JobInfo{
1593+
Correlator:"my-workflow_my-action-name",
1594+
ID:"my-run-id",
1595+
},
1596+
Detector:&DetectorInfo{Name:"frogbot",Version:"1.0.0",Url:"https://github.com/jfrog/frogbot"},
1597+
Scanned:time.Now(),
1598+
Manifests:manifests,
1599+
}
1600+
1601+
client,cleanUp:=createServerAndClient(t,vcsutils.GitHub,false,nil,expectedURI,createGitHubHandler)
1602+
defercleanUp()
1603+
1604+
err:=client.UploadSnapshotToDependencyGraph(ctx,owner,repo1,&snapshot)
1605+
assert.NoError(t,err)
1606+
1607+
// Negative test: bad client
1608+
err=createBadGitHubClient(t).UploadSnapshotToDependencyGraph(ctx,owner,repo1,&snapshot)
1609+
assert.Error(t,err)
1610+
}

‎vcsclient/gitlab.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,10 @@ func (client *GitLabClient) CreatePullRequestDetailed(ctx context.Context, owner
823823
returnCreatedPullRequestInfo{},errGitlabCreatePullRequestDetailedNotSupported
824824
}
825825

826+
func (client*GitLabClient)UploadSnapshotToDependencyGraph(ctx context.Context,owner,repostring,snapshot*SbomSnapshot)error {
827+
returnerrGitLabUploadSnapshotToDependencyGraphNotSupported
828+
}
829+
826830
funcgetProjectID(owner,projectstring)string {
827831
returnfmt.Sprintf("%s/%s",owner,project)
828832
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp