diff --git a/github/dependency_graph_snapshots.go b/github/dependency_graph_snapshots.go new file mode 100644 index 00000000000..0606b981510 --- /dev/null +++ b/github/dependency_graph_snapshots.go @@ -0,0 +1,113 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DependencyGraphSnapshotResolvedDependency represents a resolved dependency in a dependency graph snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotResolvedDependency struct { + PackageURL *string `json:"package_url,omitempty"` + // Represents whether the dependency is requested directly by the manifest or is a dependency of another dependency. + // Can have the following values: + // - "direct": indicates that the dependency is requested directly by the manifest. + // - "indirect": indicates that the dependency is a dependency of another dependency. + Relationship *string `json:"relationship,omitempty"` + // Represents whether the dependency is required for the primary build artifact or is only used for development. + // Can have the following values: + // - "runtime": indicates that the dependency is required for the primary build artifact. + // - "development": indicates that the dependency is only used for development. + Scope *string `json:"scope,omitempty"` + Dependencies []string `json:"dependencies,omitempty"` +} + +// DependencyGraphSnapshotJob represents the job that created the snapshot. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotJob struct { + Correlator *string `json:"correlator,omitempty"` + ID *string `json:"id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// DependencyGraphSnapshotDetector represents a description of the detector used. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotDetector struct { + Name *string `json:"name,omitempty"` + Version *string `json:"version,omitempty"` + URL *string `json:"url,omitempty"` +} + +// DependencyGraphSnapshotManifestFile represents the file declaring the repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifestFile struct { + SourceLocation *string `json:"source_location,omitempty"` +} + +// DependencyGraphSnapshotManifest represents a collection of related dependencies declared in a file or representing a logical group of dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotManifest struct { + Name *string `json:"name,omitempty"` + File *DependencyGraphSnapshotManifestFile `json:"file,omitempty"` + Resolved map[string]*DependencyGraphSnapshotResolvedDependency `json:"resolved,omitempty"` +} + +// DependencyGraphSnapshot represent a snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshot struct { + Version int `json:"version"` + Sha *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Job *DependencyGraphSnapshotJob `json:"job,omitempty"` + Detector *DependencyGraphSnapshotDetector `json:"detector,omitempty"` + Scanned *Timestamp `json:"scanned,omitempty"` + Manifests map[string]*DependencyGraphSnapshotManifest `json:"manifests,omitempty"` +} + +// DependencyGraphSnapshotCreationData represents the dependency snapshot's creation result. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +type DependencyGraphSnapshotCreationData struct { + ID int64 `json:"id"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Message *string `json:"message,omitempty"` + // Represents the snapshot creation result. + // Can have the following values: + // - "SUCCESS": indicates that the snapshot was successfully created and the repository's dependencies were updated. + // - "ACCEPTED": indicates that the snapshot was successfully created, but the repository's dependencies were not updated. + // - "INVALID": indicates that the snapshot was malformed. + Result *string `json:"result,omitempty"` +} + +// CreateSnapshot creates a new snapshot of a repository's dependencies. +// +// GitHub API docs: https://docs.github.com/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository +// +//meta:operation POST /repos/{owner}/{repo}/dependency-graph/snapshots +func (s *DependencyGraphService) CreateSnapshot(ctx context.Context, owner, repo string, dependencyGraphSnapshot *DependencyGraphSnapshot) (*DependencyGraphSnapshotCreationData, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependency-graph/snapshots", owner, repo) + + req, err := s.client.NewRequest("POST", url, dependencyGraphSnapshot) + if err != nil { + return nil, nil, err + } + + var snapshotCreationData *DependencyGraphSnapshotCreationData + resp, err := s.client.Do(ctx, req, &snapshotCreationData) + if err != nil { + return nil, resp, err + } + + return snapshotCreationData, resp, nil +} diff --git a/github/dependency_graph_snapshots_test.go b/github/dependency_graph_snapshots_test.go new file mode 100644 index 00000000000..ed70ed574d2 --- /dev/null +++ b/github/dependency_graph_snapshots_test.go @@ -0,0 +1,94 @@ +// Copyright 2023 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func TestDependencyGraphService_CreateSnapshot(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/dependency-graph/snapshots", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + testBody(t, r, `{"version":0,"sha":"ce587453ced02b1526dfb4cb910479d431683101","ref":"refs/heads/main","job":{"correlator":"yourworkflowname_youractionname","id":"yourrunid","html_url":"https://example.com"},"detector":{"name":"octo-detector","version":"0.0.1","url":"https://github.com/octo-org/octo-repo"},"scanned":"2022-06-14T20:25:00Z","manifests":{"package-lock.json":{"name":"package-lock.json","file":{"source_location":"src/package-lock.json"},"resolved":{"@actions/core":{"package_url":"pkg:/npm/%40actions/core@1.1.9","relationship":"direct","scope":"runtime","dependencies":["@actions/http-client"]},"@actions/http-client":{"package_url":"pkg:/npm/%40actions/http-client@1.0.7","relationship":"indirect","scope":"runtime","dependencies":["tunnel"]},"tunnel":{"package_url":"pkg:/npm/tunnel@0.0.6","relationship":"indirect","scope":"runtime"}}}}}`+"\n") + fmt.Fprint(w, `{"id":12345,"created_at":"2022-06-14T20:25:01Z","message":"Dependency results for the repo have been successfully updated.","result":"SUCCESS"}`) + }) + + ctx := context.Background() + snapshot := &DependencyGraphSnapshot{ + Version: 0, + Sha: String("ce587453ced02b1526dfb4cb910479d431683101"), + Ref: String("refs/heads/main"), + Job: &DependencyGraphSnapshotJob{ + Correlator: String("yourworkflowname_youractionname"), + ID: String("yourrunid"), + HTMLURL: String("https://example.com"), + }, + Detector: &DependencyGraphSnapshotDetector{ + Name: String("octo-detector"), + Version: String("0.0.1"), + URL: String("https://github.com/octo-org/octo-repo"), + }, + Scanned: &Timestamp{time.Date(2022, time.June, 14, 20, 25, 00, 0, time.UTC)}, + Manifests: map[string]*DependencyGraphSnapshotManifest{ + "package-lock.json": { + Name: String("package-lock.json"), + File: &DependencyGraphSnapshotManifestFile{SourceLocation: String("src/package-lock.json")}, + Resolved: map[string]*DependencyGraphSnapshotResolvedDependency{ + "@actions/core": { + PackageURL: String("pkg:/npm/%40actions/core@1.1.9"), + Relationship: String("direct"), + Scope: String("runtime"), + Dependencies: []string{"@actions/http-client"}, + }, + "@actions/http-client": { + PackageURL: String("pkg:/npm/%40actions/http-client@1.0.7"), + Relationship: String("indirect"), + Scope: String("runtime"), + Dependencies: []string{"tunnel"}, + }, + "tunnel": { + PackageURL: String("pkg:/npm/tunnel@0.0.6"), + Relationship: String("indirect"), + Scope: String("runtime"), + }, + }, + }, + }, + } + + snapshotCreationData, _, err := client.DependencyGraph.CreateSnapshot(ctx, "o", "r", snapshot) + if err != nil { + t.Errorf("DependencyGraph.CreateSnapshot returned error: %v", err) + } + + want := &DependencyGraphSnapshotCreationData{ + ID: 12345, + CreatedAt: &Timestamp{time.Date(2022, time.June, 14, 20, 25, 01, 0, time.UTC)}, + Message: String("Dependency results for the repo have been successfully updated."), + Result: String("SUCCESS"), + } + if !cmp.Equal(snapshotCreationData, want) { + t.Errorf("DependencyGraph.CreateSnapshot returned %+v, want %+v", snapshotCreationData, want) + } + + const methodName = "CreateSnapshot" + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.DependencyGraph.CreateSnapshot(ctx, "o", "r", snapshot) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} diff --git a/github/github-accessors.go b/github/github-accessors.go index 13bf7d6668c..fc83a9509b4 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -5206,6 +5206,166 @@ func (d *Dependency) GetScope() string { return *d.Scope } +// GetDetector returns the Detector field. +func (d *DependencyGraphSnapshot) GetDetector() *DependencyGraphSnapshotDetector { + if d == nil { + return nil + } + return d.Detector +} + +// GetJob returns the Job field. +func (d *DependencyGraphSnapshot) GetJob() *DependencyGraphSnapshotJob { + if d == nil { + return nil + } + return d.Job +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetScanned returns the Scanned field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetScanned() Timestamp { + if d == nil || d.Scanned == nil { + return Timestamp{} + } + return *d.Scanned +} + +// GetSha returns the Sha field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshot) GetSha() string { + if d == nil || d.Sha == nil { + return "" + } + return *d.Sha +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetMessage() string { + if d == nil || d.Message == nil { + return "" + } + return *d.Message +} + +// GetResult returns the Result field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotCreationData) GetResult() string { + if d == nil || d.Result == nil { + return "" + } + return *d.Result +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotDetector) GetVersion() string { + if d == nil || d.Version == nil { + return "" + } + return *d.Version +} + +// GetCorrelator returns the Correlator field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetCorrelator() string { + if d == nil || d.Correlator == nil { + return "" + } + return *d.Correlator +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotJob) GetID() string { + if d == nil || d.ID == nil { + return "" + } + return *d.ID +} + +// GetFile returns the File field. +func (d *DependencyGraphSnapshotManifest) GetFile() *DependencyGraphSnapshotManifestFile { + if d == nil { + return nil + } + return d.File +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifest) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetSourceLocation returns the SourceLocation field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotManifestFile) GetSourceLocation() string { + if d == nil || d.SourceLocation == nil { + return "" + } + return *d.SourceLocation +} + +// GetPackageURL returns the PackageURL field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetPackageURL() string { + if d == nil || d.PackageURL == nil { + return "" + } + return *d.PackageURL +} + +// GetRelationship returns the Relationship field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetRelationship() string { + if d == nil || d.Relationship == nil { + return "" + } + return *d.Relationship +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (d *DependencyGraphSnapshotResolvedDependency) GetScope() string { + if d == nil || d.Scope == nil { + return "" + } + return *d.Scope +} + // GetAction returns the Action field if it's non-nil, zero value otherwise. func (d *DeployKeyEvent) GetAction() string { if d == nil || d.Action == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 313e92c0596..ee15610f9c2 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -6112,6 +6112,197 @@ func TestDependency_GetScope(tt *testing.T) { d.GetScope() } +func TestDependencyGraphSnapshot_GetDetector(tt *testing.T) { + d := &DependencyGraphSnapshot{} + d.GetDetector() + d = nil + d.GetDetector() +} + +func TestDependencyGraphSnapshot_GetJob(tt *testing.T) { + d := &DependencyGraphSnapshot{} + d.GetJob() + d = nil + d.GetJob() +} + +func TestDependencyGraphSnapshot_GetRef(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshot{Ref: &zeroValue} + d.GetRef() + d = &DependencyGraphSnapshot{} + d.GetRef() + d = nil + d.GetRef() +} + +func TestDependencyGraphSnapshot_GetScanned(tt *testing.T) { + var zeroValue Timestamp + d := &DependencyGraphSnapshot{Scanned: &zeroValue} + d.GetScanned() + d = &DependencyGraphSnapshot{} + d.GetScanned() + d = nil + d.GetScanned() +} + +func TestDependencyGraphSnapshot_GetSha(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshot{Sha: &zeroValue} + d.GetSha() + d = &DependencyGraphSnapshot{} + d.GetSha() + d = nil + d.GetSha() +} + +func TestDependencyGraphSnapshotCreationData_GetCreatedAt(tt *testing.T) { + var zeroValue Timestamp + d := &DependencyGraphSnapshotCreationData{CreatedAt: &zeroValue} + d.GetCreatedAt() + d = &DependencyGraphSnapshotCreationData{} + d.GetCreatedAt() + d = nil + d.GetCreatedAt() +} + +func TestDependencyGraphSnapshotCreationData_GetMessage(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotCreationData{Message: &zeroValue} + d.GetMessage() + d = &DependencyGraphSnapshotCreationData{} + d.GetMessage() + d = nil + d.GetMessage() +} + +func TestDependencyGraphSnapshotCreationData_GetResult(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotCreationData{Result: &zeroValue} + d.GetResult() + d = &DependencyGraphSnapshotCreationData{} + d.GetResult() + d = nil + d.GetResult() +} + +func TestDependencyGraphSnapshotDetector_GetName(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotDetector{Name: &zeroValue} + d.GetName() + d = &DependencyGraphSnapshotDetector{} + d.GetName() + d = nil + d.GetName() +} + +func TestDependencyGraphSnapshotDetector_GetURL(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotDetector{URL: &zeroValue} + d.GetURL() + d = &DependencyGraphSnapshotDetector{} + d.GetURL() + d = nil + d.GetURL() +} + +func TestDependencyGraphSnapshotDetector_GetVersion(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotDetector{Version: &zeroValue} + d.GetVersion() + d = &DependencyGraphSnapshotDetector{} + d.GetVersion() + d = nil + d.GetVersion() +} + +func TestDependencyGraphSnapshotJob_GetCorrelator(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotJob{Correlator: &zeroValue} + d.GetCorrelator() + d = &DependencyGraphSnapshotJob{} + d.GetCorrelator() + d = nil + d.GetCorrelator() +} + +func TestDependencyGraphSnapshotJob_GetHTMLURL(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotJob{HTMLURL: &zeroValue} + d.GetHTMLURL() + d = &DependencyGraphSnapshotJob{} + d.GetHTMLURL() + d = nil + d.GetHTMLURL() +} + +func TestDependencyGraphSnapshotJob_GetID(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotJob{ID: &zeroValue} + d.GetID() + d = &DependencyGraphSnapshotJob{} + d.GetID() + d = nil + d.GetID() +} + +func TestDependencyGraphSnapshotManifest_GetFile(tt *testing.T) { + d := &DependencyGraphSnapshotManifest{} + d.GetFile() + d = nil + d.GetFile() +} + +func TestDependencyGraphSnapshotManifest_GetName(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotManifest{Name: &zeroValue} + d.GetName() + d = &DependencyGraphSnapshotManifest{} + d.GetName() + d = nil + d.GetName() +} + +func TestDependencyGraphSnapshotManifestFile_GetSourceLocation(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotManifestFile{SourceLocation: &zeroValue} + d.GetSourceLocation() + d = &DependencyGraphSnapshotManifestFile{} + d.GetSourceLocation() + d = nil + d.GetSourceLocation() +} + +func TestDependencyGraphSnapshotResolvedDependency_GetPackageURL(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotResolvedDependency{PackageURL: &zeroValue} + d.GetPackageURL() + d = &DependencyGraphSnapshotResolvedDependency{} + d.GetPackageURL() + d = nil + d.GetPackageURL() +} + +func TestDependencyGraphSnapshotResolvedDependency_GetRelationship(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotResolvedDependency{Relationship: &zeroValue} + d.GetRelationship() + d = &DependencyGraphSnapshotResolvedDependency{} + d.GetRelationship() + d = nil + d.GetRelationship() +} + +func TestDependencyGraphSnapshotResolvedDependency_GetScope(tt *testing.T) { + var zeroValue string + d := &DependencyGraphSnapshotResolvedDependency{Scope: &zeroValue} + d.GetScope() + d = &DependencyGraphSnapshotResolvedDependency{} + d.GetScope() + d = nil + d.GetScope() +} + func TestDeployKeyEvent_GetAction(tt *testing.T) { var zeroValue string d := &DeployKeyEvent{Action: &zeroValue}