Skip to content

Comments

feat: Add github_organization_security_configuration and github_enterprise_security_configuration resource#3143

Open
sprioriello wants to merge 3 commits intointegrations:mainfrom
sprioriello:feat/organization-security-configuration
Open

feat: Add github_organization_security_configuration and github_enterprise_security_configuration resource#3143
sprioriello wants to merge 3 commits intointegrations:mainfrom
sprioriello:feat/organization-security-configuration

Conversation

@sprioriello
Copy link

@sprioriello sprioriello commented Jan 30, 2026

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:

  • Resource implementation.
  • Acceptance tests.
  • Documentation.
  • Provider registration.

Resolves #2412


Before the change?

  • Resource not available.

After the change?

  • Implement code security configuration resource on organizational level.

Pull request checklist

  • Schema migrations have been created if needed (example)
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)

Does this introduce a breaking change?

Please see our docs on breaking changes to help!

  • Yes
  • No

Tests

==> Running acceptance tests on branch: 🌿 feat/organization-security-configuration 🌿...
TF_ACC=1 CGO_ENABLED=0 go test ./github/... -v -run '^TestAcc' -run='TestAccGithubOrganizationSecurityConfiguration'  -timeout 120m -count=1
=== RUN   TestAccGithubOrganizationSecurityConfiguration
=== RUN   TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_without_error
=== RUN   TestAccGithubOrganizationSecurityConfiguration/updates_organization_security_configuration_without_error
=== RUN   TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_with_options
=== RUN   TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_with_minimal_config
--- PASS: TestAccGithubOrganizationSecurityConfiguration (48.02s)
    --- PASS: TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_without_error (12.08s)
    --- PASS: TestAccGithubOrganizationSecurityConfiguration/updates_organization_security_configuration_without_error (15.99s)
    --- PASS: TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_with_options (10.98s)
    --- PASS: TestAccGithubOrganizationSecurityConfiguration/creates_organization_security_configuration_with_minimal_config (8.96s)
PASS
ok      github.com/integrations/terraform-provider-github/v6/github     48.317s
==> Running acceptance tests on branch: 🌿 feat/organization-security-configuration 🌿...
TF_ACC=1 CGO_ENABLED=0 go test ./github/... -v -run '^TestAcc' -run='TestAccGithubEnterpriseSecurityConfiguration'  -timeout 120m -count=1
=== RUN   TestAccGithubEnterpriseSecurityConfiguration
=== RUN   TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_without_error
=== RUN   TestAccGithubEnterpriseSecurityConfiguration/updates_enterprise_security_configuration_without_error
=== RUN   TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_with_options
=== RUN   TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_with_minimal_config
--- PASS: TestAccGithubEnterpriseSecurityConfiguration (46.68s)
    --- PASS: TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_without_error (10.97s)
    --- PASS: TestAccGithubEnterpriseSecurityConfiguration/updates_enterprise_security_configuration_without_error (15.31s)
    --- PASS: TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_with_options (11.52s)
    --- PASS: TestAccGithubEnterpriseSecurityConfiguration/creates_enterprise_security_configuration_with_minimal_config (8.88s)
PASS
ok      github.com/integrations/terraform-provider-github/v6/github     46.923s

@github-actions github-actions bot added the Type: Feature New feature or request label Jan 30, 2026
@github-actions
Copy link

👋 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 Status: Up for grabs. You & others like you are the reason all of this works! So thank you & happy coding! 🚀

@sprioriello sprioriello changed the title feat: Add github_organization_security_configuration resource [FEAT]: Add github_organization_security_configuration resource Jan 30, 2026
@sprioriello sprioriello changed the title [FEAT]: Add github_organization_security_configuration resource feat: Add github_organization_security_configuration resource Jan 30, 2026
@sprioriello sprioriello changed the title feat: Add github_organization_security_configuration resource feat: Add github_organization_security_configuration and github_enterprise_security_configuration resource Feb 1, 2026
@sprioriello
Copy link
Author

@deiga ready for review

@sprioriello sprioriello requested a review from deiga February 3, 2026 10:55
@sprioriello
Copy link
Author

sprioriello commented Feb 9, 2026

@nickfloyd @deiga is there anything else you need to help get this through. We are keen on this feature :)

@deiga
Copy link
Collaborator

deiga commented Feb 13, 2026

@sprioriello You'll need to at least rebase this 😬

Copy link
Collaborator

@deiga deiga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to populate any Computed fields inside Create

Suggested change
return resourceGithubEnterpriseSecurityConfigurationRead(ctx, d, meta)
return nil

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Create now sets computed fields (target_type) and returns nil instead of calling Read.

Comment on lines 442 to 444
} else if codeSec == "enabled" || secretProt == "enabled" {
config.CodeSecurity = github.Ptr(codeSec)
config.SecretProtection = github.Ptr(secretProt)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Refactored to set each field individually using d.GetOk() rather than the tandem approach.

Comment on lines +17 to +29
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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a testcase which uses miminal configs to test that defaults work

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return resourceGithubOrganizationSecurityConfigurationRead(ctx, d, meta)
return nil

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Create and Update in org resource now return nil instead of calling Read.

@sprioriello
Copy link
Author

Acceptance Test Results

All 8 acceptance tests pass (4 organization + 4 enterprise):

--- PASS: TestAccGithubOrganizationSecurityConfiguration (56.53s)
    --- PASS: .../creates_organization_security_configuration_without_error (13.28s)
    --- PASS: .../updates_organization_security_configuration_without_error (19.47s)
    --- PASS: .../creates_organization_security_configuration_with_options (12.26s)
    --- PASS: .../creates_organization_security_configuration_with_minimal_config (11.51s)
PASS
ok      github.com/integrations/terraform-provider-github/v6/github     56.936s

--- PASS: TestAccGithubEnterpriseSecurityConfiguration (54.89s)
    --- PASS: .../creates_enterprise_security_configuration_without_error (13.85s)
    --- PASS: .../updates_enterprise_security_configuration_without_error (17.04s)
    --- PASS: .../creates_enterprise_security_configuration_with_options (12.63s)
    --- PASS: .../creates_enterprise_security_configuration_with_minimal_config (11.38s)
PASS
ok      github.com/integrations/terraform-provider-github/v6/github     55.324s

@sprioriello sprioriello force-pushed the feat/organization-security-configuration branch from 47e7766 to 33ae057 Compare February 16, 2026 10:42
@sprioriello
Copy link
Author

sprioriello commented Feb 16, 2026

@sprioriello You'll need to at least rebase this 😬

@deiga rebased and addressed comments as requested. Thank you

@sprioriello sprioriello requested a review from deiga February 17, 2026 11:27
Copy link
Collaborator

@deiga deiga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You claimed to have removed this, but it's still there. What's going on?

Suggested change
ctx = context.WithValue(ctx, ctxId, d.Id())

Copy link
Author

@sprioriello sprioriello Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry my mistake. I made a mistake when rebasing and missed something. Should be fixed now.

return diag.FromErr(err)
}

return nil
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Please populate the Computed fields in Create

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You claimed to have removed this, but it's still there. What's going on?

Suggested change
ctx = context.WithValue(ctx, ctxId, d.Id())

var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) {
if ghErr.Response.StatusCode == http.StatusNotFound {
d.SetId("")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You claimed to have removed this, but it's still there. What's going on?

Suggested change
ctx = context.WithValue(ctx, ctxId, d.Id())

Comment on lines 375 to 377
enterprise := d.Get("enterprise_slug").(string)

enterprise, idStr, err := parseID2(d.Id())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: setting enterprise twice

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed enterprise := d.Get("enterprise_slug").(string)

Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor all Check: in all TestStep to use ConfigStateCheck: instead. https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/state-checks/resource

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Both test files migrated from Check: resource.ComposeTestCheckFunc(...) to ConfigStateChecks:

Comment on lines 49 to 59
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
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use single char variables, it degrades readability of the code a lot

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Renamed all single-char variables in util_security_configuration.go and the other two files.

StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a Description

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a description for both resources.

@sprioriello sprioriello force-pushed the feat/organization-security-configuration branch from a14d69e to 6fec8f5 Compare February 18, 2026 10:49
@sprioriello sprioriello requested a review from deiga February 18, 2026 11:00
@sprioriello sprioriello force-pushed the feat/organization-security-configuration branch from 051a400 to cdb1e63 Compare February 18, 2026 11:11
…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
@sprioriello sprioriello force-pushed the feat/organization-security-configuration branch from cdb1e63 to 6d3c919 Compare February 18, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT]: Code Security Configuration

2 participants