@@ -2,39 +2,38 @@ package github
22
33import (
44 "context"
5+ "fmt"
6+ "log"
7+ "net/http"
58
69 "github.com/google/go-github/v84/github"
7- "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
810 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
911 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1012)
1113
1214func resourceGithubOrganizationCustomProperties () * schema.Resource {
1315 return & schema.Resource {
14- Create : resourceGithubCustomPropertiesCreate ,
15- Read : resourceGithubCustomPropertiesRead ,
16- Update : resourceGithubCustomPropertiesUpdate ,
17- Delete : resourceGithubCustomPropertiesDelete ,
16+ Description : "Creates and manages a custom property for a GitHub Organization." ,
17+ Create : resourceGithubCustomPropertiesCreate ,
18+ Read : resourceGithubCustomPropertiesRead ,
19+ Update : resourceGithubCustomPropertiesUpdate ,
20+ Delete : resourceGithubCustomPropertiesDelete ,
1821 Importer : & schema.ResourceImporter {
1922 State : resourceGithubCustomPropertiesImport ,
2023 },
2124
22- CustomizeDiff : customdiff .Sequence (
23- customdiff .ComputedIf ("slug" , func (_ context.Context , d * schema.ResourceDiff , meta any ) bool {
24- return d .HasChange ("name" )
25- }),
26- ),
27-
2825 Schema : map [string ]* schema.Schema {
2926 "property_name" : {
3027 Type : schema .TypeString ,
3128 Required : true ,
29+ ForceNew : true ,
3230 Description : "The name of the custom property" ,
3331 },
3432 "value_type" : {
3533 Type : schema .TypeString ,
36- Optional : true ,
37- Description : "The type of the custom property" ,
34+ Required : true ,
35+ ForceNew : true ,
36+ Description : "The type of the custom property. Can be one of: 'string', 'single_select', 'multi_select', 'true_false', or 'url'." ,
3837 ValidateDiagFunc : validation .ToDiagFunc (validation .StringInSlice ([]string {string (github .PropertyValueTypeString ), string (github .PropertyValueTypeSingleSelect ), string (github .PropertyValueTypeMultiSelect ), string (github .PropertyValueTypeTrueFalse ), string (github .PropertyValueTypeURL )}, false )),
3938 },
4039 "required" : {
@@ -73,52 +72,83 @@ func resourceGithubOrganizationCustomProperties() *schema.Resource {
7372}
7473
7574func resourceGithubCustomPropertiesCreate (d * schema.ResourceData , meta any ) error {
75+ if err := checkOrganization (meta ); err != nil {
76+ return err
77+ }
78+
7679 ctx := context .Background ()
7780 client := meta .(* Owner ).v3client
7881 ownerName := meta .(* Owner ).name
7982
8083 propertyName := d .Get ("property_name" ).(string )
8184 valueType := github .PropertyValueType (d .Get ("value_type" ).(string ))
8285 required := d .Get ("required" ).(bool )
83- defaultValue := d .Get ("default_value" ).(string )
8486 description := d .Get ("description" ).(string )
85- allowedValues := d .Get ("allowed_values" ).([]any )
86- var allowedValuesString []string
87- for _ , v := range allowedValues {
88- allowedValuesString = append (allowedValuesString , v .(string ))
89- }
9087
9188 customProperty := & github.CustomProperty {
92- PropertyName : & propertyName ,
93- ValueType : valueType ,
94- Required : & required ,
95- DefaultValue : & defaultValue ,
96- Description : & description ,
97- AllowedValues : allowedValuesString ,
89+ PropertyName : & propertyName ,
90+ ValueType : valueType ,
91+ Required : & required ,
92+ Description : & description ,
93+ }
94+
95+ // Set default value if provided
96+ if v , ok := d .GetOk ("default_value" ); ok {
97+ defaultValue := v .(string )
98+ customProperty .DefaultValue = & defaultValue
99+ }
100+
101+ // Set allowed values if provided (only valid for select types)
102+ if v , ok := d .GetOk ("allowed_values" ); ok {
103+ allowedValues := expandStringList (v .([]any ))
104+ if valueType == github .PropertyValueTypeSingleSelect || valueType == github .PropertyValueTypeMultiSelect {
105+ customProperty .AllowedValues = allowedValues
106+ } else {
107+ return fmt .Errorf ("allowed_values can only be set for single_select or multi_select value types" )
108+ }
109+ }
110+
111+ // Validate that allowed_values is provided for select types
112+ if (valueType == github .PropertyValueTypeSingleSelect || valueType == github .PropertyValueTypeMultiSelect ) && len (customProperty .AllowedValues ) == 0 {
113+ return fmt .Errorf ("allowed_values is required for %s value type" , valueType )
98114 }
99115
100116 if val , ok := d .GetOk ("values_editable_by" ); ok {
101117 str := val .(string )
102118 customProperty .ValuesEditableBy = & str
103119 }
104120
105- customProperty , _ , err := client .Organizations .CreateOrUpdateCustomProperty (ctx , ownerName , d . Get ( "property_name" ).( string ) , customProperty )
121+ customProperty , _ , err := client .Organizations .CreateOrUpdateCustomProperty (ctx , ownerName , propertyName , customProperty )
106122 if err != nil {
107- return err
123+ return fmt . Errorf ( "error creating organization custom property %s: %w" , propertyName , err )
108124 }
109125
110126 d .SetId (* customProperty .PropertyName )
111127 return resourceGithubCustomPropertiesRead (d , meta )
112128}
113129
114130func resourceGithubCustomPropertiesRead (d * schema.ResourceData , meta any ) error {
131+ if err := checkOrganization (meta ); err != nil {
132+ return err
133+ }
134+
115135 ctx := context .Background ()
116136 client := meta .(* Owner ).v3client
117137 ownerName := meta .(* Owner ).name
118138
119- customProperty , _ , err := client .Organizations .GetCustomProperty (ctx , ownerName , d .Get ("property_name" ).(string ))
139+ propertyName := d .Id ()
140+ if pn , ok := d .GetOk ("property_name" ); ok {
141+ propertyName = pn .(string )
142+ }
143+
144+ customProperty , resp , err := client .Organizations .GetCustomProperty (ctx , ownerName , propertyName )
120145 if err != nil {
121- return err
146+ if resp != nil && resp .StatusCode == http .StatusNotFound {
147+ log .Printf ("[WARN] Removing organization custom property %s from state because it no longer exists in GitHub" , propertyName )
148+ d .SetId ("" )
149+ return nil
150+ }
151+ return fmt .Errorf ("error reading organization custom property %s: %w" , propertyName , err )
122152 }
123153
124154 // TODO: Add support for other types of default values
@@ -137,19 +167,22 @@ func resourceGithubCustomPropertiesRead(d *schema.ResourceData, meta any) error
137167}
138168
139169func resourceGithubCustomPropertiesUpdate (d * schema.ResourceData , meta any ) error {
140- if err := resourceGithubCustomPropertiesCreate (d , meta ); err != nil {
141- return err
142- }
143- return resourceGithubCustomPropertiesRead (d , meta )
170+ // Create uses the same upsert API, and already calls Read at the end
171+ return resourceGithubCustomPropertiesCreate (d , meta )
144172}
145173
146174func resourceGithubCustomPropertiesDelete (d * schema.ResourceData , meta any ) error {
175+ if err := checkOrganization (meta ); err != nil {
176+ return err
177+ }
178+
147179 client := meta .(* Owner ).v3client
148180 ownerName := meta .(* Owner ).name
181+ propertyName := d .Get ("property_name" ).(string )
149182
150- _ , err := client .Organizations .RemoveCustomProperty (context .Background (), ownerName , d . Get ( "property_name" ).( string ) )
183+ _ , err := client .Organizations .RemoveCustomProperty (context .Background (), ownerName , propertyName )
151184 if err != nil {
152- return err
185+ return fmt . Errorf ( "error deleting organization custom property %s: %w" , propertyName , err )
153186 }
154187
155188 return nil
0 commit comments