diff --git a/github/resource_github_organization_ruleset.go b/github/resource_github_organization_ruleset.go index 014b28ef6..e8eaae8cb 100644 --- a/github/resource_github_organization_ruleset.go +++ b/github/resource_github_organization_ruleset.go @@ -428,6 +428,11 @@ func resourceGithubOrganizationRuleset() *schema.Resource { Description: "Choose which Actions workflows must pass before branches can be merged into a branch that matches this rule.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "do_not_enforce_on_create": { + Type: schema.TypeBool, + Optional: true, + Description: "Allow repositories and branches to be created if a check would otherwise prohibit it.", + }, "required_workflow": { Type: schema.TypeSet, MinItems: 1, diff --git a/github/resource_github_organization_ruleset_test.go b/github/resource_github_organization_ruleset_test.go index 9aae9f35b..d6d9b6e64 100644 --- a/github/resource_github_organization_ruleset_test.go +++ b/github/resource_github_organization_ruleset_test.go @@ -63,6 +63,7 @@ func TestGithubOrganizationRulesets(t *testing.T) { } required_workflows { + do_not_enforce_on_create = true required_workflow { path = "path/to/workflow.yaml" repository_id = 1234 @@ -91,13 +92,45 @@ func TestGithubOrganizationRulesets(t *testing.T) { check := resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "github_organization_ruleset.test", "name", + "github_organization_ruleset.test", + "name", "test", ), resource.TestCheckResourceAttr( - "github_organization_ruleset.test", "enforcement", + "github_organization_ruleset.test", + "enforcement", "active", ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", + "rules.0.required_workflows.0.do_not_enforce_on_create", + "true", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", + "rules.0.required_workflows.0.required_workflow.0.path", + "path/to/workflow.yaml", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", + "rules.0.required_workflows.0.required_workflow.0.repository_id", + "1234", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.alerts_threshold", + "errors", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.security_alerts_threshold", + "high_or_higher", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.tool", + "CodeQL", + ), ) testCase := func(t *testing.T, mode string) { diff --git a/github/resource_github_repository_ruleset_test.go b/github/resource_github_repository_ruleset_test.go index 35bc80fbd..270bc644c 100644 --- a/github/resource_github_repository_ruleset_test.go +++ b/github/resource_github_repository_ruleset_test.go @@ -21,6 +21,7 @@ func TestGithubRepositoryRulesets(t *testing.T) { resource "github_repository" "test" { name = "tf-acc-test-%s" auto_init = false + vulnerability_alerts = true } resource "github_repository_environment" "example" { @@ -73,6 +74,14 @@ func TestGithubRepositoryRulesets(t *testing.T) { do_not_enforce_on_create = true } + required_code_scanning { + required_code_scanning_tool { + alerts_threshold = "errors" + security_alerts_threshold = "high_or_higher" + tool = "CodeQL" + } + } + non_fast_forward = true } } @@ -80,13 +89,30 @@ func TestGithubRepositoryRulesets(t *testing.T) { check := resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "github_repository_ruleset.test", "name", + "github_repository_ruleset.test", + "name", "test", ), resource.TestCheckResourceAttr( - "github_repository_ruleset.test", "enforcement", + "github_repository_ruleset.test", + "enforcement", "active", ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.alerts_threshold", + "errors", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.security_alerts_threshold", + "high_or_higher", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", + "rules.0.required_code_scanning.0.required_code_scanning_tool.0.tool", + "CodeQL", + ), ) testCase := func(t *testing.T, mode string) { @@ -129,6 +155,7 @@ func TestGithubRepositoryRulesets(t *testing.T) { resource "github_repository" "test" { name = "tf-acc-test-%s" auto_init = false + vulnerability_alerts = true } resource "github_repository_environment" "example" { @@ -200,6 +227,7 @@ func TestGithubRepositoryRulesets(t *testing.T) { resource "github_repository" "test" { name = "%[1]s" description = "Terraform acceptance tests %[2]s" + vulnerability_alerts = true } resource "github_repository_ruleset" "test" { @@ -271,6 +299,7 @@ func TestGithubRepositoryRulesets(t *testing.T) { name = "tf-acc-test-import-%[1]s" description = "Terraform acceptance tests %[1]s" auto_init = false + vulnerability_alerts = true } resource "github_repository_environment" "example" { diff --git a/github/respository_rules_utils.go b/github/respository_rules_utils.go index 9d9516175..728369248 100644 --- a/github/respository_rules_utils.go +++ b/github/respository_rules_utils.go @@ -359,7 +359,8 @@ func expandRules(input []interface{}, org bool) []*github.RepositoryRule { } params := &github.RequiredWorkflowsRuleParameters{ - RequiredWorkflows: requiredWorkflows, + DoNotEnforceOnCreate: requiredWorkflowsMap["do_not_enforce_on_create"].(bool), + RequiredWorkflows: requiredWorkflows, } rulesSlice = append(rulesSlice, github.NewRequiredWorkflowsRule(params)) } @@ -507,6 +508,51 @@ func flattenRules(rules []*github.RepositoryRule, org bool) []interface{} { rule["strict_required_status_checks_policy"] = params.StrictRequiredStatusChecksPolicy rule["do_not_enforce_on_create"] = params.DoNotEnforceOnCreate rulesMap[v.Type] = []map[string]interface{}{rule} + + case "workflows": + var params github.RequiredWorkflowsRuleParameters + + err := json.Unmarshal(*v.Parameters, ¶ms) + if err != nil { + log.Printf("[INFO] Unexpected error unmarshalling rule %s with parameters: %v", + v.Type, v.Parameters) + } + + requiredWorkflowsSlice := make([]map[string]interface{}, 0) + for _, check := range params.RequiredWorkflows { + requiredWorkflowsSlice = append(requiredWorkflowsSlice, map[string]interface{}{ + "repository_id": check.RepositoryID, + "path": check.Path, + "ref": check.Ref, + }) + } + + rule := make(map[string]interface{}) + rule["do_not_enforce_on_create"] = params.DoNotEnforceOnCreate + rule["required_workflow"] = requiredWorkflowsSlice + rulesMap["required_workflows"] = []map[string]interface{}{rule} + + case "code_scanning": + var params github.RequiredCodeScanningRuleParameters + + err := json.Unmarshal(*v.Parameters, ¶ms) + if err != nil { + log.Printf("[INFO] Unexpected error unmarshalling rule %s with parameters: %v", + v.Type, v.Parameters) + } + + requiredCodeScanningSlice := make([]map[string]interface{}, 0) + for _, check := range params.RequiredCodeScanningTools { + requiredCodeScanningSlice = append(requiredCodeScanningSlice, map[string]interface{}{ + "alerts_threshold": check.AlertsThreshold, + "security_alerts_threshold": check.SecurityAlertsThreshold, + "tool": check.Tool, + }) + } + + rule := make(map[string]interface{}) + rule["required_code_scanning_tool"] = requiredCodeScanningSlice + rulesMap["required_code_scanning"] = []map[string]interface{}{rule} } }