feat: Add github_organization_security_configuration and github_enterprise_security_configuration resource#3143
Conversation
|
👋 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 |
|
@deiga ready for review |
|
@nickfloyd @deiga is there anything else you need to help get this through. We are keen on this feature :) |
|
@sprioriello You'll need to at least rebase this 😬 |
deiga
left a comment
There was a problem hiding this comment.
Please apply applicable changes also to the Org resource, I don't want to repeat myself there
| "code_security": { | ||
| Type: schema.TypeString, | ||
| Optional: true, | ||
| Default: "disabled", |
There was a problem hiding this comment.
issue: Since the SDK has the omitempty tag configured for this field, I wonder if a default is going to be harmful. Especially since the API docs don't define a default either.
What if we don't set a default and use GetOk to check if we should include it or not in the payload?
There was a problem hiding this comment.
Done. Removed all Default values from optional fields and switched to using d.GetOk() to check if values should be included in the payload. Applied to both enterprise and org resources.
|
|
||
| d.SetId(strconv.FormatInt(configuration.GetID(), 10)) | ||
|
|
||
| return resourceGithubEnterpriseSecurityConfigurationRead(ctx, d, meta) |
There was a problem hiding this comment.
You need to populate any Computed fields inside Create
| return resourceGithubEnterpriseSecurityConfigurationRead(ctx, d, meta) | |
| return nil |
There was a problem hiding this comment.
Done. Create now sets computed fields (target_type) and returns nil instead of calling Read.
| } else if codeSec == "enabled" || secretProt == "enabled" { | ||
| config.CodeSecurity = github.Ptr(codeSec) | ||
| config.SecretProtection = github.Ptr(secretProt) |
There was a problem hiding this comment.
question: Even though these are closely linked, do they really need to be set in tandem? Would it be safer set these 1 by 1?
There was a problem hiding this comment.
Good point. Refactored to set each field individually using d.GetOk() rather than the tandem approach.
| resource "github_enterprise_security_configuration" "test" { | ||
| enterprise_slug = "%s" | ||
| name = "%s" | ||
| description = "Test configuration" | ||
| advanced_security = "enabled" | ||
| dependency_graph = "enabled" | ||
| dependabot_alerts = "enabled" | ||
| dependabot_security_updates = "enabled" | ||
| code_scanning_default_setup = "enabled" | ||
| secret_scanning = "enabled" | ||
| secret_scanning_push_protection = "enabled" | ||
| private_vulnerability_reporting = "enabled" | ||
| enforcement = "enforced" |
There was a problem hiding this comment.
Please add a testcase which uses miminal configs to test that defaults work
There was a problem hiding this comment.
Done. Added a "creates enterprise security configuration with minimal config" test that only sets enterprise_slug and name, and verifies target_type is set. Also added equivalent test for the org resource.
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| d.SetId(strconv.FormatInt(configuration.GetID(), 10)) |
There was a problem hiding this comment.
issue: These IDs seem to be just numbers, so a clash between resource is highly likely. What if we'd use buildID(enterprise, configuration.GetID()) to at least make the collision likelyhood smaller?
There was a problem hiding this comment.
Done. Now using buildID(enterprise, strconv.FormatInt(configuration.GetID(), 10)) to create composite IDs. Updated Read, Update, Delete, and Import to use parseID2 accordingly. Also updated ImportStateIdPrefix in tests from "/" to ":" separator.
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| d.SetId(strconv.FormatInt(configuration.GetID(), 10)) |
There was a problem hiding this comment.
issue: These IDs seem to be just numbers, so a clash between resource is highly likely. What if we'd use buildID(org, configuration.GetID()) to at least make the collision likelyhood smaller?
There was a problem hiding this comment.
Done. Same composite ID pattern applied to the org resource using buildID(org, ...).
|
|
||
| d.SetId(strconv.FormatInt(configuration.GetID(), 10)) | ||
|
|
||
| return resourceGithubOrganizationSecurityConfigurationRead(ctx, d, meta) |
There was a problem hiding this comment.
| return resourceGithubOrganizationSecurityConfigurationRead(ctx, d, meta) | |
| return nil |
There was a problem hiding this comment.
Done. Create and Update in org resource now return nil instead of calling Read.
Acceptance Test ResultsAll 8 acceptance tests pass (4 organization + 4 enterprise): |
47e7766 to
33ae057
Compare
@deiga rebased and addressed comments as requested. Thank you |
deiga
left a comment
There was a problem hiding this comment.
Please review all the comments we've left before and check that they are actually done. Many seem to have somehow gotten reverted
|
|
||
| func resourceGithubEnterpriseSecurityConfigurationCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v3client | ||
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
There was a problem hiding this comment.
You claimed to have removed this, but it's still there. What's going on?
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
There was a problem hiding this comment.
Sorry my mistake. I made a mistake when rebasing and missed something. Should be fixed now.
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
issue: Please populate the Computed fields in Create
There was a problem hiding this comment.
In both files, Create and Update now call Read at the end instead returning nil
|
|
||
| func resourceGithubEnterpriseSecurityConfigurationRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v3client | ||
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
There was a problem hiding this comment.
You claimed to have removed this, but it's still there. What's going on?
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
| var ghErr *github.ErrorResponse | ||
| if errors.As(err, &ghErr) { | ||
| if ghErr.Response.StatusCode == http.StatusNotFound { | ||
| d.SetId("") |
There was a problem hiding this comment.
I asked you to add some logging output with tflog, but you didn't?https://github.com/integrations/terraform-provider-github/pull/3143/changes#r2811597046
There was a problem hiding this comment.
Added additional logging as requested with tflog library referencing the recent pull request to github/resource_github_organization_ruleset.go
|
|
||
| func resourceGithubEnterpriseSecurityConfigurationUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v3client | ||
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
There was a problem hiding this comment.
You claimed to have removed this, but it's still there. What's going on?
| ctx = context.WithValue(ctx, ctxId, d.Id()) |
| enterprise := d.Get("enterprise_slug").(string) | ||
|
|
||
| enterprise, idStr, err := parseID2(d.Id()) |
There was a problem hiding this comment.
issue: setting enterprise twice
There was a problem hiding this comment.
Removed enterprise := d.Get("enterprise_slug").(string)
| Steps: []resource.TestStep{ | ||
| { | ||
| Config: config, | ||
| Check: resource.ComposeTestCheckFunc( |
There was a problem hiding this comment.
Please refactor all Check: in all TestStep to use ConfigStateCheck: instead. https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/state-checks/resource
There was a problem hiding this comment.
Done. Both test files migrated from Check: resource.ComposeTestCheckFunc(...) to ConfigStateChecks:
| m := make(map[string]any) | ||
| if options.Reviewers != nil { | ||
| reviewers := make([]any, 0, len(options.Reviewers)) | ||
| for _, r := range options.Reviewers { | ||
| rM := make(map[string]any) | ||
| rM["reviewer_id"] = r.ReviewerID | ||
| rM["reviewer_type"] = r.ReviewerType | ||
| reviewers = append(reviewers, rM) | ||
| } | ||
| m["reviewers"] = reviewers | ||
| } |
There was a problem hiding this comment.
Please don't use single char variables, it degrades readability of the code a lot
There was a problem hiding this comment.
Done. Renamed all single-char variables in util_security_configuration.go and the other two files.
| StateContext: schema.ImportStatePassthroughContext, | ||
| }, | ||
|
|
||
| Schema: map[string]*schema.Schema{ |
There was a problem hiding this comment.
Added a description for both resources.
a14d69e to
6fec8f5
Compare
051a400 to
cdb1e63
Compare
…prise_security_configuration resources This commit adds two new resources to manage Code Security Configurations: - `github_organization_security_configuration`: manages code security configurations at the organization level - `github_enterprise_security_configuration`: manages code security configurations at the enterprise level Both resources include: - Full CRUD operations using GitHub's Code Security Configurations API - Composite IDs (org/enterprise + config ID) to avoid state collisions - 404-tolerant delete (treats already-deleted resources as success) - tflog structured logging throughout - All optional fields use GetOk to avoid sending unset values - Custom import support Acceptance tests (8 total, 4 per resource): - creates without error - updates without error - creates with nested options (runner, autosubmit, bypass) - creates with minimal config Documentation added for both resources. Resolves integrations#2412
cdb1e63 to
6d3c919
Compare
This commit adds a new resource github_organization_security_configuration & github_enterprise_security_configuration to manage Code Security Configurations at the organization & enterprise level respectively. It includes:
Resolves #2412
Before the change?
After the change?
Pull request checklist
Does this introduce a breaking change?
Please see our docs on breaking changes to help!
Tests