[FEAT] Add github_repository_pages Resource and Data Source#3168
[FEAT] Add github_repository_pages Resource and Data Source#3168deiga wants to merge 21 commits intointegrations:mainfrom
github_repository_pages Resource and Data Source#3168Conversation
|
👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday! We have a process in place for prioritizing and responding to your input. Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labeled with |
e081a2d to
c75d366
Compare
stevehipwell
left a comment
There was a problem hiding this comment.
This is looking really good.
c75d366 to
91f6484
Compare
|
@healiha I'll check that out |
github_repository_pages Reasource and Data Sourcegithub_repository_pages Resource and Data Source
|
@deiga could you please rebase this PR? |
18c8135 to
55b203a
Compare
| // Determine if we need to update the page with CNAME or public flag | ||
| shouldUpdatePage := false | ||
| update := &github.PagesUpdate{} | ||
| cname, cnameExists := d.GetOk("cname") | ||
| if cnameExists && cname.(string) != "" { | ||
| shouldUpdatePage = true | ||
| update.CNAME = github.Ptr(cname.(string)) | ||
| } | ||
| public, publicExists := d.GetOkExists("public") // nolint:staticcheck // SA1019: There is no better alternative for checking if boolean value is set | ||
| if publicExists && public != nil { | ||
| shouldUpdatePage = true | ||
| update.Public = github.Ptr(public.(bool)) | ||
| } else { | ||
| if err := d.Set("public", pages.GetPublic()); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } | ||
| httpsEnforced, httpsEnforcedExists := d.GetOkExists("https_enforced") // nolint:staticcheck // SA1019: There is no better alternative for checking if boolean value is set | ||
| if httpsEnforcedExists && httpsEnforced != nil { | ||
| shouldUpdatePage = true | ||
| update.HTTPSEnforced = github.Ptr(httpsEnforced.(bool)) | ||
| } else { | ||
| if err := d.Set("https_enforced", pages.GetHTTPSEnforced()); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } | ||
|
|
||
| if shouldUpdatePage { | ||
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } |
There was a problem hiding this comment.
| // Determine if we need to update the page with CNAME or public flag | |
| shouldUpdatePage := false | |
| update := &github.PagesUpdate{} | |
| cname, cnameExists := d.GetOk("cname") | |
| if cnameExists && cname.(string) != "" { | |
| shouldUpdatePage = true | |
| update.CNAME = github.Ptr(cname.(string)) | |
| } | |
| public, publicExists := d.GetOkExists("public") // nolint:staticcheck // SA1019: There is no better alternative for checking if boolean value is set | |
| if publicExists && public != nil { | |
| shouldUpdatePage = true | |
| update.Public = github.Ptr(public.(bool)) | |
| } else { | |
| if err := d.Set("public", pages.GetPublic()); err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| httpsEnforced, httpsEnforcedExists := d.GetOkExists("https_enforced") // nolint:staticcheck // SA1019: There is no better alternative for checking if boolean value is set | |
| if httpsEnforcedExists && httpsEnforced != nil { | |
| shouldUpdatePage = true | |
| update.HTTPSEnforced = github.Ptr(httpsEnforced.(bool)) | |
| } else { | |
| if err := d.Set("https_enforced", pages.GetHTTPSEnforced()); err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| if shouldUpdatePage { | |
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | |
| if err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| // Check if we have values set that can't be configured as part of the create logic | |
| cname, cnameOK := d.GetOk("cname") | |
| public := d.get("public").(bool) | |
| httpsEnforced := d.Get("https_enforced").(bool) | |
| if cnameOK || public || httpsEnforced { | |
| update := &github.PagesUpdate{} | |
| if cnameOK { | |
| update.CNAME = github.Ptr(cname.(string)) | |
| } | |
| if public { | |
| update.Public = github.Ptr(public) | |
| } | |
| if httpsEnforced { | |
| update.HTTPSEnforced = github.Ptr(httpsEnforced) | |
| } | |
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | |
| if err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } |
The logic for this can be significantly simplified as we only care about true values and this code is only run for the create.
There was a problem hiding this comment.
Thanks! We do care are about the false value for public too, since a non-EMU GHEC can set either.
But I'll adopt your suggestion with that modification!
There was a problem hiding this comment.
What I mean is that the unset value matches the default value. We only need to use the hacky method if we care about differentiating between false and unset.
In update, I'd expect the value to be set as we usually do rather than checking for a diff. Unless there is a specific reason not to?
There was a problem hiding this comment.
I restructured it, but had to re-add the d.Set calls as otherwise the computed values won't be set
|
|
||
| update := &github.PagesUpdate{} | ||
|
|
||
| if d.HasChange("cname") { |
There was a problem hiding this comment.
We generally don't use this pattern, I'd expect to see d.get() & d.GetOk() here.
There was a problem hiding this comment.
I'm not sure I understand what you mean. d.HasChange has been used ~36 times in the codebase.
d.HasChange() tells us if there is a value change in the plan, whereas d.Get() and d.GetOk() would cause us to send fields even if they are not changed
There was a problem hiding this comment.
I don't think 36 usages, some of which are definitely in diff functions, comes close to the occurrences of the get functions. The only reason you're in the update function is that there are changes to apply, so building the struct using the get functions (d.Get() for bools & d.GetOk() for strings where that aren't always set) is going to be the most efficient and readable pattern.
There was a problem hiding this comment.
Since the API supports partial updates, I don't fully understand why we wouldn't want to utilize that.
For example these Optional & Computed fields are things that I wouldn't want to send unless they are actually changed in the plan and have been modified by the user.
Though I guess d.GetOk() isn't able to determine the latter once they have been set by Create or Read?
Could you elaborate the issue you're seeing with using d.HasChange()?
There was a problem hiding this comment.
The API supports partial updates, but Terraform doesn't. The idiomatic pattern in this provider is to set all of the fields being managed by Terraform before making a request; this makes the code as readable as possible and makes it less likely that we are impacted by edge case issues (our code path is as small and non-branching as possible). By using d.hasChanges() you're adding unnecessary complexity.
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
… config Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
7a1f79f to
56b7d70
Compare
| "public": { | ||
| Type: schema.TypeBool, | ||
| Optional: true, | ||
| Computed: true, |
There was a problem hiding this comment.
| Computed: true, | |
| Default: false, |
| "https_enforced": { | ||
| Type: schema.TypeBool, | ||
| Optional: true, | ||
| Computed: true, |
There was a problem hiding this comment.
| Computed: true, | |
| Default: false, |
| // Check if we have values set that can't be configured as part of the create logic | ||
| cname, cnameOK := d.GetOk("cname") | ||
| public, publicOKExists := d.GetOkExists("public") //nolint:staticcheck // SA1019: d.GetOkExists is deprecated but necessary for bool fields | ||
| httpsEnforced, httpsEnforcedExists := d.GetOkExists("https_enforced") //nolint:staticcheck // SA1019: d.GetOkExists is deprecated but necessary for bool fields | ||
| tflog.Debug(ctx, "Do we have values set that need the update logic?", map[string]any{ | ||
| "public": public, | ||
| "public_ok_exists": publicOKExists, | ||
| "https_enforced": httpsEnforced, | ||
| "https_enforced_exists": httpsEnforcedExists, | ||
| "cname": cname, | ||
| "cname_ok": cnameOK, | ||
| }) | ||
|
|
||
| if cnameOK || publicOKExists || httpsEnforcedExists { | ||
| update := &github.PagesUpdate{} | ||
|
|
||
| if cnameOK { | ||
| update.CNAME = github.Ptr(cname.(string)) | ||
| } | ||
|
|
||
| if publicOKExists { | ||
| update.Public = github.Ptr(public.(bool)) | ||
| } | ||
|
|
||
| if httpsEnforcedExists { | ||
| update.HTTPSEnforced = github.Ptr(httpsEnforced.(bool)) | ||
| } | ||
|
|
||
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } | ||
| if !publicOKExists { | ||
| if err := d.Set("public", pages.GetPublic()); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } | ||
| if !httpsEnforcedExists { | ||
| if err := d.Set("https_enforced", pages.GetHTTPSEnforced()); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| } |
There was a problem hiding this comment.
| // Check if we have values set that can't be configured as part of the create logic | |
| cname, cnameOK := d.GetOk("cname") | |
| public, publicOKExists := d.GetOkExists("public") //nolint:staticcheck // SA1019: d.GetOkExists is deprecated but necessary for bool fields | |
| httpsEnforced, httpsEnforcedExists := d.GetOkExists("https_enforced") //nolint:staticcheck // SA1019: d.GetOkExists is deprecated but necessary for bool fields | |
| tflog.Debug(ctx, "Do we have values set that need the update logic?", map[string]any{ | |
| "public": public, | |
| "public_ok_exists": publicOKExists, | |
| "https_enforced": httpsEnforced, | |
| "https_enforced_exists": httpsEnforcedExists, | |
| "cname": cname, | |
| "cname_ok": cnameOK, | |
| }) | |
| if cnameOK || publicOKExists || httpsEnforcedExists { | |
| update := &github.PagesUpdate{} | |
| if cnameOK { | |
| update.CNAME = github.Ptr(cname.(string)) | |
| } | |
| if publicOKExists { | |
| update.Public = github.Ptr(public.(bool)) | |
| } | |
| if httpsEnforcedExists { | |
| update.HTTPSEnforced = github.Ptr(httpsEnforced.(bool)) | |
| } | |
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | |
| if err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| if !publicOKExists { | |
| if err := d.Set("public", pages.GetPublic()); err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| if !httpsEnforcedExists { | |
| if err := d.Set("https_enforced", pages.GetHTTPSEnforced()); err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } | |
| // Check if we have values set that can't be configured as part of the create logic | |
| cname, cnameOK := d.GetOk("cname") | |
| public := d.Get("public").(bool) | |
| httpsEnforced := d.Get("https_enforced").(bool) | |
| if cnameOK || public || httpsEnforced { | |
| tflog.Debug(ctx, "values set that require an update after create", map[string]any{ | |
| "public": public, | |
| "https_enforced": httpsEnforced, | |
| "cname": cname, | |
| }) | |
| update := &github.PagesUpdate{} | |
| if cnameOK { | |
| update.CNAME = github.Ptr(cname.(string)) | |
| } | |
| if public { | |
| update.Public = github.Ptr(public) | |
| } | |
| if httpsEnforcedExists { | |
| update.HTTPSEnforced = github.Ptr(httpsEnforced) | |
| } | |
| _, err = client.Repositories.UpdatePages(ctx, owner, repoName, update) | |
| if err != nil { | |
| return diag.FromErr(err) | |
| } | |
| } |
We only care about the non-default values so we can short circuit the behaviour in the create function. Note the boolean values now have defaults so they don't need setting.

Resolves #3167
Resolves #2671
Resolves #3142
Resolves #1045
Resolves #2653
Resolves #2335
Before the change?
github_repositoryAfter the change?
github_repository_pagesresource to manage the pagesgithub_repository_pagesdata source to fetch information about the pagesgithub_repositoryResource and Data Sourcepublicfield ofgithub_repository_pageshttps_enforcedfield ofgithub_repository_pagesPull request checklist
Schema migrations have been created if needed (example)Does this introduce a breaking change?
Please see our docs on breaking changes to help!