diff --git a/github/github-accessors.go b/github/github-accessors.go index d94949d8f29..6e2bbaf93bd 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -6310,6 +6310,14 @@ func (c *CreateEvent) GetSender() *User { return c.Sender } +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (c *CreateOrganizationPrivateRegistry) GetUsername() string { + if c == nil || c.Username == nil { + return "" + } + return *c.Username +} + // GetEmail returns the Email field if it's non-nil, zero value otherwise. func (c *CreateOrgInvitationOptions) GetEmail() string { if c == nil || c.Email == nil { @@ -18694,6 +18702,62 @@ func (p *PreReceiveHook) GetName() string { return *p.Name } +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (p *PrivateRegistries) GetTotalCount() int { + if p == nil || p.TotalCount == nil { + return 0 + } + return *p.TotalCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PrivateRegistry) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PrivateRegistry) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetRegistryType returns the RegistryType field if it's non-nil, zero value otherwise. +func (p *PrivateRegistry) GetRegistryType() string { + if p == nil || p.RegistryType == nil { + return "" + } + return *p.RegistryType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PrivateRegistry) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (p *PrivateRegistry) GetUsername() string { + if p == nil || p.Username == nil { + return "" + } + return *p.Username +} + +// GetVisibility returns the Visibility field. +func (p *PrivateRegistry) GetVisibility() *PrivateRegistryVisibility { + if p == nil { + return nil + } + return p.Visibility +} + // GetHRef returns the HRef field if it's non-nil, zero value otherwise. func (p *PRLink) GetHRef() string { if p == nil || p.HRef == nil { @@ -28854,6 +28918,54 @@ func (u *UpdateEnterpriseRunnerGroupRequest) GetVisibility() string { return *u.Visibility } +// GetEncryptedValue returns the EncryptedValue field if it's non-nil, zero value otherwise. +func (u *UpdateOrganizationPrivateRegistry) GetEncryptedValue() string { + if u == nil || u.EncryptedValue == nil { + return "" + } + return *u.EncryptedValue +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (u *UpdateOrganizationPrivateRegistry) GetKeyID() string { + if u == nil || u.KeyID == nil { + return "" + } + return *u.KeyID +} + +// GetRegistryType returns the RegistryType field if it's non-nil, zero value otherwise. +func (u *UpdateOrganizationPrivateRegistry) GetRegistryType() string { + if u == nil || u.RegistryType == nil { + return "" + } + return *u.RegistryType +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UpdateOrganizationPrivateRegistry) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetUsername returns the Username field if it's non-nil, zero value otherwise. +func (u *UpdateOrganizationPrivateRegistry) GetUsername() string { + if u == nil || u.Username == nil { + return "" + } + return *u.Username +} + +// GetVisibility returns the Visibility field. +func (u *UpdateOrganizationPrivateRegistry) GetVisibility() *PrivateRegistryVisibility { + if u == nil { + return nil + } + return u.Visibility +} + // GetForce returns the Force field if it's non-nil, zero value otherwise. func (u *UpdateRef) GetForce() bool { if u == nil || u.Force == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 3d1cf6e3b13..32d44331180 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -8234,6 +8234,17 @@ func TestCreateEvent_GetSender(tt *testing.T) { c.GetSender() } +func TestCreateOrganizationPrivateRegistry_GetUsername(tt *testing.T) { + tt.Parallel() + var zeroValue string + c := &CreateOrganizationPrivateRegistry{Username: &zeroValue} + c.GetUsername() + c = &CreateOrganizationPrivateRegistry{} + c.GetUsername() + c = nil + c.GetUsername() +} + func TestCreateOrgInvitationOptions_GetEmail(tt *testing.T) { tt.Parallel() var zeroValue string @@ -24302,6 +24313,80 @@ func TestPreReceiveHook_GetName(tt *testing.T) { p.GetName() } +func TestPrivateRegistries_GetTotalCount(tt *testing.T) { + tt.Parallel() + var zeroValue int + p := &PrivateRegistries{TotalCount: &zeroValue} + p.GetTotalCount() + p = &PrivateRegistries{} + p.GetTotalCount() + p = nil + p.GetTotalCount() +} + +func TestPrivateRegistry_GetCreatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + p := &PrivateRegistry{CreatedAt: &zeroValue} + p.GetCreatedAt() + p = &PrivateRegistry{} + p.GetCreatedAt() + p = nil + p.GetCreatedAt() +} + +func TestPrivateRegistry_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + p := &PrivateRegistry{Name: &zeroValue} + p.GetName() + p = &PrivateRegistry{} + p.GetName() + p = nil + p.GetName() +} + +func TestPrivateRegistry_GetRegistryType(tt *testing.T) { + tt.Parallel() + var zeroValue string + p := &PrivateRegistry{RegistryType: &zeroValue} + p.GetRegistryType() + p = &PrivateRegistry{} + p.GetRegistryType() + p = nil + p.GetRegistryType() +} + +func TestPrivateRegistry_GetUpdatedAt(tt *testing.T) { + tt.Parallel() + var zeroValue Timestamp + p := &PrivateRegistry{UpdatedAt: &zeroValue} + p.GetUpdatedAt() + p = &PrivateRegistry{} + p.GetUpdatedAt() + p = nil + p.GetUpdatedAt() +} + +func TestPrivateRegistry_GetUsername(tt *testing.T) { + tt.Parallel() + var zeroValue string + p := &PrivateRegistry{Username: &zeroValue} + p.GetUsername() + p = &PrivateRegistry{} + p.GetUsername() + p = nil + p.GetUsername() +} + +func TestPrivateRegistry_GetVisibility(tt *testing.T) { + tt.Parallel() + p := &PrivateRegistry{} + p.GetVisibility() + p = nil + p.GetVisibility() +} + func TestPRLink_GetHRef(tt *testing.T) { tt.Parallel() var zeroValue string @@ -37165,6 +37250,69 @@ func TestUpdateEnterpriseRunnerGroupRequest_GetVisibility(tt *testing.T) { u.GetVisibility() } +func TestUpdateOrganizationPrivateRegistry_GetEncryptedValue(tt *testing.T) { + tt.Parallel() + var zeroValue string + u := &UpdateOrganizationPrivateRegistry{EncryptedValue: &zeroValue} + u.GetEncryptedValue() + u = &UpdateOrganizationPrivateRegistry{} + u.GetEncryptedValue() + u = nil + u.GetEncryptedValue() +} + +func TestUpdateOrganizationPrivateRegistry_GetKeyID(tt *testing.T) { + tt.Parallel() + var zeroValue string + u := &UpdateOrganizationPrivateRegistry{KeyID: &zeroValue} + u.GetKeyID() + u = &UpdateOrganizationPrivateRegistry{} + u.GetKeyID() + u = nil + u.GetKeyID() +} + +func TestUpdateOrganizationPrivateRegistry_GetRegistryType(tt *testing.T) { + tt.Parallel() + var zeroValue string + u := &UpdateOrganizationPrivateRegistry{RegistryType: &zeroValue} + u.GetRegistryType() + u = &UpdateOrganizationPrivateRegistry{} + u.GetRegistryType() + u = nil + u.GetRegistryType() +} + +func TestUpdateOrganizationPrivateRegistry_GetURL(tt *testing.T) { + tt.Parallel() + var zeroValue string + u := &UpdateOrganizationPrivateRegistry{URL: &zeroValue} + u.GetURL() + u = &UpdateOrganizationPrivateRegistry{} + u.GetURL() + u = nil + u.GetURL() +} + +func TestUpdateOrganizationPrivateRegistry_GetUsername(tt *testing.T) { + tt.Parallel() + var zeroValue string + u := &UpdateOrganizationPrivateRegistry{Username: &zeroValue} + u.GetUsername() + u = &UpdateOrganizationPrivateRegistry{} + u.GetUsername() + u = nil + u.GetUsername() +} + +func TestUpdateOrganizationPrivateRegistry_GetVisibility(tt *testing.T) { + tt.Parallel() + u := &UpdateOrganizationPrivateRegistry{} + u.GetVisibility() + u = nil + u.GetVisibility() +} + func TestUpdateRef_GetForce(tt *testing.T) { tt.Parallel() var zeroValue bool diff --git a/github/github.go b/github/github.go index bf17933207c..09d35833d19 100644 --- a/github/github.go +++ b/github/github.go @@ -218,6 +218,7 @@ type Client struct { Meta *MetaService Migrations *MigrationService Organizations *OrganizationsService + PrivateRegistries *PrivateRegistriesService Projects *ProjectsService PullRequests *PullRequestsService RateLimit *RateLimitService @@ -457,6 +458,7 @@ func (c *Client) initialize() { c.Meta = (*MetaService)(&c.common) c.Migrations = (*MigrationService)(&c.common) c.Organizations = (*OrganizationsService)(&c.common) + c.PrivateRegistries = (*PrivateRegistriesService)(&c.common) c.Projects = (*ProjectsService)(&c.common) c.PullRequests = (*PullRequestsService)(&c.common) c.RateLimit = (*RateLimitService)(&c.common) diff --git a/github/private_registries.go b/github/private_registries.go new file mode 100644 index 00000000000..ff8582c45dc --- /dev/null +++ b/github/private_registries.go @@ -0,0 +1,263 @@ +// Copyright 2025 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" +) + +// PrivateRegistriesService handles communication with the private registries +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/rest/private-registries +type PrivateRegistriesService service + +// PrivateRegistryType represents the type of private registry. +type PrivateRegistryType string + +const ( + PrivateRegistryTypeMavenRepository PrivateRegistryType = "maven_repository" + PrivateRegistryTypeNugetFeed PrivateRegistryType = "nuget_feed" + PrivateRegistryTypeGoProxyServer PrivateRegistryType = "goproxy_server" + PrivateRegistryTypeNpmRegistry PrivateRegistryType = "npm_registry" + PrivateRegistryTypeRubygemsServer PrivateRegistryType = "rubygems_server" + PrivateRegistryTypeCargoRegistry PrivateRegistryType = "cargo_registry" + PrivateRegistryTypeComposerRepository PrivateRegistryType = "composer_repository" + PrivateRegistryTypeDockerRegistry PrivateRegistryType = "docker_registry" + PrivateRegistryTypeGitSource PrivateRegistryType = "git_source" + PrivateRegistryTypeHelmRegistry PrivateRegistryType = "helm_registry" + PrivateRegistryTypeHexOrganization PrivateRegistryType = "hex_organization" + PrivateRegistryTypeHexRepository PrivateRegistryType = "hex_repository" + PrivateRegistryTypePubRepository PrivateRegistryType = "pub_repository" + PrivateRegistryTypePythonIndex PrivateRegistryType = "python_index" + PrivateRegistryTypeTerraformRegistry PrivateRegistryType = "terraform_registry" +) + +// PrivateRegistryVisibility represents the visibility of a private registry. +type PrivateRegistryVisibility string + +const ( + PrivateRegistryVisibilityPrivate PrivateRegistryVisibility = "private" + PrivateRegistryVisibilityAll PrivateRegistryVisibility = "all" + PrivateRegistryVisibilitySelected PrivateRegistryVisibility = "selected" +) + +// PrivateRegistry represents a private registry configuration. +type PrivateRegistry struct { + // Name of the private registry. + Name *string `json:"name,omitempty"` + // RegistryType is the type of private registry. You can find the list of supported types in PrivateRegistryType. + RegistryType *string `json:"registry_type,omitempty"` + // Username to use when authenticating with the private registry. + // This field is omitted if the private registry does not require a username for authentication. + Username *string `json:"username,omitempty"` + // CreatedAt is the timestamp when the private registry was created. + CreatedAt *Timestamp `json:"created_at,omitempty"` + // UpdatedAt is the timestamp when the private registry was last updated. + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + // Visibility is the visibility of the private registry. Possible values are: "private", "all", and "selected". + Visibility *PrivateRegistryVisibility `json:"visibility,omitempty"` +} + +// PrivateRegistries represents a list of private registries. +type PrivateRegistries struct { + // TotalCount is the total number of private registries. + TotalCount *int `json:"total_count,omitempty"` + // Configurations is the list of private registry configurations. + Configurations []*PrivateRegistry `json:"configurations,omitempty"` +} + +// CreateOrganizationPrivateRegistry represents the payload to create a private registry. +type CreateOrganizationPrivateRegistry struct { + // RegistryType is the type of private registry. + // You can find the list of supported types in PrivateRegistryType. + RegistryType string `json:"registry_type"` + + // URL is the URL of the private registry. + URL string `json:"url"` + + // The username to use when authenticating with the private registry. + // This field should be omitted if the private registry does not require a username for authentication. + Username *string `json:"username,omitempty"` + + // The value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) + // using the public key retrieved from the PrivateRegistriesService.GetOrganizationPrivateRegistriesPublicKey. + EncryptedValue string `json:"encrypted_value"` + // KeyID is the ID of the public key used to encrypt the secret. + KeyID string `json:"key_id"` + // Visibility is the visibility of the private registry. + // Possible values are: "private", "all", and "selected". + Visibility PrivateRegistryVisibility `json:"visibility"` + + // An array of repository IDs that can access the organization private registry. + // You can only provide a list of repository IDs when CreateOrganizationPrivateRegistry.Visibility is set to PrivateRegistryVisibilitySelected. + // This field should be omitted if visibility is set to PrivateRegistryVisibilityAll or PrivateRegistryVisibilityPrivate. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"` +} + +// UpdateOrganizationPrivateRegistry represents the payload to update a private registry. +type UpdateOrganizationPrivateRegistry struct { + // RegistryType is the type of private registry. + // You can find the list of supported types in PrivateRegistryType. + RegistryType *string `json:"registry_type,omitempty"` + + // URL is the URL of the private registry. + URL *string `json:"url,omitempty"` + + // The username to use when authenticating with the private registry. + // This field should be omitted if the private registry does not require a username for authentication. + Username *string `json:"username,omitempty"` + + // The value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) + // using the public key retrieved from the PrivateRegistriesService.GetOrganizationPrivateRegistriesPublicKey. + EncryptedValue *string `json:"encrypted_value,omitempty"` + // KeyID is the ID of the public key used to encrypt the secret. + KeyID *string `json:"key_id,omitempty"` + // Visibility is the visibility of the private registry. + // Possible values are: "private", "all", and "selected". + Visibility *PrivateRegistryVisibility `json:"visibility,omitempty"` + + // An array of repository IDs that can access the organization private registry. + // You can only provide a list of repository IDs when CreateOrganizationPrivateRegistry.Visibility is set to PrivateRegistryVisibilitySelected. + // This field should be omitted if visibility is set to PrivateRegistryVisibilityAll or PrivateRegistryVisibilityPrivate. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"` +} + +// ListOrganizationPrivateRegistries lists private registries for an organization. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#list-private-registries-for-an-organization +// +//meta:operation GET /orgs/{org}/private-registries +func (s *PrivateRegistriesService) ListOrganizationPrivateRegistries(ctx context.Context, org string, opts *ListOptions) (*PrivateRegistries, *Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries", org) + 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 + } + + var privateRegistries PrivateRegistries + resp, err := s.client.Do(ctx, req, &privateRegistries) + if err != nil { + return nil, resp, err + } + return &privateRegistries, resp, nil +} + +// CreateOrganizationPrivateRegistry creates a private registry configuration with an encrypted value for an organization. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#create-a-private-registry-for-an-organization +// +//meta:operation POST /orgs/{org}/private-registries +func (s *PrivateRegistriesService) CreateOrganizationPrivateRegistry(ctx context.Context, org string, privateRegistry CreateOrganizationPrivateRegistry) (*PrivateRegistry, *Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries", org) + + req, err := s.client.NewRequest("POST", u, privateRegistry) + if err != nil { + return nil, nil, err + } + + var result PrivateRegistry + resp, err := s.client.Do(ctx, req, &result) + if err != nil { + return nil, resp, err + } + return &result, resp, nil +} + +// GetOrganizationPrivateRegistriesPublicKey retrieves the public key for encrypting secrets for an organization's private registries. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#get-private-registries-public-key-for-an-organization +// +//meta:operation GET /orgs/{org}/private-registries/public-key +func (s *PrivateRegistriesService) GetOrganizationPrivateRegistriesPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries/public-key", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var publicKey PublicKey + resp, err := s.client.Do(ctx, req, &publicKey) + if err != nil { + return nil, resp, err + } + return &publicKey, resp, nil +} + +// GetOrganizationPrivateRegistry gets a specific private registry for an organization. +// The `name` parameter is the name of the private registry to retrieve. It is the same as PrivateRegistry.Name. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#get-a-private-registry-for-an-organization +// +//meta:operation GET /orgs/{org}/private-registries/{secret_name} +func (s *PrivateRegistriesService) GetOrganizationPrivateRegistry(ctx context.Context, org, secretName string) (*PrivateRegistry, *Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries/%v", org, secretName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var privateRegistry PrivateRegistry + resp, err := s.client.Do(ctx, req, &privateRegistry) + if err != nil { + return nil, resp, err + } + + return &privateRegistry, resp, nil +} + +// UpdateOrganizationPrivateRegistry updates a specific private registry for an organization. +// The `name` parameter is the name of the private registry to update. It is the same as PrivateRegistry.Name. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#update-a-private-registry-for-an-organization +// +//meta:operation PATCH /orgs/{org}/private-registries/{secret_name} +func (s *PrivateRegistriesService) UpdateOrganizationPrivateRegistry(ctx context.Context, org, secretName string, privateRegistry UpdateOrganizationPrivateRegistry) (*PrivateRegistry, *Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries/%v", org, secretName) + + req, err := s.client.NewRequest("PATCH", u, privateRegistry) + if err != nil { + return nil, nil, err + } + + var updatedRegistry PrivateRegistry + resp, err := s.client.Do(ctx, req, &updatedRegistry) + if err != nil { + return nil, resp, err + } + + return &updatedRegistry, resp, nil +} + +// DeleteOrganizationPrivateRegistry deletes a specific private registry for an organization. +// The `name` parameter is the name of the private registry to delete. It is the same as PrivateRegistry.Name. +// +// GitHub API docs: https://docs.github.com/rest/private-registries/organization-configurations#delete-a-private-registry-for-an-organization +// +//meta:operation DELETE /orgs/{org}/private-registries/{secret_name} +func (s *PrivateRegistriesService) DeleteOrganizationPrivateRegistry(ctx context.Context, org, secretName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/private-registries/%v", org, secretName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/github/private_registries_test.go b/github/private_registries_test.go new file mode 100644 index 00000000000..5c01b6dad59 --- /dev/null +++ b/github/private_registries_test.go @@ -0,0 +1,326 @@ +// Copyright 2025 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" + "encoding/json" + "fmt" + "net/http" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func TestPrivateRegistriesService_ListOrganizationPrivateRegistries(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/private-registries", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testFormValues(t, r, values{ + "page": "2", + }) + fmt.Fprint(w, `{ + "total_count": 1, + "configurations": [ + { + "name": "MAVEN_REPOSITORY_SECRET", + "registry_type": "maven_repository", + "username": "monalisa", + "created_at": "2019-08-10T14:59:22Z", + "updated_at": "2020-01-10T14:59:22Z", + "visibility": "selected" + } + ] +}`) + }) + + opts := &ListOptions{Page: 2} + ctx := t.Context() + privateRegistries, _, err := client.PrivateRegistries.ListOrganizationPrivateRegistries(ctx, "o", opts) + if err != nil { + t.Fatalf("PrivateRegistries.ListOrganizationPrivateRegitries returned error: %v", err) + } + + want := &PrivateRegistries{ + TotalCount: Ptr(1), + Configurations: []*PrivateRegistry{ + { + Name: Ptr("MAVEN_REPOSITORY_SECRET"), + RegistryType: Ptr("maven_repository"), + Username: Ptr("monalisa"), + CreatedAt: &Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, + UpdatedAt: &Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, + Visibility: Ptr(PrivateRegistryVisibilitySelected), + }, + }, + } + if diff := cmp.Diff(want, privateRegistries); diff != "" { + t.Errorf("PrivateRegistries.ListOrganizationPrivateRegitries mismatch (-want +got):\\n%v", diff) + } + + const methodName = "ListOrganizationPrivateRegistries" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.PrivateRegistries.ListOrganizationPrivateRegistries(ctx, "\n", opts) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.PrivateRegistries.ListOrganizationPrivateRegistries(ctx, "o", opts) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) + + // still allow both set (no validation enforced) – ensure it does not error + ctxBypass := context.WithValue(t.Context(), BypassRateLimitCheck, true) + if _, _, err = client.PrivateRegistries.ListOrganizationPrivateRegistries(ctxBypass, "o", opts); err != nil { + t.Fatalf("unexpected error when both before/after set: %v", err) + } +} + +func TestPrivateRegistriesService_CreateOrganizationPrivateRegistry(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &CreateOrganizationPrivateRegistry{ + RegistryType: "maven_repository", + URL: "https://maven.pkg.github.com/OWNER/REPOSITORY", + Username: Ptr("monalisa"), + EncryptedValue: "encrypted_value", + KeyID: "key_id", + Visibility: PrivateRegistryVisibilitySelected, + SelectedRepositoryIDs: []int64{1, 2, 3}, + } + + mux.HandleFunc("/orgs/o/private-registries", func(w http.ResponseWriter, r *http.Request) { + v := new(CreateOrganizationPrivateRegistry) + assertNilError(t, json.NewDecoder(r.Body).Decode(v)) + + testMethod(t, r, "POST") + if !cmp.Equal(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{ + "name": "MAVEN_REPOSITORY_SECRET", + "registry_type": "maven_repository", + "username": "monalisa", + "created_at": "2019-08-10T14:59:22Z", + "updated_at": "2020-01-10T14:59:22Z", + "visibility": "selected" +}`) + }) + + ctx := t.Context() + privateRegistry, _, err := client.PrivateRegistries.CreateOrganizationPrivateRegistry(ctx, "o", *input) + if err != nil { + t.Fatalf("PrivateRegistries.CreateOrganizationPrivateRegitries returned error: %v", err) + } + + want := &PrivateRegistry{ + Name: Ptr("MAVEN_REPOSITORY_SECRET"), + RegistryType: Ptr("maven_repository"), + Username: Ptr("monalisa"), + CreatedAt: &Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, + UpdatedAt: &Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, + Visibility: Ptr(PrivateRegistryVisibilitySelected), + } + if diff := cmp.Diff(want, privateRegistry); diff != "" { + t.Errorf("PrivateRegistries.CreateOrganizationPrivateRegitries mismatch (-want +got):\\n%v", diff) + } + + const methodName = "CreateOrganizationPrivateRegistry" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.PrivateRegistries.CreateOrganizationPrivateRegistry(ctx, "\n", *input) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.PrivateRegistries.CreateOrganizationPrivateRegistry(ctx, "o", *input) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestPrivateRegistriesService_GetOrganizationPrivateRegistriesPublicKey(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/private-registries/public-key", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "key_id": "0123456789", + "key": "public_key" +}`) + }) + ctx := t.Context() + publicKey, _, err := client.PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey(ctx, "o") + if err != nil { + t.Fatalf("PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey returned error: %v", err) + } + + want := &PublicKey{ + KeyID: Ptr("0123456789"), + Key: Ptr("public_key"), + } + if diff := cmp.Diff(want, publicKey); diff != "" { + t.Errorf("PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey mismatch (-want +got):\\n%v", diff) + } + + const methodName = "GetOrganizationPrivateRegistriesPublicKey" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey(ctx, "\n") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.PrivateRegistries.GetOrganizationPrivateRegistriesPublicKey(ctx, "o") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestPrivateRegistriesService_GetOrganizationPrivateRegistry(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/private-registries/MAVEN_REPOSITORY_SECRET", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "name": "MAVEN_REPOSITORY_SECRET", + "registry_type": "maven_repository", + "username": "monalisa", + "created_at": "2019-08-10T14:59:22Z", + "updated_at": "2020-01-10T14:59:22Z", + "visibility": "selected" +}`) + }) + ctx := t.Context() + privateRegistry, _, err := client.PrivateRegistries.GetOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET") + if err != nil { + t.Fatalf("PrivateRegistries.GetOrganizationPrivateRegistry returned error: %v", err) + } + + want := &PrivateRegistry{ + Name: Ptr("MAVEN_REPOSITORY_SECRET"), + RegistryType: Ptr("maven_repository"), + Username: Ptr("monalisa"), + CreatedAt: &Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, + UpdatedAt: &Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, + Visibility: Ptr(PrivateRegistryVisibilitySelected), + } + if diff := cmp.Diff(want, privateRegistry); diff != "" { + t.Errorf("PrivateRegistries.GetOrganizationPrivateRegistry mismatch (-want +got):\\n%v", diff) + } + + const methodName = "GetOrganizationPrivateRegistry" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.PrivateRegistries.GetOrganizationPrivateRegistry(ctx, "\n", "MAVEN_REPOSITORY_SECRET") + return err + }) + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.PrivateRegistries.GetOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestPrivateRegistries_UpdateOrganizationPrivateRegistry(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + input := &UpdateOrganizationPrivateRegistry{ + Username: Ptr("monalisa"), + EncryptedValue: Ptr("encrypted_value"), + KeyID: Ptr("key_id"), + Visibility: Ptr(PrivateRegistryVisibilitySelected), + } + + mux.HandleFunc("/orgs/o/private-registries/MAVEN_REPOSITORY_SECRET", func(w http.ResponseWriter, r *http.Request) { + v := new(UpdateOrganizationPrivateRegistry) + assertNilError(t, json.NewDecoder(r.Body).Decode(v)) + + testMethod(t, r, "PATCH") + if !cmp.Equal(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, `{ + "name": "MAVEN_REPOSITORY_SECRET", + "registry_type": "maven_repository", + "username": "monalisa", + "created_at": "2019-08-10T14:59:22Z", + "updated_at": "2020-01-10T14:59:22Z", + "visibility": "selected" +}`) + }) + + ctx := t.Context() + privateRegistry, _, err := client.PrivateRegistries.UpdateOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET", *input) + if err != nil { + t.Fatalf("PrivateRegistries.UpdateOrganizationPrivateRegistry returned error: %v", err) + } + + want := &PrivateRegistry{ + Name: Ptr("MAVEN_REPOSITORY_SECRET"), + RegistryType: Ptr("maven_repository"), + Username: Ptr("monalisa"), + CreatedAt: &Timestamp{time.Date(2019, time.August, 10, 14, 59, 22, 0, time.UTC)}, + UpdatedAt: &Timestamp{time.Date(2020, time.January, 10, 14, 59, 22, 0, time.UTC)}, + Visibility: Ptr(PrivateRegistryVisibilitySelected), + } + if diff := cmp.Diff(want, privateRegistry); diff != "" { + t.Errorf("PrivateRegistries.UpdateOrganizationPrivateRegistry mismatch (-want +got):\\n%v", diff) + } + + const methodName = "UpdateOrganizationPrivateRegistry" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.PrivateRegistries.UpdateOrganizationPrivateRegistry(ctx, "\n", "MAVEN_REPOSITORY_SECRET", *input) + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.PrivateRegistries.UpdateOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET", *input) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestPrivateRegistriesService_DeleteOrganizationPrivateRegistry(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/private-registries/MAVEN_REPOSITORY_SECRET", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + w.WriteHeader(http.StatusNoContent) + }) + ctx := t.Context() + _, err := client.PrivateRegistries.DeleteOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET") + if err != nil { + t.Fatalf("PrivateRegistries.DeleteOrganizationPrivateRegistry returned error: %v", err) + } + + const methodName = "DeleteOrganizationPrivateRegistry" + testBadOptions(t, methodName, func() (err error) { + _, err = client.PrivateRegistries.DeleteOrganizationPrivateRegistry(ctx, "\n", "MAVEN_REPOSITORY_SECRET") + return err + }) + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.PrivateRegistries.DeleteOrganizationPrivateRegistry(ctx, "o", "MAVEN_REPOSITORY_SECRET") + }) +}