@@ -3,21 +3,22 @@ package github
33import (
44 "context"
55 "errors"
6- "log"
76 "net/http"
87
98 "github.com/google/go-github/v88/github"
9+ "github.com/hashicorp/terraform-plugin-log/tflog"
10+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1011 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1112)
1213
1314func resourceGithubIssueLabel () * schema.Resource {
1415 return & schema.Resource {
15- Create : resourceGithubIssueLabelCreateOrUpdate ,
16- Read : resourceGithubIssueLabelRead ,
17- Update : resourceGithubIssueLabelCreateOrUpdate ,
18- Delete : resourceGithubIssueLabelDelete ,
16+ CreateContext : resourceGithubIssueLabelCreate ,
17+ ReadContext : resourceGithubIssueLabelRead ,
18+ UpdateContext : resourceGithubIssueLabelUpdate ,
19+ DeleteContext : resourceGithubIssueLabelDelete ,
1920 Importer : & schema.ResourceImporter {
20- StateContext : schema . ImportStatePassthroughContext ,
21+ StateContext : resourceGithubIssueLabelImport ,
2122 },
2223
2324 Schema : map [string ]* schema.Schema {
@@ -60,150 +61,202 @@ func resourceGithubIssueLabel() *schema.Resource {
6061 }
6162}
6263
63- // resourceGithubIssueLabelCreateOrUpdate idempotently creates or updates an
64- // issue label. Issue labels are keyed off of their "name", so pre-existing
65- // issue labels result in a 422 HTTP error if they exist outside of Terraform.
66- // Normally this would not be an issue, except new repositories are created with
67- // a "default" set of labels, and those labels easily conflict with custom ones.
68- //
69- // This function will first check if the label exists, and then issue an update,
70- // otherwise it will create. This is also advantageous in that we get to use the
71- // same function for two schema funcs.
72-
73- func resourceGithubIssueLabelCreateOrUpdate (d * schema.ResourceData , meta any ) error {
74- client := meta .(* Owner ).v3client
75- orgName := meta .(* Owner ).name
76- repoName := d .Get ("repository" ).(string )
77- name := d .Get ("name" ).(string )
78- color := d .Get ("color" ).(string )
64+ // resourceGithubIssueLabelCreate creates an issue label.
65+ func resourceGithubIssueLabelCreate (ctx context.Context , d * schema.ResourceData , m any ) diag.Diagnostics {
66+ meta , _ := m .(* Owner )
67+ client := meta .v3client
68+ orgName := meta .name
69+ repoName , ok := d .Get ("repository" ).(string )
70+ if ! ok {
71+ return diag .Errorf (`expected "repository" to be string` )
72+ }
73+ name , ok := d .Get ("name" ).(string )
74+ if ! ok {
75+ return diag .Errorf (`expected "name" to be string` )
76+ }
77+ color , ok := d .Get ("color" ).(string )
78+ if ! ok {
79+ return diag .Errorf (`expected "color" to be string` )
80+ }
7981
8082 label := & github.Label {
8183 Name : new (name ),
8284 Color : new (color ),
8385 }
84- ctx := context .Background ()
85- if ! d .IsNewResource () {
86- ctx = context .WithValue (ctx , ctxId , d .Id ())
87- }
8886
89- // Pull out the original name. If we already have a resource, this is the
90- // parsed ID. If not, it's the value given to the resource.
91- var originalName string
92- if d .Id () == "" {
93- originalName = name
94- } else {
95- var err error
96- _ , originalName , err = parseID2 (d .Id ())
97- if err != nil {
98- return err
87+ if v , ok := d .GetOk ("description" ); ok {
88+ description , ok := v .(string )
89+ if ! ok {
90+ return diag .Errorf (`expected "description" to be string` )
9991 }
92+ label .Description = & description
10093 }
101-
102- existing , resp , err := client .Issues .GetLabel (ctx ,
103- orgName , repoName , originalName )
104- if err != nil && resp .StatusCode != http .StatusNotFound {
105- return err
106- }
107-
108- if existing != nil {
109- label .Description = new (d.Get ("description" ).(string ))
110-
111- // Pull out the original name. If we already have a resource, this is the
112- // parsed ID. If not, it's the value given to the resource.
113- var originalName string
114- if d .Id () == "" {
115- originalName = name
116- } else {
117- var err error
118- _ , originalName , err = parseID2 (d .Id ())
119- if err != nil {
120- return err
121- }
122- }
123-
124- _ , _ , err := client .Issues .EditLabel (ctx ,
125- orgName , repoName , originalName , label )
126- if err != nil {
127- return err
94+ githubLabel , resp , err := client .Issues .GetLabel (ctx , orgName , repoName , name )
95+ if err != nil {
96+ if resp == nil || resp .StatusCode != http .StatusNotFound {
97+ return diag .FromErr (err )
12898 }
99+ githubLabel , resp , err = client .Issues .CreateLabel (ctx , orgName , repoName , label )
129100 } else {
130- if v , ok := d .GetOk ("description" ); ok {
131- label .Description = new (v .(string ))
132- }
133-
134- _ , _ , err := client .Issues .CreateLabel (ctx ,
135- orgName , repoName , label )
136- if err != nil {
137- return err
138- }
101+ githubLabel , resp , err = client .Issues .EditLabel (ctx , orgName , repoName , name , label )
139102 }
140103
141- d .SetId (buildTwoPartID (repoName , name ))
104+ if err != nil {
105+ return diag .FromErr (err )
106+ }
107+ id , err := buildID (repoName , name )
108+ if err != nil {
109+ return diag .FromErr (err )
110+ }
111+ d .SetId (id )
112+ if err := d .Set ("url" , githubLabel .GetURL ()); err != nil {
113+ return diag .FromErr (err )
114+ }
142115
143- return resourceGithubIssueLabelRead (d , meta )
116+ if err := d .Set ("etag" , resp .Header .Get ("ETag" )); err != nil {
117+ return diag .FromErr (err )
118+ }
119+ return nil
144120}
145121
146- func resourceGithubIssueLabelRead (d * schema.ResourceData , meta any ) error {
147- client := meta .(* Owner ).v3client
148- repoName , name , err := parseID2 (d .Id ())
149- if err != nil {
150- return err
122+ func resourceGithubIssueLabelRead (ctx context.Context , d * schema.ResourceData , m any ) diag.Diagnostics {
123+ meta , _ := m .(* Owner )
124+ client := meta .v3client
125+ repoName , ok := d .Get ("repository" ).(string )
126+ if ! ok {
127+ return diag .Errorf (`expected "repository" to be string` )
128+ }
129+ name , ok := d .Get ("name" ).(string )
130+ if ! ok {
131+ return diag .Errorf (`expected "name" to be string` )
151132 }
152133
153- orgName := meta .(* Owner ).name
154- ctx := context .WithValue (context .Background (), ctxId , d .Id ())
134+ orgName := meta .name
155135 if ! d .IsNewResource () {
156136 ctx = context .WithValue (ctx , ctxEtag , d .Get ("etag" ).(string ))
157137 }
158138
159- githubLabel , resp , err := client .Issues .GetLabel (ctx ,
160- orgName , repoName , name )
139+ githubLabel , resp , err := client .Issues .GetLabel (ctx , orgName , repoName , name )
161140 if err != nil {
162141 var ghErr * github.ErrorResponse
163142 if errors .As (err , & ghErr ) {
164143 if ghErr .Response .StatusCode == http .StatusNotModified {
165144 return nil
166145 }
167146 if ghErr .Response .StatusCode == http .StatusNotFound {
168- log .Printf ("[INFO] Removing label %s (%s/%s) from state because it no longer exists in GitHub" ,
169- name , orgName , repoName )
147+ tflog .Info (ctx , "Removing label from state because it no longer exists in GitHub" , map [string ]any {"name" : name , "org_name" : orgName , "repo_name" : repoName })
170148 d .SetId ("" )
171149 return nil
172150 }
173151 }
174- return err
152+ return diag . FromErr ( err )
175153 }
176154
177- if err = d .Set ("etag" , resp .Header .Get ("ETag" )); err != nil {
178- return err
179- }
180- if err = d .Set ("repository" , repoName ); err != nil {
181- return err
182- }
183- if err = d .Set ("name" , name ); err != nil {
184- return err
185- }
186155 if err = d .Set ("color" , githubLabel .GetColor ()); err != nil {
187- return err
156+ return diag . FromErr ( err )
188157 }
189158 if err = d .Set ("description" , githubLabel .GetDescription ()); err != nil {
190- return err
159+ return diag .FromErr (err )
160+ }
161+
162+ if err = d .Set ("etag" , resp .Header .Get ("ETag" )); err != nil {
163+ return diag .FromErr (err )
191164 }
192165 if err = d .Set ("url" , githubLabel .GetURL ()); err != nil {
193- return err
166+ return diag . FromErr ( err )
194167 }
195168
196169 return nil
197170}
198171
199- func resourceGithubIssueLabelDelete (d * schema.ResourceData , meta any ) error {
200- client := meta .(* Owner ).v3client
172+ func resourceGithubIssueLabelUpdate (ctx context.Context , d * schema.ResourceData , m any ) diag.Diagnostics {
173+ meta , _ := m .(* Owner )
174+ client := meta .v3client
175+ orgName := meta .name
176+ repoName , ok := d .Get ("repository" ).(string )
177+ if ! ok {
178+ return diag .Errorf (`expected "repository" to be string` )
179+ }
180+ name , ok := d .Get ("name" ).(string )
181+ if ! ok {
182+ return diag .Errorf (`expected "name" to be string` )
183+ }
184+ color , ok := d .Get ("color" ).(string )
185+ if ! ok {
186+ return diag .Errorf (`expected "color" to be string` )
187+ }
188+
189+ originalName := name
190+ if d .HasChange ("name" ) {
191+ oldName , _ := d .GetChange ("name" )
192+ oldNameString , ok := oldName .(string )
193+ if ! ok {
194+ return diag .Errorf (`expected old "name" to be string` )
195+ }
196+ originalName = oldNameString
197+ }
198+ label := & github.Label {
199+ Name : new (name ),
200+ Color : new (color ),
201+ }
202+ if v , ok := d .GetOk ("description" ); ok {
203+ description , ok := v .(string )
204+ if ! ok {
205+ return diag .Errorf (`expected "description" to be string` )
206+ }
207+ label .Description = & description
208+ }
209+ githubLabel , resp , err := client .Issues .EditLabel (ctx , orgName , repoName , originalName , label )
210+ if err != nil {
211+ return diag .FromErr (err )
212+ }
213+ id , err := buildID (repoName , name )
214+ if err != nil {
215+ return diag .FromErr (err )
216+ }
217+ d .SetId (id )
218+
219+ if err := d .Set ("url" , githubLabel .GetURL ()); err != nil {
220+ return diag .FromErr (err )
221+ }
201222
202- orgName := meta .(* Owner ).name
203- repoName := d .Get ("repository" ).(string )
204- name := d .Get ("name" ).(string )
205- ctx := context .WithValue (context .Background (), ctxId , d .Id ())
223+ if err := d .Set ("etag" , resp .Header .Get ("ETag" )); err != nil {
224+ return diag .FromErr (err )
225+ }
226+
227+ return nil
228+ }
229+
230+ func resourceGithubIssueLabelDelete (ctx context.Context , d * schema.ResourceData , m any ) diag.Diagnostics {
231+ meta , _ := m .(* Owner )
232+ client := meta .v3client
233+ orgName := meta .name
206234
235+ repoName , ok := d .Get ("repository" ).(string )
236+ if ! ok {
237+ return diag .Errorf (`expected "repository" to be string` )
238+ }
239+ name , ok := d .Get ("name" ).(string )
240+ if ! ok {
241+ return diag .Errorf (`expected "name" to be string` )
242+ }
207243 _ , err := client .Issues .DeleteLabel (ctx , orgName , repoName , name )
208- return handleArchivedRepoDelete (err , "issue label" , name , orgName , repoName )
244+ return diag .FromErr (handleArchivedRepoDelete (err , "issue label" , name , orgName , repoName ))
245+ }
246+
247+ func resourceGithubIssueLabelImport (_ context.Context , d * schema.ResourceData , _ any ) ([]* schema.ResourceData , error ) {
248+ repoName , name , err := parseID2 (d .Id ())
249+ if err != nil {
250+ return nil , err
251+ }
252+
253+ if err := d .Set ("repository" , repoName ); err != nil {
254+ return nil , err
255+ }
256+
257+ if err := d .Set ("name" , name ); err != nil {
258+ return nil , err
259+ }
260+
261+ return []* schema.ResourceData {d }, nil
209262}
0 commit comments