From 89a506d16ec718a9e2b11e0ac5a7f247a00810f5 Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Tue, 27 Jan 2026 09:43:16 +0530 Subject: [PATCH 1/6] feat: implement organization artifact metadata APIs --- github/github-accessors.go | 176 +++++++++++++++++++++++ github/github-accessors_test.go | 242 ++++++++++++++++++++++++++++++++ github/github-stringify_test.go | 61 ++++++++ github/orgs_artifacts.go | 139 ++++++++++++++++++ github/orgs_artifacts_test.go | 145 +++++++++++++++++++ 5 files changed, 763 insertions(+) create mode 100644 github/orgs_artifacts.go create mode 100644 github/orgs_artifacts_test.go diff --git a/github/github-accessors.go b/github/github-accessors.go index 03a8bc19eaa..a3c701e461d 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1134,6 +1134,110 @@ func (a *Artifact) GetWorkflowRun() *ArtifactWorkflowRun { return a.WorkflowRun } +// GetAttestationID returns the AttestationID field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetAttestationID() int64 { + if a == nil || a.AttestationID == nil { + return 0 + } + return *a.AttestationID +} + +// GetCluster returns the Cluster field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetCluster() string { + if a == nil || a.Cluster == nil { + return "" + } + return *a.Cluster +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetCreated() Timestamp { + if a == nil || a.Created == nil { + return Timestamp{} + } + return *a.Created +} + +// GetDeploymentName returns the DeploymentName field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetDeploymentName() string { + if a == nil || a.DeploymentName == nil { + return "" + } + return *a.DeploymentName +} + +// GetDigest returns the Digest field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetDigest() string { + if a == nil || a.Digest == nil { + return "" + } + return *a.Digest +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetLogicalEnvironment returns the LogicalEnvironment field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetLogicalEnvironment() string { + if a == nil || a.LogicalEnvironment == nil { + return "" + } + return *a.LogicalEnvironment +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetPhysicalEnvironment returns the PhysicalEnvironment field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetPhysicalEnvironment() string { + if a == nil || a.PhysicalEnvironment == nil { + return "" + } + return *a.PhysicalEnvironment +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetStatus() string { + if a == nil || a.Status == nil { + return "" + } + return *a.Status +} + +// GetTags returns the Tags map if it's non-nil, an empty map otherwise. +func (a *ArtifactDeploymentRecord) GetTags() map[string]string { + if a == nil || a.Tags == nil { + return map[string]string{} + } + return a.Tags +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentResponse) GetTotalCount() int { + if a == nil || a.TotalCount == nil { + return 0 + } + return *a.TotalCount +} + // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (a *ArtifactList) GetTotalCount() int64 { if a == nil || a.TotalCount == nil { @@ -1166,6 +1270,78 @@ func (a *ArtifactPeriodOpt) GetDays() int { return *a.Days } +// GetArtifactURL returns the ArtifactURL field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetArtifactURL() string { + if a == nil || a.ArtifactURL == nil { + return "" + } + return *a.ArtifactURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDigest returns the Digest field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetDigest() string { + if a == nil || a.Digest == nil { + return "" + } + return *a.Digest +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetRegistryURL returns the RegistryURL field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetRegistryURL() string { + if a == nil || a.RegistryURL == nil { + return "" + } + return *a.RegistryURL +} + +// GetRepository returns the Repository field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetRepository() string { + if a == nil || a.Repository == nil { + return "" + } + return *a.Repository +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetStatus() string { + if a == nil || a.Status == nil { + return "" + } + return *a.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageResponse) GetTotalCount() int { + if a == nil || a.TotalCount == nil { + return 0 + } + return *a.TotalCount +} + // GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. func (a *ArtifactWorkflowRun) GetHeadBranch() string { if a == nil || a.HeadBranch == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 1e8778d11c7..63d55f5b757 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1468,6 +1468,149 @@ func TestArtifact_GetWorkflowRun(tt *testing.T) { a.GetWorkflowRun() } +func TestArtifactDeploymentRecord_GetAttestationID(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + a := &ArtifactDeploymentRecord{AttestationID: &zeroValue} + a.GetAttestationID() + a = &ArtifactDeploymentRecord{} + a.GetAttestationID() + a = nil + a.GetAttestationID() +} + +func TestArtifactDeploymentRecord_GetCluster(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{Cluster: &zeroValue} + a.GetCluster() + a = &ArtifactDeploymentRecord{} + a.GetCluster() + a = nil + a.GetCluster() +} + +func TestArtifactDeploymentRecord_GetCreated(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &ArtifactDeploymentRecord{Created: &zeroValue} + a.GetCreated() + a = &ArtifactDeploymentRecord{} + a.GetCreated() + a = nil + a.GetCreated() +} + +func TestArtifactDeploymentRecord_GetDeploymentName(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{DeploymentName: &zeroValue} + a.GetDeploymentName() + a = &ArtifactDeploymentRecord{} + a.GetDeploymentName() + a = nil + a.GetDeploymentName() +} + +func TestArtifactDeploymentRecord_GetDigest(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{Digest: &zeroValue} + a.GetDigest() + a = &ArtifactDeploymentRecord{} + a.GetDigest() + a = nil + a.GetDigest() +} + +func TestArtifactDeploymentRecord_GetID(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + a := &ArtifactDeploymentRecord{ID: &zeroValue} + a.GetID() + a = &ArtifactDeploymentRecord{} + a.GetID() + a = nil + a.GetID() +} + +func TestArtifactDeploymentRecord_GetLogicalEnvironment(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{LogicalEnvironment: &zeroValue} + a.GetLogicalEnvironment() + a = &ArtifactDeploymentRecord{} + a.GetLogicalEnvironment() + a = nil + a.GetLogicalEnvironment() +} + +func TestArtifactDeploymentRecord_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{Name: &zeroValue} + a.GetName() + a = &ArtifactDeploymentRecord{} + a.GetName() + a = nil + a.GetName() +} + +func TestArtifactDeploymentRecord_GetPhysicalEnvironment(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{PhysicalEnvironment: &zeroValue} + a.GetPhysicalEnvironment() + a = &ArtifactDeploymentRecord{} + a.GetPhysicalEnvironment() + a = nil + a.GetPhysicalEnvironment() +} + +func TestArtifactDeploymentRecord_GetStatus(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{Status: &zeroValue} + a.GetStatus() + a = &ArtifactDeploymentRecord{} + a.GetStatus() + a = nil + a.GetStatus() +} + +func TestArtifactDeploymentRecord_GetTags(tt *testing.T) { + tt.Parallel() + zeroValue := map[string]string{} + a := &ArtifactDeploymentRecord{Tags: zeroValue} + a.GetTags() + a = &ArtifactDeploymentRecord{} + a.GetTags() + a = nil + a.GetTags() +} + +func TestArtifactDeploymentRecord_GetUpdatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &ArtifactDeploymentRecord{UpdatedAt: &zeroValue} + a.GetUpdatedAt() + a = &ArtifactDeploymentRecord{} + a.GetUpdatedAt() + a = nil + a.GetUpdatedAt() +} + +func TestArtifactDeploymentResponse_GetTotalCount(tt *testing.T) { + tt.Parallel() + var zeroValue int + a := &ArtifactDeploymentResponse{TotalCount: &zeroValue} + a.GetTotalCount() + a = &ArtifactDeploymentResponse{} + a.GetTotalCount() + a = nil + a.GetTotalCount() +} + func TestArtifactList_GetTotalCount(tt *testing.T) { tt.Parallel() var zeroValue int64 @@ -1512,6 +1655,105 @@ func TestArtifactPeriodOpt_GetDays(tt *testing.T) { a.GetDays() } +func TestArtifactStorageRecord_GetArtifactURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{ArtifactURL: &zeroValue} + a.GetArtifactURL() + a = &ArtifactStorageRecord{} + a.GetArtifactURL() + a = nil + a.GetArtifactURL() +} + +func TestArtifactStorageRecord_GetCreatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &ArtifactStorageRecord{CreatedAt: &zeroValue} + a.GetCreatedAt() + a = &ArtifactStorageRecord{} + a.GetCreatedAt() + a = nil + a.GetCreatedAt() +} + +func TestArtifactStorageRecord_GetDigest(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Digest: &zeroValue} + a.GetDigest() + a = &ArtifactStorageRecord{} + a.GetDigest() + a = nil + a.GetDigest() +} + +func TestArtifactStorageRecord_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Name: &zeroValue} + a.GetName() + a = &ArtifactStorageRecord{} + a.GetName() + a = nil + a.GetName() +} + +func TestArtifactStorageRecord_GetRegistryURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{RegistryURL: &zeroValue} + a.GetRegistryURL() + a = &ArtifactStorageRecord{} + a.GetRegistryURL() + a = nil + a.GetRegistryURL() +} + +func TestArtifactStorageRecord_GetRepository(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Repository: &zeroValue} + a.GetRepository() + a = &ArtifactStorageRecord{} + a.GetRepository() + a = nil + a.GetRepository() +} + +func TestArtifactStorageRecord_GetStatus(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Status: &zeroValue} + a.GetStatus() + a = &ArtifactStorageRecord{} + a.GetStatus() + a = nil + a.GetStatus() +} + +func TestArtifactStorageRecord_GetUpdatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + a := &ArtifactStorageRecord{UpdatedAt: &zeroValue} + a.GetUpdatedAt() + a = &ArtifactStorageRecord{} + a.GetUpdatedAt() + a = nil + a.GetUpdatedAt() +} + +func TestArtifactStorageResponse_GetTotalCount(tt *testing.T) { + tt.Parallel() + var zeroValue int + a := &ArtifactStorageResponse{TotalCount: &zeroValue} + a.GetTotalCount() + a = &ArtifactStorageResponse{} + a.GetTotalCount() + a = nil + a.GetTotalCount() +} + func TestArtifactWorkflowRun_GetHeadBranch(tt *testing.T) { tt.Parallel() var zeroValue string diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go index e7c6ed86da5..67aae3d9915 100644 --- a/github/github-stringify_test.go +++ b/github/github-stringify_test.go @@ -115,6 +115,38 @@ func TestAdvancedSecurity_String(t *testing.T) { } } +func TestArtifactDeploymentRecord_String(t *testing.T) { + t.Parallel() + v := ArtifactDeploymentRecord{ + ID: Ptr(int64(0)), + Digest: Ptr(""), + Name: Ptr(""), + Status: Ptr(""), + LogicalEnvironment: Ptr(""), + PhysicalEnvironment: Ptr(""), + Cluster: Ptr(""), + DeploymentName: Ptr(""), + Created: &Timestamp{}, + UpdatedAt: &Timestamp{}, + AttestationID: Ptr(int64(0)), + } + want := `github.ArtifactDeploymentRecord{ID:0, Digest:"", Name:"", Status:"", LogicalEnvironment:"", PhysicalEnvironment:"", Cluster:"", DeploymentName:"", Created:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, AttestationID:0}` + if got := v.String(); got != want { + t.Errorf("ArtifactDeploymentRecord.String = %v, want %v", got, want) + } +} + +func TestArtifactDeploymentResponse_String(t *testing.T) { + t.Parallel() + v := ArtifactDeploymentResponse{ + TotalCount: Ptr(0), + } + want := `github.ArtifactDeploymentResponse{TotalCount:0}` + if got := v.String(); got != want { + t.Errorf("ArtifactDeploymentResponse.String = %v, want %v", got, want) + } +} + func TestArtifactPeriod_String(t *testing.T) { t.Parallel() v := ArtifactPeriod{ @@ -127,6 +159,35 @@ func TestArtifactPeriod_String(t *testing.T) { } } +func TestArtifactStorageRecord_String(t *testing.T) { + t.Parallel() + v := ArtifactStorageRecord{ + Name: Ptr(""), + Digest: Ptr(""), + ArtifactURL: Ptr(""), + RegistryURL: Ptr(""), + Repository: Ptr(""), + Status: Ptr(""), + CreatedAt: &Timestamp{}, + UpdatedAt: &Timestamp{}, + } + want := `github.ArtifactStorageRecord{Name:"", Digest:"", ArtifactURL:"", RegistryURL:"", Repository:"", Status:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` + if got := v.String(); got != want { + t.Errorf("ArtifactStorageRecord.String = %v, want %v", got, want) + } +} + +func TestArtifactStorageResponse_String(t *testing.T) { + t.Parallel() + v := ArtifactStorageResponse{ + TotalCount: Ptr(0), + } + want := `github.ArtifactStorageResponse{TotalCount:0}` + if got := v.String(); got != want { + t.Errorf("ArtifactStorageResponse.String = %v, want %v", got, want) + } +} + func TestAssignmentGrade_String(t *testing.T) { t.Parallel() v := AssignmentGrade{ diff --git a/github/orgs_artifacts.go b/github/orgs_artifacts.go new file mode 100644 index 00000000000..e9a3645d3b5 --- /dev/null +++ b/github/orgs_artifacts.go @@ -0,0 +1,139 @@ +// Copyright 2024 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" +) + +// ArtifactDeploymentRecord represents a GitHub artifact deployment record. +type ArtifactDeploymentRecord struct { + ID *int64 `json:"id,omitempty"` + Digest *string `json:"digest,omitempty"` + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + LogicalEnvironment *string `json:"logical_environment,omitempty"` + PhysicalEnvironment *string `json:"physical_environment,omitempty"` + Cluster *string `json:"cluster,omitempty"` + DeploymentName *string `json:"deployment_name,omitempty"` + Tags map[string]string `json:"tags,omitempty"` + Created *Timestamp `json:"created,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + AttestationID *int64 `json:"attestation_id,omitempty"` +} + +func (r ArtifactDeploymentRecord) String() string { return Stringify(r) } + +// ArtifactDeploymentResponse represents the response for deployment records. +type ArtifactDeploymentResponse struct { + TotalCount *int `json:"total_count,omitempty"` + DeploymentRecords []*ArtifactDeploymentRecord `json:"deployment_records,omitempty"` +} + +func (r ArtifactDeploymentResponse) String() string { return Stringify(r) } + +// ArtifactStorageRecord represents a GitHub artifact storage record. +type ArtifactStorageRecord struct { + Name *string `json:"name,omitempty"` + Digest *string `json:"digest,omitempty"` + ArtifactURL *string `json:"artifact_url,omitempty"` + RegistryURL *string `json:"registry_url,omitempty"` + Repository *string `json:"repository,omitempty"` + Status *string `json:"status,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (r ArtifactStorageRecord) String() string { return Stringify(r) } + +// ArtifactStorageResponse represents the response for storage records. +type ArtifactStorageResponse struct { + TotalCount *int `json:"total_count,omitempty"` + StorageRecords []*ArtifactStorageRecord `json:"storage_records,omitempty"` +} + +func (r ArtifactStorageResponse) String() string { return Stringify(r) } + +// CreateArtifactDeploymentRecord creates an artifact deployment record for an organization. +// +// GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#create-an-artifact-deployment-record +// +//meta:operation POST /orgs/{org}/artifacts/metadata/deployment-record +func (s *OrganizationsService) CreateArtifactDeploymentRecord(ctx context.Context, org string, record *ArtifactDeploymentRecord) (*ArtifactDeploymentResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/artifacts/metadata/deployment-record", org) + req, err := s.client.NewRequest("POST", u, record) + if err != nil { + return nil, nil, err + } + v := new(ArtifactDeploymentResponse) + resp, err := s.client.Do(ctx, req, v) + return v, resp, err +} + +// SetClusterDeploymentRecords sets deployment records for a given cluster. +// +// GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#set-cluster-deployment-records +// +//meta:operation POST /orgs/{org}/artifacts/metadata/deployment-record/cluster/{cluster} +func (s *OrganizationsService) SetClusterDeploymentRecords(ctx context.Context, org, cluster string, record *ArtifactDeploymentRecord) (*ArtifactDeploymentResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/artifacts/metadata/deployment-record/cluster/%v", org, cluster) + req, err := s.client.NewRequest("POST", u, record) + if err != nil { + return nil, nil, err + } + v := new(ArtifactDeploymentResponse) + resp, err := s.client.Do(ctx, req, v) + return v, resp, err +} + +// CreateArtifactStorageRecord creates metadata storage records for artifacts. +// +// GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#create-artifact-metadata-storage-record +// +//meta:operation POST /orgs/{org}/artifacts/metadata/storage-record +func (s *OrganizationsService) CreateArtifactStorageRecord(ctx context.Context, org string, record *ArtifactStorageRecord) (*ArtifactStorageResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/artifacts/metadata/storage-record", org) + req, err := s.client.NewRequest("POST", u, record) + if err != nil { + return nil, nil, err + } + v := new(ArtifactStorageResponse) + resp, err := s.client.Do(ctx, req, v) + return v, resp, err +} + +// ListArtifactDeploymentRecords lists deployment records for an artifact metadata. +// +// GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-deployment-records +// +//meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/deployment-records +func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context, org, subjectDigest string) (*ArtifactDeploymentResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/deployment-records", org, subjectDigest) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + v := new(ArtifactDeploymentResponse) + resp, err := s.client.Do(ctx, req, v) + return v, resp, err +} + +// ListArtifactStorageRecords lists artifact storage records with a given subject digest. +// +// GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-storage-records +// +//meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/storage-records +func (s *OrganizationsService) ListArtifactStorageRecords(ctx context.Context, org, subjectDigest string) (*ArtifactStorageResponse, *Response, error) { + u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/storage-records", org, subjectDigest) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + v := new(ArtifactStorageResponse) + resp, err := s.client.Do(ctx, req, v) + return v, resp, err +} diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go new file mode 100644 index 00000000000..ef1c1bb6c22 --- /dev/null +++ b/github/orgs_artifacts_test.go @@ -0,0 +1,145 @@ +// Copyright 2024 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 ( + "fmt" + "net/http" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestOrganizationsService_CreateArtifactDeploymentRecord(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ArtifactDeploymentRecord{Name: Ptr("test-n")} + + mux.HandleFunc("/orgs/o/artifacts/metadata/deployment-record", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + testJSONMarshal(t, input, `{"name":"test-n"}`) + fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) + }) + + ctx := t.Context() + got, _, err := client.Organizations.CreateArtifactDeploymentRecord(ctx, "o", input) + if err != nil { + t.Errorf("CreateArtifactDeploymentRecord returned error: %v", err) + } + + want := &ArtifactDeploymentResponse{ + TotalCount: Ptr(1), + DeploymentRecords: []*ArtifactDeploymentRecord{{ID: Ptr(int64(1))}}, + } + if !cmp.Equal(got, want) { + t.Errorf("CreateArtifactDeploymentRecord returned %+v, want %+v", got, want) + } +} + +func TestOrganizationsService_SetClusterDeploymentRecords(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ArtifactDeploymentRecord{Name: Ptr("cluster-deploy")} + + mux.HandleFunc("/orgs/o/artifacts/metadata/deployment-record/cluster/c1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":2}]}`) + }) + + ctx := t.Context() + got, _, err := client.Organizations.SetClusterDeploymentRecords(ctx, "o", "c1", input) + if err != nil { + t.Errorf("SetClusterDeploymentRecords returned error: %v", err) + } + + want := &ArtifactDeploymentResponse{ + TotalCount: Ptr(1), + DeploymentRecords: []*ArtifactDeploymentRecord{{ID: Ptr(int64(2))}}, + } + if !cmp.Equal(got, want) { + t.Errorf("SetClusterDeploymentRecords returned %+v, want %+v", got, want) + } +} + +func TestOrganizationsService_ListArtifactDeploymentRecords(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/artifacts/d/metadata/deployment-records", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) + }) + + ctx := t.Context() + got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d") + if err != nil { + t.Errorf("ListArtifactDeploymentRecords returned error: %v", err) + } + + want := &ArtifactDeploymentResponse{ + TotalCount: Ptr(1), + DeploymentRecords: []*ArtifactDeploymentRecord{{ID: Ptr(int64(1))}}, + } + if !cmp.Equal(got, want) { + t.Errorf("ListArtifactDeploymentRecords returned %+v, want %+v", got, want) + } +} + +func TestOrganizationsService_CreateArtifactStorageRecord(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &ArtifactStorageRecord{Name: Ptr("s-test")} + + mux.HandleFunc("/orgs/o/artifacts/metadata/storage-record", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"s-test"}]}`) + }) + + ctx := t.Context() + got, _, err := client.Organizations.CreateArtifactStorageRecord(ctx, "o", input) + if err != nil { + t.Errorf("CreateArtifactStorageRecord returned error: %v", err) + } + + want := &ArtifactStorageResponse{ + TotalCount: Ptr(1), + StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("s-test")}}, + } + if !cmp.Equal(got, want) { + t.Errorf("CreateArtifactStorageRecord returned %+v, want %+v", got, want) + } +} + +func TestOrganizationsService_ArtifactMetadata_InvalidOrg(t *testing.T) { + t.Parallel() + client, _, _ := setup(t) + + ctx := t.Context() + _, _, err := client.Organizations.CreateArtifactDeploymentRecord(ctx, "%", nil) + testURLParseError(t, err) +} + +func TestArtifactDeploymentRecord_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &ArtifactDeploymentRecord{}, "{}") + + u := &ArtifactDeploymentRecord{ + ID: Ptr(int64(1)), + Name: Ptr("n"), + Status: Ptr("s"), + } + + want := `{ + "id": 1, + "name": "n", + "status": "s" + }` + + testJSONMarshal(t, u, want) +} From 927c77b1da7c47c2c4b441cc36b9f7b471050dfc Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Tue, 27 Jan 2026 17:29:33 +0530 Subject: [PATCH 2/6] feat(orgs): add artifact metadata endpoints --- github/orgs_artifacts.go | 16 ++++++++++++++-- github/orgs_artifacts_test.go | 28 +++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/github/orgs_artifacts.go b/github/orgs_artifacts.go index e9a3645d3b5..cc385d09cd7 100644 --- a/github/orgs_artifacts.go +++ b/github/orgs_artifacts.go @@ -111,12 +111,18 @@ func (s *OrganizationsService) CreateArtifactStorageRecord(ctx context.Context, // GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-deployment-records // //meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/deployment-records -func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context, org, subjectDigest string) (*ArtifactDeploymentResponse, *Response, error) { +func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*ArtifactDeploymentResponse, *Response, error) { u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/deployment-records", org, subjectDigest) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } + v := new(ArtifactDeploymentResponse) resp, err := s.client.Do(ctx, req, v) return v, resp, err @@ -127,12 +133,18 @@ func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context // GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-storage-records // //meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/storage-records -func (s *OrganizationsService) ListArtifactStorageRecords(ctx context.Context, org, subjectDigest string) (*ArtifactStorageResponse, *Response, error) { +func (s *OrganizationsService) ListArtifactStorageRecords(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*ArtifactStorageResponse, *Response, error) { u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/storage-records", org, subjectDigest) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, nil, err } + v := new(ArtifactStorageResponse) resp, err := s.client.Do(ctx, req, v) return v, resp, err diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go index ef1c1bb6c22..1672d91cf9b 100644 --- a/github/orgs_artifacts_test.go +++ b/github/orgs_artifacts_test.go @@ -72,11 +72,13 @@ func TestOrganizationsService_ListArtifactDeploymentRecords(t *testing.T) { mux.HandleFunc("/orgs/o/artifacts/d/metadata/deployment-records", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") + testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) }) ctx := t.Context() - got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d") + opts := &ListOptions{Page: 2} + got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d", opts) if err != nil { t.Errorf("ListArtifactDeploymentRecords returned error: %v", err) } @@ -116,6 +118,30 @@ func TestOrganizationsService_CreateArtifactStorageRecord(t *testing.T) { } } +func TestOrganizationsService_ListArtifactStorageRecords(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/artifacts/d/metadata/storage-records", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"s-test"}]}`) + }) + + ctx := t.Context() + got, _, err := client.Organizations.ListArtifactStorageRecords(ctx, "o", "d", nil) + if err != nil { + t.Errorf("ListArtifactStorageRecords returned error: %v", err) + } + + want := &ArtifactStorageResponse{ + TotalCount: Ptr(1), + StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("s-test")}}, + } + if !cmp.Equal(got, want) { + t.Errorf("ListArtifactStorageRecords returned %+v, want %+v", got, want) + } +} + func TestOrganizationsService_ArtifactMetadata_InvalidOrg(t *testing.T) { t.Parallel() client, _, _ := setup(t) From 8c406536e3863395b954e5fb55e9d3ecc0b49a65 Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Tue, 27 Jan 2026 20:10:21 +0530 Subject: [PATCH 3/6] feat: add artifact metadata support for orgs with 100% test coverage --- github/orgs_artifacts_test.go | 36 ++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go index 1672d91cf9b..0e0741fa1f7 100644 --- a/github/orgs_artifacts_test.go +++ b/github/orgs_artifacts_test.go @@ -145,10 +145,28 @@ func TestOrganizationsService_ListArtifactStorageRecords(t *testing.T) { func TestOrganizationsService_ArtifactMetadata_InvalidOrg(t *testing.T) { t.Parallel() client, _, _ := setup(t) - ctx := t.Context() + _, _, err := client.Organizations.CreateArtifactDeploymentRecord(ctx, "%", nil) testURLParseError(t, err) + + _, _, err = client.Organizations.SetClusterDeploymentRecords(ctx, "%", "c", nil) + testURLParseError(t, err) + + _, _, err = client.Organizations.CreateArtifactStorageRecord(ctx, "%", nil) + testURLParseError(t, err) + + _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d", nil) + testURLParseError(t, err) + + _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d", &ListOptions{}) + testURLParseError(t, err) + + _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d", nil) + testURLParseError(t, err) + + _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d", &ListOptions{}) + testURLParseError(t, err) } func TestArtifactDeploymentRecord_Marshal(t *testing.T) { @@ -169,3 +187,19 @@ func TestArtifactDeploymentRecord_Marshal(t *testing.T) { testJSONMarshal(t, u, want) } + +func TestArtifactMetadata_String(t *testing.T) { + t.Parallel() + + r1 := ArtifactDeploymentRecord{Name: Ptr("n")} + _ = r1.String() + + r2 := ArtifactDeploymentResponse{TotalCount: Ptr(1)} + _ = r2.String() + + r3 := ArtifactStorageRecord{Name: Ptr("n")} + _ = r3.String() + + r4 := ArtifactStorageResponse{TotalCount: Ptr(1)} + _ = r4.String() +} From abf2b4420bf62037fcc6496d19852afcc9d2593a Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Tue, 27 Jan 2026 21:07:44 +0530 Subject: [PATCH 4/6] feat: add artifact metadata support for orgs with 99.1% coverage for github --- github/orgs_artifacts.go | 2 +- github/orgs_artifacts_test.go | 18 +----------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/github/orgs_artifacts.go b/github/orgs_artifacts.go index cc385d09cd7..31ef64dd611 100644 --- a/github/orgs_artifacts.go +++ b/github/orgs_artifacts.go @@ -1,4 +1,4 @@ -// Copyright 2024 The go-github AUTHORS. All rights reserved. +// Copyright 2026 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. diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go index 0e0741fa1f7..00f8a452f72 100644 --- a/github/orgs_artifacts_test.go +++ b/github/orgs_artifacts_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 The go-github AUTHORS. All rights reserved. +// Copyright 2026 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. @@ -187,19 +187,3 @@ func TestArtifactDeploymentRecord_Marshal(t *testing.T) { testJSONMarshal(t, u, want) } - -func TestArtifactMetadata_String(t *testing.T) { - t.Parallel() - - r1 := ArtifactDeploymentRecord{Name: Ptr("n")} - _ = r1.String() - - r2 := ArtifactDeploymentResponse{TotalCount: Ptr(1)} - _ = r2.String() - - r3 := ArtifactStorageRecord{Name: Ptr("n")} - _ = r3.String() - - r4 := ArtifactStorageResponse{TotalCount: Ptr(1)} - _ = r4.String() -} From 6e34124bdb2bf7bdd35383136d23e4e44fff1618 Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Tue, 27 Jan 2026 21:45:05 +0530 Subject: [PATCH 5/6] feat: add artifact metadata support for orgs with 99.1% coverage for github final --- github/orgs_artifacts.go | 12 ++---------- github/orgs_artifacts_test.go | 16 ++++------------ 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/github/orgs_artifacts.go b/github/orgs_artifacts.go index 31ef64dd611..4a26baa92f0 100644 --- a/github/orgs_artifacts.go +++ b/github/orgs_artifacts.go @@ -111,12 +111,8 @@ func (s *OrganizationsService) CreateArtifactStorageRecord(ctx context.Context, // GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-deployment-records // //meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/deployment-records -func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*ArtifactDeploymentResponse, *Response, error) { +func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context, org, subjectDigest string) (*ArtifactDeploymentResponse, *Response, error) { u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/deployment-records", org, subjectDigest) - u, err := addOptions(u, opts) - if err != nil { - return nil, nil, err - } req, err := s.client.NewRequest("GET", u, nil) if err != nil { @@ -133,12 +129,8 @@ func (s *OrganizationsService) ListArtifactDeploymentRecords(ctx context.Context // GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#list-artifact-storage-records // //meta:operation GET /orgs/{org}/artifacts/{subject_digest}/metadata/storage-records -func (s *OrganizationsService) ListArtifactStorageRecords(ctx context.Context, org, subjectDigest string, opts *ListOptions) (*ArtifactStorageResponse, *Response, error) { +func (s *OrganizationsService) ListArtifactStorageRecords(ctx context.Context, org, subjectDigest string) (*ArtifactStorageResponse, *Response, error) { u := fmt.Sprintf("orgs/%v/artifacts/%v/metadata/storage-records", org, subjectDigest) - u, err := addOptions(u, opts) - if err != nil { - return nil, nil, err - } req, err := s.client.NewRequest("GET", u, nil) if err != nil { diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go index 00f8a452f72..231ebe6111a 100644 --- a/github/orgs_artifacts_test.go +++ b/github/orgs_artifacts_test.go @@ -72,13 +72,11 @@ func TestOrganizationsService_ListArtifactDeploymentRecords(t *testing.T) { mux.HandleFunc("/orgs/o/artifacts/d/metadata/deployment-records", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - testFormValues(t, r, values{"page": "2"}) fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) }) ctx := t.Context() - opts := &ListOptions{Page: 2} - got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d", opts) + got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d") if err != nil { t.Errorf("ListArtifactDeploymentRecords returned error: %v", err) } @@ -128,7 +126,7 @@ func TestOrganizationsService_ListArtifactStorageRecords(t *testing.T) { }) ctx := t.Context() - got, _, err := client.Organizations.ListArtifactStorageRecords(ctx, "o", "d", nil) + got, _, err := client.Organizations.ListArtifactStorageRecords(ctx, "o", "d") if err != nil { t.Errorf("ListArtifactStorageRecords returned error: %v", err) } @@ -156,16 +154,10 @@ func TestOrganizationsService_ArtifactMetadata_InvalidOrg(t *testing.T) { _, _, err = client.Organizations.CreateArtifactStorageRecord(ctx, "%", nil) testURLParseError(t, err) - _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d", nil) + _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d") testURLParseError(t, err) - _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d", &ListOptions{}) - testURLParseError(t, err) - - _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d", nil) - testURLParseError(t, err) - - _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d", &ListOptions{}) + _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d") testURLParseError(t, err) } From 39a1ebc49d318ac1ad708264cfdcc056d646594e Mon Sep 17 00:00:00 2001 From: maishivamhoo123 Date: Wed, 28 Jan 2026 14:55:44 +0530 Subject: [PATCH 6/6] feat: add artifact metadata support for orgs with 99.1% coverage for github final changes --- github/github-accessors.go | 72 +++++++++++++++++- github/github-accessors_test.go | 98 ++++++++++++++++++++++-- github/github-stringify_test.go | 43 ++++++++--- github/orgs_artifacts.go | 40 +++++++--- github/orgs_artifacts_test.go | 131 +++++++++++++++----------------- 5 files changed, 282 insertions(+), 102 deletions(-) diff --git a/github/github-accessors.go b/github/github-accessors.go index a3c701e461d..3ef4f2a792c 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1150,12 +1150,12 @@ func (a *ArtifactDeploymentRecord) GetCluster() string { return *a.Cluster } -// GetCreated returns the Created field if it's non-nil, zero value otherwise. -func (a *ArtifactDeploymentRecord) GetCreated() Timestamp { - if a == nil || a.Created == nil { +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { return Timestamp{} } - return *a.Created + return *a.CreatedAt } // GetDeploymentName returns the DeploymentName field if it's non-nil, zero value otherwise. @@ -1174,6 +1174,14 @@ func (a *ArtifactDeploymentRecord) GetDigest() string { return *a.Digest } +// GetGithubRepository returns the GithubRepository field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetGithubRepository() string { + if a == nil || a.GithubRepository == nil { + return "" + } + return *a.GithubRepository +} + // GetID returns the ID field if it's non-nil, zero value otherwise. func (a *ArtifactDeploymentRecord) GetID() int64 { if a == nil || a.ID == nil { @@ -1230,6 +1238,14 @@ func (a *ArtifactDeploymentRecord) GetUpdatedAt() Timestamp { return *a.UpdatedAt } +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (a *ArtifactDeploymentRecord) GetVersion() string { + if a == nil || a.Version == nil { + return "" + } + return *a.Version +} + // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (a *ArtifactDeploymentResponse) GetTotalCount() int { if a == nil || a.TotalCount == nil { @@ -1294,6 +1310,22 @@ func (a *ArtifactStorageRecord) GetDigest() string { return *a.Digest } +// GetGithubRepository returns the GithubRepository field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetGithubRepository() string { + if a == nil || a.GithubRepository == nil { + return "" + } + return *a.GithubRepository +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + // GetName returns the Name field if it's non-nil, zero value otherwise. func (a *ArtifactStorageRecord) GetName() string { if a == nil || a.Name == nil { @@ -1302,6 +1334,14 @@ func (a *ArtifactStorageRecord) GetName() string { return *a.Name } +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetPath() string { + if a == nil || a.Path == nil { + return "" + } + return *a.Path +} + // GetRegistryURL returns the RegistryURL field if it's non-nil, zero value otherwise. func (a *ArtifactStorageRecord) GetRegistryURL() string { if a == nil || a.RegistryURL == nil { @@ -1334,6 +1374,14 @@ func (a *ArtifactStorageRecord) GetUpdatedAt() Timestamp { return *a.UpdatedAt } +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (a *ArtifactStorageRecord) GetVersion() string { + if a == nil || a.Version == nil { + return "" + } + return *a.Version +} + // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. func (a *ArtifactStorageResponse) GetTotalCount() int { if a == nil || a.TotalCount == nil { @@ -3142,6 +3190,22 @@ func (c *ClassroomUser) GetLogin() string { return *c.Login } +// GetLogicalEnvironment returns the LogicalEnvironment field if it's non-nil, zero value otherwise. +func (c *ClusterDeploymentRecordsRequest) GetLogicalEnvironment() string { + if c == nil || c.LogicalEnvironment == nil { + return "" + } + return *c.LogicalEnvironment +} + +// GetPhysicalEnvironment returns the PhysicalEnvironment field if it's non-nil, zero value otherwise. +func (c *ClusterDeploymentRecordsRequest) GetPhysicalEnvironment() string { + if c == nil || c.PhysicalEnvironment == nil { + return "" + } + return *c.PhysicalEnvironment +} + // GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. func (c *ClusterSSHKey) GetFingerprint() string { if c == nil || c.Fingerprint == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 63d55f5b757..584525cb240 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1490,15 +1490,15 @@ func TestArtifactDeploymentRecord_GetCluster(tt *testing.T) { a.GetCluster() } -func TestArtifactDeploymentRecord_GetCreated(tt *testing.T) { +func TestArtifactDeploymentRecord_GetCreatedAt(tt *testing.T) { tt.Parallel() var zeroValue Timestamp - a := &ArtifactDeploymentRecord{Created: &zeroValue} - a.GetCreated() + a := &ArtifactDeploymentRecord{CreatedAt: &zeroValue} + a.GetCreatedAt() a = &ArtifactDeploymentRecord{} - a.GetCreated() + a.GetCreatedAt() a = nil - a.GetCreated() + a.GetCreatedAt() } func TestArtifactDeploymentRecord_GetDeploymentName(tt *testing.T) { @@ -1523,6 +1523,17 @@ func TestArtifactDeploymentRecord_GetDigest(tt *testing.T) { a.GetDigest() } +func TestArtifactDeploymentRecord_GetGithubRepository(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{GithubRepository: &zeroValue} + a.GetGithubRepository() + a = &ArtifactDeploymentRecord{} + a.GetGithubRepository() + a = nil + a.GetGithubRepository() +} + func TestArtifactDeploymentRecord_GetID(tt *testing.T) { tt.Parallel() var zeroValue int64 @@ -1600,6 +1611,17 @@ func TestArtifactDeploymentRecord_GetUpdatedAt(tt *testing.T) { a.GetUpdatedAt() } +func TestArtifactDeploymentRecord_GetVersion(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactDeploymentRecord{Version: &zeroValue} + a.GetVersion() + a = &ArtifactDeploymentRecord{} + a.GetVersion() + a = nil + a.GetVersion() +} + func TestArtifactDeploymentResponse_GetTotalCount(tt *testing.T) { tt.Parallel() var zeroValue int @@ -1688,6 +1710,28 @@ func TestArtifactStorageRecord_GetDigest(tt *testing.T) { a.GetDigest() } +func TestArtifactStorageRecord_GetGithubRepository(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{GithubRepository: &zeroValue} + a.GetGithubRepository() + a = &ArtifactStorageRecord{} + a.GetGithubRepository() + a = nil + a.GetGithubRepository() +} + +func TestArtifactStorageRecord_GetID(tt *testing.T) { + tt.Parallel() + var zeroValue int64 + a := &ArtifactStorageRecord{ID: &zeroValue} + a.GetID() + a = &ArtifactStorageRecord{} + a.GetID() + a = nil + a.GetID() +} + func TestArtifactStorageRecord_GetName(tt *testing.T) { tt.Parallel() var zeroValue string @@ -1699,6 +1743,17 @@ func TestArtifactStorageRecord_GetName(tt *testing.T) { a.GetName() } +func TestArtifactStorageRecord_GetPath(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Path: &zeroValue} + a.GetPath() + a = &ArtifactStorageRecord{} + a.GetPath() + a = nil + a.GetPath() +} + func TestArtifactStorageRecord_GetRegistryURL(tt *testing.T) { tt.Parallel() var zeroValue string @@ -1743,6 +1798,17 @@ func TestArtifactStorageRecord_GetUpdatedAt(tt *testing.T) { a.GetUpdatedAt() } +func TestArtifactStorageRecord_GetVersion(tt *testing.T) { + tt.Parallel() + var zeroValue string + a := &ArtifactStorageRecord{Version: &zeroValue} + a.GetVersion() + a = &ArtifactStorageRecord{} + a.GetVersion() + a = nil + a.GetVersion() +} + func TestArtifactStorageResponse_GetTotalCount(tt *testing.T) { tt.Parallel() var zeroValue int @@ -4106,6 +4172,28 @@ func TestClassroomUser_GetLogin(tt *testing.T) { c.GetLogin() } +func TestClusterDeploymentRecordsRequest_GetLogicalEnvironment(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &ClusterDeploymentRecordsRequest{LogicalEnvironment: &zeroValue} + c.GetLogicalEnvironment() + c = &ClusterDeploymentRecordsRequest{} + c.GetLogicalEnvironment() + c = nil + c.GetLogicalEnvironment() +} + +func TestClusterDeploymentRecordsRequest_GetPhysicalEnvironment(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &ClusterDeploymentRecordsRequest{PhysicalEnvironment: &zeroValue} + c.GetPhysicalEnvironment() + c = &ClusterDeploymentRecordsRequest{} + c.GetPhysicalEnvironment() + c = nil + c.GetPhysicalEnvironment() +} + func TestClusterSSHKey_GetFingerprint(tt *testing.T) { tt.Parallel() var zeroValue string diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go index 67aae3d9915..718afcb36ce 100644 --- a/github/github-stringify_test.go +++ b/github/github-stringify_test.go @@ -121,16 +121,19 @@ func TestArtifactDeploymentRecord_String(t *testing.T) { ID: Ptr(int64(0)), Digest: Ptr(""), Name: Ptr(""), + Version: Ptr(""), Status: Ptr(""), LogicalEnvironment: Ptr(""), PhysicalEnvironment: Ptr(""), Cluster: Ptr(""), DeploymentName: Ptr(""), - Created: &Timestamp{}, - UpdatedAt: &Timestamp{}, + RuntimeRisks: []string{""}, + GithubRepository: Ptr(""), AttestationID: Ptr(int64(0)), + CreatedAt: &Timestamp{}, + UpdatedAt: &Timestamp{}, } - want := `github.ArtifactDeploymentRecord{ID:0, Digest:"", Name:"", Status:"", LogicalEnvironment:"", PhysicalEnvironment:"", Cluster:"", DeploymentName:"", Created:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, AttestationID:0}` + want := `github.ArtifactDeploymentRecord{ID:0, Digest:"", Name:"", Version:"", Status:"", LogicalEnvironment:"", PhysicalEnvironment:"", Cluster:"", DeploymentName:"", RuntimeRisks:[""], GithubRepository:"", AttestationID:0, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("ArtifactDeploymentRecord.String = %v, want %v", got, want) } @@ -162,16 +165,20 @@ func TestArtifactPeriod_String(t *testing.T) { func TestArtifactStorageRecord_String(t *testing.T) { t.Parallel() v := ArtifactStorageRecord{ - Name: Ptr(""), - Digest: Ptr(""), - ArtifactURL: Ptr(""), - RegistryURL: Ptr(""), - Repository: Ptr(""), - Status: Ptr(""), - CreatedAt: &Timestamp{}, - UpdatedAt: &Timestamp{}, + ID: Ptr(int64(0)), + Name: Ptr(""), + Digest: Ptr(""), + Version: Ptr(""), + ArtifactURL: Ptr(""), + Path: Ptr(""), + RegistryURL: Ptr(""), + Repository: Ptr(""), + Status: Ptr(""), + GithubRepository: Ptr(""), + CreatedAt: &Timestamp{}, + UpdatedAt: &Timestamp{}, } - want := `github.ArtifactStorageRecord{Name:"", Digest:"", ArtifactURL:"", RegistryURL:"", Repository:"", Status:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` + want := `github.ArtifactStorageRecord{ID:0, Name:"", Digest:"", Version:"", ArtifactURL:"", Path:"", RegistryURL:"", Repository:"", Status:"", GithubRepository:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}}` if got := v.String(); got != want { t.Errorf("ArtifactStorageRecord.String = %v, want %v", got, want) } @@ -387,6 +394,18 @@ func TestClassroomUser_String(t *testing.T) { } } +func TestClusterDeploymentRecordsRequest_String(t *testing.T) { + t.Parallel() + v := ClusterDeploymentRecordsRequest{ + LogicalEnvironment: Ptr(""), + PhysicalEnvironment: Ptr(""), + } + want := `github.ClusterDeploymentRecordsRequest{LogicalEnvironment:"", PhysicalEnvironment:""}` + if got := v.String(); got != want { + t.Errorf("ClusterDeploymentRecordsRequest.String = %v, want %v", got, want) + } +} + func TestCodeOfConduct_String(t *testing.T) { t.Parallel() v := CodeOfConduct{ diff --git a/github/orgs_artifacts.go b/github/orgs_artifacts.go index 4a26baa92f0..ac17ef371a2 100644 --- a/github/orgs_artifacts.go +++ b/github/orgs_artifacts.go @@ -15,15 +15,18 @@ type ArtifactDeploymentRecord struct { ID *int64 `json:"id,omitempty"` Digest *string `json:"digest,omitempty"` Name *string `json:"name,omitempty"` + Version *string `json:"version,omitempty"` Status *string `json:"status,omitempty"` LogicalEnvironment *string `json:"logical_environment,omitempty"` PhysicalEnvironment *string `json:"physical_environment,omitempty"` Cluster *string `json:"cluster,omitempty"` DeploymentName *string `json:"deployment_name,omitempty"` Tags map[string]string `json:"tags,omitempty"` - Created *Timestamp `json:"created,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` + RuntimeRisks []string `json:"runtime_risks,omitempty"` + GithubRepository *string `json:"github_repository,omitempty"` AttestationID *int64 `json:"attestation_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` } func (r ArtifactDeploymentRecord) String() string { return Stringify(r) } @@ -36,16 +39,29 @@ type ArtifactDeploymentResponse struct { func (r ArtifactDeploymentResponse) String() string { return Stringify(r) } +// ClusterDeploymentRecordsRequest represents the request body for setting cluster deployment records. +type ClusterDeploymentRecordsRequest struct { + LogicalEnvironment *string `json:"logical_environment,omitempty"` + PhysicalEnvironment *string `json:"physical_environment,omitempty"` + Deployments []*ArtifactDeploymentRecord `json:"deployments,omitempty"` +} + +func (r ClusterDeploymentRecordsRequest) String() string { return Stringify(r) } + // ArtifactStorageRecord represents a GitHub artifact storage record. type ArtifactStorageRecord struct { - Name *string `json:"name,omitempty"` - Digest *string `json:"digest,omitempty"` - ArtifactURL *string `json:"artifact_url,omitempty"` - RegistryURL *string `json:"registry_url,omitempty"` - Repository *string `json:"repository,omitempty"` - Status *string `json:"status,omitempty"` - CreatedAt *Timestamp `json:"created_at,omitempty"` - UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Digest *string `json:"digest,omitempty"` + Version *string `json:"version,omitempty"` + ArtifactURL *string `json:"artifact_url,omitempty"` + Path *string `json:"path,omitempty"` + RegistryURL *string `json:"registry_url,omitempty"` + Repository *string `json:"repository,omitempty"` + Status *string `json:"status,omitempty"` + GithubRepository *string `json:"github_repository,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` } func (r ArtifactStorageRecord) String() string { return Stringify(r) } @@ -79,9 +95,9 @@ func (s *OrganizationsService) CreateArtifactDeploymentRecord(ctx context.Contex // GitHub API docs: https://docs.github.com/rest/orgs/artifact-metadata#set-cluster-deployment-records // //meta:operation POST /orgs/{org}/artifacts/metadata/deployment-record/cluster/{cluster} -func (s *OrganizationsService) SetClusterDeploymentRecords(ctx context.Context, org, cluster string, record *ArtifactDeploymentRecord) (*ArtifactDeploymentResponse, *Response, error) { +func (s *OrganizationsService) SetClusterDeploymentRecords(ctx context.Context, org, cluster string, request *ClusterDeploymentRecordsRequest) (*ArtifactDeploymentResponse, *Response, error) { u := fmt.Sprintf("orgs/%v/artifacts/metadata/deployment-record/cluster/%v", org, cluster) - req, err := s.client.NewRequest("POST", u, record) + req, err := s.client.NewRequest("POST", u, request) if err != nil { return nil, nil, err } diff --git a/github/orgs_artifacts_test.go b/github/orgs_artifacts_test.go index 231ebe6111a..606f7238387 100644 --- a/github/orgs_artifacts_test.go +++ b/github/orgs_artifacts_test.go @@ -17,11 +17,23 @@ func TestOrganizationsService_CreateArtifactDeploymentRecord(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - input := &ArtifactDeploymentRecord{Name: Ptr("test-n")} + input := &ArtifactDeploymentRecord{ + Name: Ptr("test-n"), + Digest: Ptr("sha256:123"), + Version: Ptr("v1.0.0"), + Status: Ptr("deployed"), + LogicalEnvironment: Ptr("prod"), + DeploymentName: Ptr("dep-1"), + RuntimeRisks: []string{"critical-resource", "internet-exposed"}, + GithubRepository: Ptr("octo-org/octo-repo"), + Tags: map[string]string{ + "data-access": "sensitive", + }, + } mux.HandleFunc("/orgs/o/artifacts/metadata/deployment-record", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") - testJSONMarshal(t, input, `{"name":"test-n"}`) + testJSONMarshal(t, input, `{"digest":"sha256:123","name":"test-n","version":"v1.0.0","status":"deployed","logical_environment":"prod","deployment_name":"dep-1","tags":{"data-access":"sensitive"},"runtime_risks":["critical-resource","internet-exposed"],"github_repository":"octo-org/octo-repo"}`) fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) }) @@ -44,10 +56,21 @@ func TestOrganizationsService_SetClusterDeploymentRecords(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - input := &ArtifactDeploymentRecord{Name: Ptr("cluster-deploy")} + input := &ClusterDeploymentRecordsRequest{ + LogicalEnvironment: Ptr("prod"), + PhysicalEnvironment: Ptr("pacific-east"), + Deployments: []*ArtifactDeploymentRecord{ + { + Name: Ptr("awesome-image"), + Version: Ptr("v2.0"), + Status: Ptr("deployed"), + }, + }, + } mux.HandleFunc("/orgs/o/artifacts/metadata/deployment-record/cluster/c1", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") + testJSONMarshal(t, input, `{"logical_environment":"prod","physical_environment":"pacific-east","deployments":[{"name":"awesome-image","version":"v2.0","status":"deployed"}]}`) fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":2}]}`) }) @@ -66,53 +89,63 @@ func TestOrganizationsService_SetClusterDeploymentRecords(t *testing.T) { } } -func TestOrganizationsService_ListArtifactDeploymentRecords(t *testing.T) { +func TestOrganizationsService_CreateArtifactStorageRecord(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - mux.HandleFunc("/orgs/o/artifacts/d/metadata/deployment-records", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "GET") - fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1}]}`) + input := &ArtifactStorageRecord{ + Name: Ptr("libfoo"), + Version: Ptr("v1.2.3"), + Path: Ptr("target/libs"), + GithubRepository: Ptr("org/repo"), + RegistryURL: Ptr("https://reg.example.com"), + Status: Ptr("active"), + } + + mux.HandleFunc("/orgs/o/artifacts/metadata/storage-record", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + testJSONMarshal(t, input, `{"name":"libfoo","version":"v1.2.3","path":"target/libs","registry_url":"https://reg.example.com","status":"active","github_repository":"org/repo"}`) + fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"libfoo"}]}`) }) ctx := t.Context() - got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "d") + got, _, err := client.Organizations.CreateArtifactStorageRecord(ctx, "o", input) if err != nil { - t.Errorf("ListArtifactDeploymentRecords returned error: %v", err) + t.Errorf("CreateArtifactStorageRecord returned error: %v", err) } - want := &ArtifactDeploymentResponse{ - TotalCount: Ptr(1), - DeploymentRecords: []*ArtifactDeploymentRecord{{ID: Ptr(int64(1))}}, + want := &ArtifactStorageResponse{ + TotalCount: Ptr(1), + StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("libfoo")}}, } if !cmp.Equal(got, want) { - t.Errorf("ListArtifactDeploymentRecords returned %+v, want %+v", got, want) + t.Errorf("CreateArtifactStorageRecord returned %+v, want %+v", got, want) } } -func TestOrganizationsService_CreateArtifactStorageRecord(t *testing.T) { +func TestOrganizationsService_ListArtifactDeploymentRecords(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - input := &ArtifactStorageRecord{Name: Ptr("s-test")} - - mux.HandleFunc("/orgs/o/artifacts/metadata/storage-record", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, "POST") - fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"s-test"}]}`) + mux.HandleFunc("/orgs/o/artifacts/sha256:abc/metadata/deployment-records", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"total_count":1,"deployment_records":[{"id":1, "runtime_risks": ["sensitive-data"]}]}`) }) ctx := t.Context() - got, _, err := client.Organizations.CreateArtifactStorageRecord(ctx, "o", input) + got, _, err := client.Organizations.ListArtifactDeploymentRecords(ctx, "o", "sha256:abc") if err != nil { - t.Errorf("CreateArtifactStorageRecord returned error: %v", err) + t.Errorf("ListArtifactDeploymentRecords returned error: %v", err) } - want := &ArtifactStorageResponse{ - TotalCount: Ptr(1), - StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("s-test")}}, + want := &ArtifactDeploymentResponse{ + TotalCount: Ptr(1), + DeploymentRecords: []*ArtifactDeploymentRecord{ + {ID: Ptr(int64(1)), RuntimeRisks: []string{"sensitive-data"}}, + }, } if !cmp.Equal(got, want) { - t.Errorf("CreateArtifactStorageRecord returned %+v, want %+v", got, want) + t.Errorf("ListArtifactDeploymentRecords returned %+v, want %+v", got, want) } } @@ -120,62 +153,22 @@ func TestOrganizationsService_ListArtifactStorageRecords(t *testing.T) { t.Parallel() client, mux, _ := setup(t) - mux.HandleFunc("/orgs/o/artifacts/d/metadata/storage-records", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/orgs/o/artifacts/sha256:abc/metadata/storage-records", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"s-test"}]}`) + fmt.Fprint(w, `{"total_count":1,"storage_records":[{"name":"libfoo"}]}`) }) ctx := t.Context() - got, _, err := client.Organizations.ListArtifactStorageRecords(ctx, "o", "d") + got, _, err := client.Organizations.ListArtifactStorageRecords(ctx, "o", "sha256:abc") if err != nil { t.Errorf("ListArtifactStorageRecords returned error: %v", err) } want := &ArtifactStorageResponse{ TotalCount: Ptr(1), - StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("s-test")}}, + StorageRecords: []*ArtifactStorageRecord{{Name: Ptr("libfoo")}}, } if !cmp.Equal(got, want) { t.Errorf("ListArtifactStorageRecords returned %+v, want %+v", got, want) } } - -func TestOrganizationsService_ArtifactMetadata_InvalidOrg(t *testing.T) { - t.Parallel() - client, _, _ := setup(t) - ctx := t.Context() - - _, _, err := client.Organizations.CreateArtifactDeploymentRecord(ctx, "%", nil) - testURLParseError(t, err) - - _, _, err = client.Organizations.SetClusterDeploymentRecords(ctx, "%", "c", nil) - testURLParseError(t, err) - - _, _, err = client.Organizations.CreateArtifactStorageRecord(ctx, "%", nil) - testURLParseError(t, err) - - _, _, err = client.Organizations.ListArtifactDeploymentRecords(ctx, "%", "d") - testURLParseError(t, err) - - _, _, err = client.Organizations.ListArtifactStorageRecords(ctx, "%", "d") - testURLParseError(t, err) -} - -func TestArtifactDeploymentRecord_Marshal(t *testing.T) { - t.Parallel() - testJSONMarshal(t, &ArtifactDeploymentRecord{}, "{}") - - u := &ArtifactDeploymentRecord{ - ID: Ptr(int64(1)), - Name: Ptr("n"), - Status: Ptr("s"), - } - - want := `{ - "id": 1, - "name": "n", - "status": "s" - }` - - testJSONMarshal(t, u, want) -}