diff --git a/AUTHORS b/AUTHORS index 6e3c5035f63..a6104ffa9aa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -481,6 +481,7 @@ SoundCloud, Ltd. Sridhar Mocherla SriVignessh Pss Stefan Sedich +Steve Hipwell Steve Teuber Stian Eikeland Suhaib Mujahid diff --git a/github/enterprise_properties.go b/github/enterprise_properties.go new file mode 100644 index 00000000000..bc5ab55a3a6 --- /dev/null +++ b/github/enterprise_properties.go @@ -0,0 +1,121 @@ +// 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" +) + +// GetAllCustomProperties gets all custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-custom-properties-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) GetAllCustomProperties(ctx context.Context, enterprise string) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// CreateOrUpdateCustomProperties creates new or updates existing custom properties that are defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-custom-properties-for-an-enterprise +// +//meta:operation PATCH /enterprises/{enterprise}/properties/schema +func (s *EnterpriseService) CreateOrUpdateCustomProperties(ctx context.Context, enterprise string, properties []*CustomProperty) ([]*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema", enterprise) + + params := struct { + Properties []*CustomProperty `json:"properties"` + }{ + Properties: properties, + } + + req, err := s.client.NewRequest("PATCH", u, params) + if err != nil { + return nil, nil, err + } + + var customProperties []*CustomProperty + resp, err := s.client.Do(ctx, req, &customProperties) + if err != nil { + return nil, resp, err + } + + return customProperties, resp, nil +} + +// GetCustomProperty gets a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#get-a-custom-property-for-an-enterprise +// +//meta:operation GET /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) GetCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// CreateOrUpdateCustomProperty creates a new or updates an existing custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#create-or-update-a-custom-property-for-an-enterprise +// +//meta:operation PUT /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) CreateOrUpdateCustomProperty(ctx context.Context, enterprise, customPropertyName string, property *CustomProperty) (*CustomProperty, *Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("PUT", u, property) + if err != nil { + return nil, nil, err + } + + var customProperty *CustomProperty + resp, err := s.client.Do(ctx, req, &customProperty) + if err != nil { + return nil, resp, err + } + + return customProperty, resp, nil +} + +// RemoveCustomProperty removes a custom property that is defined for the specified enterprise. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/enterprise-admin/custom-properties#remove-a-custom-property-for-an-enterprise +// +//meta:operation DELETE /enterprises/{enterprise}/properties/schema/{custom_property_name} +func (s *EnterpriseService) RemoveCustomProperty(ctx context.Context, enterprise, customPropertyName string) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/properties/schema/%v", enterprise, customPropertyName) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/github/enterprise_properties_test.go b/github/enterprise_properties_test.go new file mode 100644 index 00000000000..4f44d60f217 --- /dev/null +++ b/github/enterprise_properties_test.go @@ -0,0 +1,278 @@ +// 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" + "net/http" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestEnterpriseService_GetAllCustomProperties(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/properties/schema", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "property_name": "name", + "value_type": "single_select", + "required": true, + "default_value": "production", + "description": "Prod or dev environment", + "allowed_values":[ + "production", + "development" + ], + "values_editable_by": "org_actors" + }, + { + "property_name": "service", + "value_type": "string" + }, + { + "property_name": "team", + "value_type": "string", + "description": "Team owning the repository" + } + ]`) + }) + + ctx := context.Background() + properties, _, err := client.Enterprise.GetAllCustomProperties(ctx, "e") + if err != nil { + t.Errorf("Enterprise.GetAllCustomProperties returned error: %v", err) + } + + want := []*CustomProperty{ + { + PropertyName: Ptr("name"), + ValueType: "single_select", + Required: Ptr(true), + DefaultValue: Ptr("production"), + Description: Ptr("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: Ptr("org_actors"), + }, + { + PropertyName: Ptr("service"), + ValueType: "string", + }, + { + PropertyName: Ptr("team"), + ValueType: "string", + Description: Ptr("Team owning the repository"), + }, + } + if !cmp.Equal(properties, want) { + t.Errorf("Enterprise.GetAllCustomProperties returned %+v, want %+v", properties, want) + } + + const methodName = "GetAllCustomProperties" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.GetAllCustomProperties(ctx, "e") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_CreateOrUpdateCustomProperties(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/properties/schema", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PATCH") + testBody(t, r, `{"properties":[{"property_name":"name","value_type":"single_select","required":true},{"property_name":"service","value_type":"string"}]}`+"\n") + fmt.Fprint(w, `[ + { + "property_name": "name", + "value_type": "single_select", + "required": true + }, + { + "property_name": "service", + "value_type": "string" + } + ]`) + }) + + ctx := context.Background() + properties, _, err := client.Enterprise.CreateOrUpdateCustomProperties(ctx, "e", []*CustomProperty{ + { + PropertyName: Ptr("name"), + ValueType: "single_select", + Required: Ptr(true), + }, + { + PropertyName: Ptr("service"), + ValueType: "string", + }, + }) + if err != nil { + t.Errorf("Enterprise.CreateOrUpdateCustomProperties returned error: %v", err) + } + + want := []*CustomProperty{ + { + PropertyName: Ptr("name"), + ValueType: "single_select", + Required: Ptr(true), + }, + { + PropertyName: Ptr("service"), + ValueType: "string", + }, + } + + if !cmp.Equal(properties, want) { + t.Errorf("Enterprise.CreateOrUpdateCustomProperties returned %+v, want %+v", properties, want) + } + + const methodName = "CreateOrUpdateCustomProperties" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.CreateOrUpdateCustomProperties(ctx, "e", nil) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_GetCustomProperty(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/properties/schema/name", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "property_name": "name", + "value_type": "single_select", + "required": true, + "default_value": "production", + "description": "Prod or dev environment", + "allowed_values":[ + "production", + "development" + ], + "values_editable_by": "org_actors" + }`) + }) + + ctx := context.Background() + property, _, err := client.Enterprise.GetCustomProperty(ctx, "e", "name") + if err != nil { + t.Errorf("Enterprise.GetCustomProperty returned error: %v", err) + } + + want := &CustomProperty{ + PropertyName: Ptr("name"), + ValueType: "single_select", + Required: Ptr(true), + DefaultValue: Ptr("production"), + Description: Ptr("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: Ptr("org_actors"), + } + if !cmp.Equal(property, want) { + t.Errorf("Enterprise.GetCustomProperty returned %+v, want %+v", property, want) + } + + const methodName = "GetCustomProperty" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.GetCustomProperty(ctx, "e", "name") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_CreateOrUpdateCustomProperty(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/properties/schema/name", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + fmt.Fprint(w, `{ + "property_name": "name", + "value_type": "single_select", + "required": true, + "default_value": "production", + "description": "Prod or dev environment", + "allowed_values":[ + "production", + "development" + ], + "values_editable_by": "org_actors" + }`) + }) + + ctx := context.Background() + property, _, err := client.Enterprise.CreateOrUpdateCustomProperty(ctx, "e", "name", &CustomProperty{ + ValueType: "single_select", + Required: Ptr(true), + DefaultValue: Ptr("production"), + Description: Ptr("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: Ptr("org_actors"), + }) + if err != nil { + t.Errorf("Enterprise.CreateOrUpdateCustomProperty returned error: %v", err) + } + + want := &CustomProperty{ + PropertyName: Ptr("name"), + ValueType: "single_select", + Required: Ptr(true), + DefaultValue: Ptr("production"), + Description: Ptr("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: Ptr("org_actors"), + } + if !cmp.Equal(property, want) { + t.Errorf("Enterprise.CreateOrUpdateCustomProperty returned %+v, want %+v", property, want) + } + + const methodName = "CreateOrUpdateCustomProperty" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Enterprise.CreateOrUpdateCustomProperty(ctx, "e", "name", nil) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestEnterpriseService_RemoveCustomProperty(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/enterprises/e/properties/schema/name", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + ctx := context.Background() + _, err := client.Enterprise.RemoveCustomProperty(ctx, "e", "name") + if err != nil { + t.Errorf("Enterprise.RemoveCustomProperty returned error: %v", err) + } + + const methodName = "RemoveCustomProperty" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + return client.Enterprise.RemoveCustomProperty(ctx, "e", "name") + }) +}