Skip to content

Commit b33f177

Browse files
committed
Improve syntax for include and exclude property
Improve e2e tests for the ruleset and improve documentation
1 parent 968b1af commit b33f177

3 files changed

Lines changed: 158 additions & 73 deletions

File tree

github/resource_github_organization_ruleset.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ func resourceGithubOrganizationRuleset() *schema.Resource {
134134
"include": {
135135
Type: schema.TypeList,
136136
Optional: true,
137+
ConfigMode: schema.SchemaConfigModeAttr,
137138
Description: "The repository properties and values to include. All of these properties must match for the condition to pass.",
138139
Elem: &schema.Resource{
139140
Schema: map[string]*schema.Schema{
@@ -163,6 +164,7 @@ func resourceGithubOrganizationRuleset() *schema.Resource {
163164
"exclude": {
164165
Type: schema.TypeList,
165166
Optional: true,
167+
ConfigMode: schema.SchemaConfigModeAttr,
166168
Description: "The repository properties and values to exclude. The ruleset will not apply if any of these properties match.",
167169
Elem: &schema.Resource{
168170
Schema: map[string]*schema.Schema{

github/resource_github_organization_ruleset_test.go

Lines changed: 137 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package github
22

33
import (
4+
"context"
45
"fmt"
56
"regexp"
67
"testing"
78

9+
"github.com/google/go-github/v82/github"
810
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
911
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
1012
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -250,15 +252,11 @@ resource "github_organization_ruleset" "test" {
250252
251253
conditions {
252254
repository_property {
253-
include = [{
254-
name = "tier"
255-
source = "custom"
256-
property_values = ["premium"]
257-
}]
255+
include = []
258256
exclude = [{
259-
name = "archived"
260-
source = "system"
261-
property_values = ["true"]
257+
name = "team"
258+
source = "custom"
259+
property_values = ["red"]
262260
}]
263261
}
264262
@@ -282,11 +280,11 @@ resource "github_organization_ruleset" "test" {
282280
Config: config,
283281
Check: resource.ComposeTestCheckFunc(
284282
resource.TestCheckResourceAttr("github_organization_ruleset.test", "name", rulesetName),
285-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.#", "1"),
283+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.#", "0"),
286284
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.#", "1"),
287-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.name", "archived"),
288-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.source", "system"),
289-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.property_values.0", "true"),
285+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.name", "team"),
286+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.source", "custom"),
287+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.property_values.0", "red"),
290288
),
291289
},
292290
},
@@ -297,6 +295,45 @@ resource "github_organization_ruleset" "test" {
297295
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
298296
rulesetName := fmt.Sprintf("%s-repo-prop-multiple-%s", testResourcePrefix, randomID)
299297

298+
// Setup: Create custom properties for testing
299+
meta, err := getTestMeta()
300+
if err != nil {
301+
t.Fatalf("Error getting test meta: %v", err)
302+
}
303+
304+
ctx := context.Background()
305+
org := testAccConf.owner
306+
307+
// Create test properties
308+
properties := []struct {
309+
name string
310+
values []string
311+
}{
312+
{name: "e2e_test_environment", values: []string{"production", "staging"}},
313+
{name: "e2e_test_tier", values: []string{"premium", "enterprise"}},
314+
}
315+
316+
for _, prop := range properties {
317+
_, _, err := meta.v3client.Organizations.CreateOrUpdateCustomProperty(ctx, org, prop.name, &github.CustomProperty{
318+
ValueType: github.PropertyValueTypeSingleSelect,
319+
Required: github.Ptr(false),
320+
AllowedValues: prop.values,
321+
})
322+
if err != nil {
323+
t.Logf("Warning: Could not create custom property %s (may already exist): %v", prop.name, err)
324+
}
325+
}
326+
327+
// Cleanup: Remove custom properties after test
328+
defer func() {
329+
for _, prop := range properties {
330+
_, err := meta.v3client.Organizations.RemoveCustomProperty(ctx, org, prop.name)
331+
if err != nil {
332+
t.Logf("Warning: Could not remove custom property %s: %v", prop.name, err)
333+
}
334+
}
335+
}()
336+
300337
config := fmt.Sprintf(`
301338
resource "github_organization_ruleset" "test" {
302339
name = "%s"
@@ -307,14 +344,14 @@ resource "github_organization_ruleset" "test" {
307344
repository_property {
308345
include = [
309346
{
310-
name = "environment"
347+
name = "e2e_test_environment"
311348
source = "custom"
312349
property_values = ["production"]
313350
},
314351
{
315-
name = "team"
352+
name = "e2e_test_tier"
316353
source = "custom"
317-
property_values = ["backend", "platform"]
354+
property_values = ["premium", "enterprise"]
318355
}
319356
]
320357
exclude = []
@@ -341,10 +378,15 @@ resource "github_organization_ruleset" "test" {
341378
Check: resource.ComposeTestCheckFunc(
342379
resource.TestCheckResourceAttr("github_organization_ruleset.test", "name", rulesetName),
343380
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.#", "2"),
344-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.name", "environment"),
381+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.name", "e2e_test_environment"),
382+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.source", "custom"),
383+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.#", "1"),
345384
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "production"),
346-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.name", "team"),
385+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.name", "e2e_test_tier"),
386+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.source", "custom"),
347387
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.property_values.#", "2"),
388+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.property_values.0", "premium"),
389+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.1.property_values.1", "enterprise"),
348390
),
349391
},
350392
},
@@ -364,9 +406,9 @@ resource "github_organization_ruleset" "test" {
364406
conditions {
365407
repository_property {
366408
include = [{
367-
name = "tier"
409+
name = "team"
368410
source = "custom"
369-
property_values = ["basic"]
411+
property_values = ["blue"]
370412
}]
371413
exclude = []
372414
}
@@ -392,15 +434,11 @@ resource "github_organization_ruleset" "test" {
392434
conditions {
393435
repository_property {
394436
include = [{
395-
name = "tier"
437+
name = "team"
396438
source = "custom"
397-
property_values = ["premium", "enterprise"]
398-
}]
399-
exclude = [{
400-
name = "archived"
401-
source = "system"
402-
property_values = ["true"]
439+
property_values = ["backend", "platform"]
403440
}]
441+
exclude = []
404442
}
405443
406444
ref_name {
@@ -425,7 +463,7 @@ resource "github_organization_ruleset" "test" {
425463
Check: resource.ComposeTestCheckFunc(
426464
resource.TestCheckResourceAttr("github_organization_ruleset.test", "name", rulesetName),
427465
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.#", "1"),
428-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "basic"),
466+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "blue"),
429467
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.#", "0"),
430468
),
431469
},
@@ -434,10 +472,9 @@ resource "github_organization_ruleset" "test" {
434472
Check: resource.ComposeTestCheckFunc(
435473
resource.TestCheckResourceAttr("github_organization_ruleset.test", "name", rulesetName),
436474
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.#", "2"),
437-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "premium"),
438-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.1", "enterprise"),
439-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.#", "1"),
440-
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.0.name", "archived"),
475+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "backend"),
476+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.1", "platform"),
477+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.exclude.#", "0"),
441478
),
442479
},
443480
},
@@ -977,7 +1014,7 @@ resource "github_organization_ruleset" "test" {
9771014
Steps: []resource.TestStep{
9781015
{
9791016
Config: config,
980-
ExpectError: regexp.MustCompile("only one of `conditions.0.repository_id,conditions.0.repository_name,conditions.0.repository_property` can be specified"),
1017+
ExpectError: regexp.MustCompile(`(?s)only one of.*conditions\.0\.repository_id.*conditions\.0\.repository_name.*conditions\.0\.repository_property.*can be specified`),
9811018
},
9821019
},
9831020
})
@@ -1011,48 +1048,90 @@ resource "github_organization_ruleset" "test" {
10111048
Steps: []resource.TestStep{
10121049
{
10131050
Config: config,
1014-
ExpectError: regexp.MustCompile("one of `conditions.0.repository_id,conditions.0.repository_name,conditions.0.repository_property` must be specified"),
1051+
ExpectError: regexp.MustCompile(`(?s)one of.*conditions\.0\.repository_id.*conditions\.0\.repository_name.*conditions\.0\.repository_property.*must be specified`),
10151052
},
10161053
},
10171054
})
10181055
})
10191056

10201057
t.Run("validates_repository_property_works_as_single_targeting_option", func(t *testing.T) {
10211058
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
1022-
resourceName := "test-repo-property-targeting"
1023-
config := fmt.Sprintf(`
1024-
resource "github_organization_ruleset" "%s" {
1025-
name = "test-property-targeting-%s"
1026-
target = "branch"
1027-
enforcement = "active"
1059+
rulesetName := fmt.Sprintf("%s-repo-prop-only-%s", testResourcePrefix, randomID)
10281060

1029-
conditions {
1030-
ref_name {
1031-
include = ["~ALL"]
1032-
exclude = []
1033-
}
1034-
repository_property {
1035-
include {
1036-
name = "environment"
1037-
property_values = ["production"]
1038-
source = "custom"
1039-
}
1040-
}
1041-
}
1061+
// Setup: Create custom property for testing
1062+
meta, err := getTestMeta()
1063+
if err != nil {
1064+
t.Fatalf("Error getting test meta: %v", err)
1065+
}
10421066

1043-
rules {
1044-
creation = true
1045-
}
1067+
ctx := context.Background()
1068+
org := testAccConf.owner
1069+
propName := "e2e_test_environment"
1070+
propValues := []string{"production", "staging"}
1071+
1072+
_, _, err = meta.v3client.Organizations.CreateOrUpdateCustomProperty(ctx, org, propName, &github.CustomProperty{
1073+
ValueType: github.PropertyValueTypeSingleSelect,
1074+
Required: github.Ptr(false),
1075+
AllowedValues: propValues,
1076+
})
1077+
if err != nil {
1078+
t.Logf("Warning: Could not create custom property %s (may already exist): %v", propName, err)
1079+
}
1080+
1081+
// Cleanup: Remove custom property after test
1082+
defer func() {
1083+
_, err := meta.v3client.Organizations.RemoveCustomProperty(ctx, org, propName)
1084+
if err != nil {
1085+
t.Logf("Warning: Could not remove custom property %s: %v", propName, err)
10461086
}
1047-
`, resourceName, randomID)
1087+
}()
1088+
1089+
config := fmt.Sprintf(`
1090+
resource "github_organization_ruleset" "test" {
1091+
name = "%s"
1092+
target = "branch"
1093+
enforcement = "active"
1094+
1095+
conditions {
1096+
repository_property {
1097+
include = [{
1098+
name = "e2e_test_environment"
1099+
source = "custom"
1100+
property_values = ["production", "staging"]
1101+
}]
1102+
exclude = []
1103+
}
1104+
1105+
ref_name {
1106+
include = ["~DEFAULT_BRANCH"]
1107+
exclude = []
1108+
}
1109+
}
1110+
1111+
rules {
1112+
creation = true
1113+
update = true
1114+
}
1115+
}
1116+
`, rulesetName)
10481117

10491118
resource.Test(t, resource.TestCase{
10501119
PreCheck: func() { skipUnlessHasPaidOrgs(t) },
10511120
ProviderFactories: providerFactories,
10521121
Steps: []resource.TestStep{
10531122
{
1054-
Config: config,
1055-
ExpectError: nil, // This should succeed
1123+
Config: config,
1124+
Check: resource.ComposeTestCheckFunc(
1125+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "name", rulesetName),
1126+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "target", "branch"),
1127+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "enforcement", "active"),
1128+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.#", "1"),
1129+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.name", "e2e_test_environment"),
1130+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.source", "custom"),
1131+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.#", "2"),
1132+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.0", "production"),
1133+
resource.TestCheckResourceAttr("github_organization_ruleset.test", "conditions.0.repository_property.0.include.0.property_values.1", "staging"),
1134+
),
10561135
},
10571136
},
10581137
})

website/docs/r/organization_ruleset.html.markdown

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,25 @@ resource "github_organization_ruleset" "example_property" {
113113
}
114114
115115
repository_property {
116-
include {
117-
name = "environment"
118-
property_values = ["production", "staging"]
119-
source = "custom"
120-
}
121-
include {
122-
name = "team"
123-
property_values = ["backend"]
124-
source = "custom"
125-
}
126-
exclude {
127-
name = "archived"
128-
property_values = ["true"]
129-
source = "system"
130-
}
116+
include = [
117+
{
118+
name = "environment"
119+
property_values = ["production", "staging"]
120+
source = "custom"
121+
},
122+
{
123+
name = "team"
124+
property_values = ["backend"]
125+
source = "custom"
126+
}
127+
]
128+
exclude = [
129+
{
130+
name = "archived"
131+
property_values = ["true"]
132+
source = "system"
133+
}
134+
]
131135
}
132136
}
133137

0 commit comments

Comments
 (0)