Repository: google/go-github (2025-07-27T09:33:13Z)

Issue:
Add Metadata properties to DependencySubmission API structs (DependencyGraph.CreateSnapshot)
The current Dependency Submission API structs are lacking Metadata fields in several possible places places (according to GitHub docs: https://docs.github.com/en/rest/dependency-graph/dependency-submission?apiVersion=2022-11-28&search-overlay-input=in+the+dependency+submission+api+what+is+the+detector.version+param%3F&search-overlay-ask-ai=true)

These properties are required for a feature we are working on and were partially added in this PR: https://github.com/google/go-github/pull/3640

Here is the link for the PR:
https://github.com/google/go-github/pull/3653



Discussion:

Patch:
diff --git a/github/dependency_graph_snapshots.go b/github/dependency_graph_snapshots.go
index ed1a752f463..ddfecf429f7 100644
--- a/github/dependency_graph_snapshots.go
+++ b/github/dependency_graph_snapshots.go
@@ -15,6 +15,15 @@ import (
 // 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"`
+	// User-defined metadata to store domain-specific information limited to 8 keys with scalar values.
+	// This metadata overrides auto-detected values from the package URL and GitHub's database.
+	// Common fields include:
+	//   - "licenses": license information (e.g., "MIT", "Apache-2.0")
+	//   - "name": package name
+	//   - "version": package version
+	//   - "manager": package manager (e.g., "npm", "pip", "maven")
+	//   - "description": package description
+	Metadata map[string]any `json:"metadata,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.
@@ -59,6 +68,7 @@ type DependencyGraphSnapshotManifestFile struct {
 type DependencyGraphSnapshotManifest struct {
 	Name     *string                                               `json:"name,omitempty"`
 	File     *DependencyGraphSnapshotManifestFile                  `json:"file,omitempty"`
+	Metadata map[string]any                                        `json:"metadata,omitempty"`
 	Resolved map[string]*DependencyGraphSnapshotResolvedDependency `json:"resolved,omitempty"`
 }
 
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 7edf3a4cdf0..db42c7f3970 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -7126,6 +7126,14 @@ func (d *DependencyGraphSnapshotManifest) GetFile() *DependencyGraphSnapshotMani
 	return d.File
 }
 
+// GetMetadata returns the Metadata map if it's non-nil, an empty map otherwise.
+func (d *DependencyGraphSnapshotManifest) GetMetadata() map[string]any {
+	if d == nil || d.Metadata == nil {
+		return map[string]any{}
+	}
+	return d.Metadata
+}
+
 // GetName returns the Name field if it's non-nil, zero value otherwise.
 func (d *DependencyGraphSnapshotManifest) GetName() string {
 	if d == nil || d.Name == nil {
@@ -7142,6 +7150,14 @@ func (d *DependencyGraphSnapshotManifestFile) GetSourceLocation() string {
 	return *d.SourceLocation
 }
 
+// GetMetadata returns the Metadata map if it's non-nil, an empty map otherwise.
+func (d *DependencyGraphSnapshotResolvedDependency) GetMetadata() map[string]any {
+	if d == nil || d.Metadata == nil {
+		return map[string]any{}
+	}
+	return d.Metadata
+}
+
 // GetPackageURL returns the PackageURL field if it's non-nil, zero value otherwise.
 func (d *DependencyGraphSnapshotResolvedDependency) GetPackageURL() string {
 	if d == nil || d.PackageURL == nil {


Test patch:
diff --git a/github/dependency_graph_snapshots_test.go b/github/dependency_graph_snapshots_test.go
index 24a6230a184..6b9ec81f095 100644
--- a/github/dependency_graph_snapshots_test.go
+++ b/github/dependency_graph_snapshots_test.go
@@ -21,7 +21,7 @@ func TestDependencyGraphService_CreateSnapshot(t *testing.T) {
 
 	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","metadata":{"key1":"value1","key2":"value2"},"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")
+		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","metadata":{"key1":"value1","key2":"value2"},"manifests":{"package-lock.json":{"name":"package-lock.json","file":{"source_location":"src/package-lock.json"},"metadata":{"key1":"value1","key2":"value2"},"resolved":{"@actions/core":{"package_url":"pkg:/npm/%40actions/core@1.1.9","metadata":{"licenses":"MIT"},"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"}`)
 	})
 
@@ -49,11 +49,18 @@ func TestDependencyGraphService_CreateSnapshot(t *testing.T) {
 			"package-lock.json": {
 				Name: Ptr("package-lock.json"),
 				File: &DependencyGraphSnapshotManifestFile{SourceLocation: Ptr("src/package-lock.json")},
+				Metadata: map[string]any{
+					"key1": "value1",
+					"key2": "value2",
+				},
 				Resolved: map[string]*DependencyGraphSnapshotResolvedDependency{
 					"@actions/core": {
 						PackageURL:   Ptr("pkg:/npm/%40actions/core@1.1.9"),
 						Relationship: Ptr("direct"),
 						Scope:        Ptr("runtime"),
+						Metadata: map[string]any{
+							"licenses": "MIT",
+						},
 						Dependencies: []string{"@actions/http-client"},
 					},
 					"@actions/http-client": {
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 38a1fda432e..b41098b1b47 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -9263,6 +9263,17 @@ func TestDependencyGraphSnapshotManifest_GetFile(tt *testing.T) {
 	d.GetFile()
 }
 
+func TestDependencyGraphSnapshotManifest_GetMetadata(tt *testing.T) {
+	tt.Parallel()
+	zeroValue := map[string]any{}
+	d := &DependencyGraphSnapshotManifest{Metadata: zeroValue}
+	d.GetMetadata()
+	d = &DependencyGraphSnapshotManifest{}
+	d.GetMetadata()
+	d = nil
+	d.GetMetadata()
+}
+
 func TestDependencyGraphSnapshotManifest_GetName(tt *testing.T) {
 	tt.Parallel()
 	var zeroValue string
@@ -9285,6 +9296,17 @@ func TestDependencyGraphSnapshotManifestFile_GetSourceLocation(tt *testing.T) {
 	d.GetSourceLocation()
 }
 
+func TestDependencyGraphSnapshotResolvedDependency_GetMetadata(tt *testing.T) {
+	tt.Parallel()
+	zeroValue := map[string]any{}
+	d := &DependencyGraphSnapshotResolvedDependency{Metadata: zeroValue}
+	d.GetMetadata()
+	d = &DependencyGraphSnapshotResolvedDependency{}
+	d.GetMetadata()
+	d = nil
+	d.GetMetadata()
+}
+
 func TestDependencyGraphSnapshotResolvedDependency_GetPackageURL(tt *testing.T) {
 	tt.Parallel()
 	var zeroValue string