From d184914469978d6c091422f3c139ad4aef9e1e6d Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Wed, 16 Sep 2026 14:18:21 +0200 Subject: [PATCH 1/4] feat: Support explicit custom property values --- .golangci.yml | 1 + github/github-accessors.go | 8 +++ github/github-accessors_test.go | 11 ++++ github/orgs_properties.go | 2 + github/orgs_properties_test.go | 96 +++++++++++++++++++++++---------- 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 6828063a288..7a628039b0c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -362,6 +362,7 @@ linters: - CreateTag.Object # TODO: Git - CreateTag.Tag # TODO: Git - CreateTag.Type # TODO: Git + - CustomProperty.RequireExplicitValues - DismissalRestrictionsRequest.Apps # TODO: Repositories - DismissalRestrictionsRequest.Teams # TODO: Repositories - DismissalRestrictionsRequest.Users # TODO: Repositories diff --git a/github/github-accessors.go b/github/github-accessors.go index 3ff9513dd29..aac523bb9d2 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -13934,6 +13934,14 @@ func (c *CustomProperty) GetRequired() bool { return *c.Required } +// GetRequireExplicitValues returns the RequireExplicitValues field if it's non-nil, zero value otherwise. +func (c *CustomProperty) GetRequireExplicitValues() bool { + if c == nil || c.RequireExplicitValues == nil { + return false + } + return *c.RequireExplicitValues +} + // GetSourceType returns the SourceType field if it's non-nil, zero value otherwise. func (c *CustomProperty) GetSourceType() string { if c == nil || c.SourceType == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index b16681d6456..fcfceabd863 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -17601,6 +17601,17 @@ func TestCustomProperty_GetRequired(tt *testing.T) { c.GetRequired() } +func TestCustomProperty_GetRequireExplicitValues(tt *testing.T) { + tt.Parallel() + var zeroValue bool + c := &CustomProperty{RequireExplicitValues: &zeroValue} + c.GetRequireExplicitValues() + c = &CustomProperty{} + c.GetRequireExplicitValues() + c = nil + c.GetRequireExplicitValues() +} + func TestCustomProperty_GetSourceType(tt *testing.T) { tt.Parallel() var zeroValue string diff --git a/github/orgs_properties.go b/github/orgs_properties.go index f3492c47e87..50cf5a7b6bc 100644 --- a/github/orgs_properties.go +++ b/github/orgs_properties.go @@ -38,6 +38,8 @@ type CustomProperty struct { ValueType PropertyValueType `json:"value_type"` // Whether the property is required. Required *bool `json:"required,omitempty"` + // Whether setting property values is mandatory. + RequireExplicitValues *bool `json:"require_explicit_values,omitzero"` // Default value of the property. DefaultValue any `json:"default_value,omitempty"` // Short description of the property. diff --git a/github/orgs_properties_test.go b/github/orgs_properties_test.go index 10de42fe2da..1bfee97612e 100644 --- a/github/orgs_properties_test.go +++ b/github/orgs_properties_test.go @@ -25,6 +25,7 @@ func TestOrganizationsService_GetAllCustomProperties(t *testing.T) { "property_name": "name", "value_type": "single_select", "required": true, + "require_explicit_values": true, "default_value": "production", "description": "Prod or dev environment", "allowed_values":[ @@ -76,13 +77,14 @@ func TestOrganizationsService_GetAllCustomProperties(t *testing.T) { want := []*CustomProperty{ { - PropertyName: new("name"), - ValueType: PropertyValueTypeSingleSelect, - Required: new(true), - DefaultValue: "production", - Description: new("Prod or dev environment"), - AllowedValues: []string{"production", "development"}, - ValuesEditableBy: new("org_actors"), + PropertyName: new("name"), + ValueType: PropertyValueTypeSingleSelect, + Required: new(true), + RequireExplicitValues: new(true), + DefaultValue: "production", + Description: new("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: new("org_actors"), }, { PropertyName: new("test"), @@ -135,9 +137,10 @@ func TestOrganizationsService_CreateOrUpdateCustomProperties(t *testing.T) { }{ Properties: []*CustomProperty{ { - PropertyName: new("name"), - ValueType: PropertyValueTypeSingleSelect, - Required: new(true), + PropertyName: new("name"), + ValueType: PropertyValueTypeSingleSelect, + Required: new(true), + RequireExplicitValues: new(false), }, { PropertyName: new("service"), @@ -153,7 +156,8 @@ func TestOrganizationsService_CreateOrUpdateCustomProperties(t *testing.T) { { "property_name": "name", "value_type": "single_select", - "required": true + "required": true, + "require_explicit_values": false }, { "property_name": "service", @@ -170,9 +174,10 @@ func TestOrganizationsService_CreateOrUpdateCustomProperties(t *testing.T) { want := []*CustomProperty{ { - PropertyName: new("name"), - ValueType: PropertyValueTypeSingleSelect, - Required: new(true), + PropertyName: new("name"), + ValueType: PropertyValueTypeSingleSelect, + Required: new(true), + RequireExplicitValues: new(false), }, { PropertyName: new("service"), @@ -249,12 +254,24 @@ func TestOrganizationsService_CreateOrUpdateCustomProperty(t *testing.T) { t.Parallel() client, mux, _ := setup(t) + input := &CustomProperty{ + ValueType: PropertyValueTypeSingleSelect, + Required: new(true), + RequireExplicitValues: new(false), + DefaultValue: "production", + Description: new("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: new("org_actors"), + } + mux.HandleFunc("/orgs/o/properties/schema/name", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") + testJSONBody(t, r, input) fmt.Fprint(w, `{ "property_name": "name", "value_type": "single_select", "required": true, + "require_explicit_values": false, "default_value": "production", "description": "Prod or dev environment", "allowed_values":[ @@ -266,26 +283,20 @@ func TestOrganizationsService_CreateOrUpdateCustomProperty(t *testing.T) { }) ctx := t.Context() - property, _, err := client.Organizations.CreateOrUpdateCustomProperty(ctx, "o", "name", &CustomProperty{ - ValueType: PropertyValueTypeSingleSelect, - Required: new(true), - DefaultValue: "production", - Description: new("Prod or dev environment"), - AllowedValues: []string{"production", "development"}, - ValuesEditableBy: new("org_actors"), - }) + property, _, err := client.Organizations.CreateOrUpdateCustomProperty(ctx, "o", "name", input) if err != nil { t.Errorf("Organizations.CreateOrUpdateCustomProperty returned error: %v", err) } want := &CustomProperty{ - PropertyName: new("name"), - ValueType: PropertyValueTypeSingleSelect, - Required: new(true), - DefaultValue: "production", - Description: new("Prod or dev environment"), - AllowedValues: []string{"production", "development"}, - ValuesEditableBy: new("org_actors"), + PropertyName: new("name"), + ValueType: PropertyValueTypeSingleSelect, + Required: new(true), + RequireExplicitValues: new(false), + DefaultValue: "production", + Description: new("Prod or dev environment"), + AllowedValues: []string{"production", "development"}, + ValuesEditableBy: new("org_actors"), } if !cmp.Equal(property, want) { t.Errorf("Organizations.CreateOrUpdateCustomProperty returned %+v, want %+v", property, want) @@ -302,6 +313,33 @@ func TestOrganizationsService_CreateOrUpdateCustomProperty(t *testing.T) { }) } +func TestCustomProperty_RequireExplicitValuesJSON(t *testing.T) { + t.Parallel() + tests := map[string]struct { + property *CustomProperty + want string + }{ + "omitted": { + property: &CustomProperty{ValueType: PropertyValueTypeString}, + want: `{"value_type":"string"}`, + }, + "explicit false": { + property: &CustomProperty{ + ValueType: PropertyValueTypeString, + RequireExplicitValues: new(false), + }, + want: `{"value_type":"string","require_explicit_values":false}`, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + t.Parallel() + testJSONMarshal(t, test.property, test.want) + }) + } +} + func TestOrganizationsService_RemoveCustomProperty(t *testing.T) { t.Parallel() client, mux, _ := setup(t) From d1802b6036e28250912417070c34094af104e534 Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Thu, 17 Sep 2026 11:18:10 +0200 Subject: [PATCH 2/4] Update github/orgs_properties.go Co-authored-by: Dhananjay Mishra --- github/orgs_properties.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/orgs_properties.go b/github/orgs_properties.go index 50cf5a7b6bc..2955082ab14 100644 --- a/github/orgs_properties.go +++ b/github/orgs_properties.go @@ -39,7 +39,7 @@ type CustomProperty struct { // Whether the property is required. Required *bool `json:"required,omitempty"` // Whether setting property values is mandatory. - RequireExplicitValues *bool `json:"require_explicit_values,omitzero"` + RequireExplicitValues *bool `json:"require_explicit_values,omitempty"` // Default value of the property. DefaultValue any `json:"default_value,omitempty"` // Short description of the property. From dfce6f1f14430523430bcb8f5d05ed8fe7219963 Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Thu, 17 Sep 2026 12:45:57 +0200 Subject: [PATCH 3/4] Update github/orgs_properties_test.go Co-authored-by: Dhananjay Mishra --- github/orgs_properties_test.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/github/orgs_properties_test.go b/github/orgs_properties_test.go index 1bfee97612e..44f473829f6 100644 --- a/github/orgs_properties_test.go +++ b/github/orgs_properties_test.go @@ -313,33 +313,6 @@ func TestOrganizationsService_CreateOrUpdateCustomProperty(t *testing.T) { }) } -func TestCustomProperty_RequireExplicitValuesJSON(t *testing.T) { - t.Parallel() - tests := map[string]struct { - property *CustomProperty - want string - }{ - "omitted": { - property: &CustomProperty{ValueType: PropertyValueTypeString}, - want: `{"value_type":"string"}`, - }, - "explicit false": { - property: &CustomProperty{ - ValueType: PropertyValueTypeString, - RequireExplicitValues: new(false), - }, - want: `{"value_type":"string","require_explicit_values":false}`, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - t.Parallel() - testJSONMarshal(t, test.property, test.want) - }) - } -} - func TestOrganizationsService_RemoveCustomProperty(t *testing.T) { t.Parallel() client, mux, _ := setup(t) From deb10bd48164dcf1dc69788b11192e5919208b01 Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Thu, 17 Sep 2026 12:46:03 +0200 Subject: [PATCH 4/4] Update .golangci.yml Co-authored-by: Dhananjay Mishra --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 7a628039b0c..6828063a288 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -362,7 +362,6 @@ linters: - CreateTag.Object # TODO: Git - CreateTag.Tag # TODO: Git - CreateTag.Type # TODO: Git - - CustomProperty.RequireExplicitValues - DismissalRestrictionsRequest.Apps # TODO: Repositories - DismissalRestrictionsRequest.Teams # TODO: Repositories - DismissalRestrictionsRequest.Users # TODO: Repositories