Skip to content

Commit 94f71cf

Browse files
authored
feat : Support repository property for GitHub organization ruleset (#2356)
* Define schema for repository_property Refactor expandConditions to reduce complexity Refactor logic to reduce the cognitive complexity and add logic to handle the repository_property field Flatten conditions for repository_property and fix schemas Add test case when ruleset use repository_property Refactor repository property conditions to make them optional Flatten update Target parameters to allow the detection of changes when remote resource is updated Update documentation * Apply format in the code base * Fix repository_property validation and docs - Add ValidateFunc to include.source field for consistency with exclude - Update docs to mention repository_property as third targeting option - Fix missing space in documentation * Support repository_property in push rulesets * Remove unused customdiff imports * Replace custom validation with built-in ExactlyOneOf for repo targeting Add ExactlyOneOf/AtLeastOneOf to repository_property, repository_name,repository_id fields. Remove manual validation counting in util_ruleset_validation.Add 3 validation tests for single/multiple/missing repo targeting options. Addresses PR #2356 review feedback - simplifies validation using schema constraints. * Rever unintencial change * Add tests, docs, and fix default handling for repository_property - Add doc example for repository_property usage - Add tests for exclude block, multiple properties, and updates - Fix source field default handling in flatten function to prevent diffs * Apply suggestions from PR comment * Add unit tests * Remove redundant condition * Updated description based in the GitHub API docs * Apply linter and fmt * Remove unnecessary checks * Remove tests These tests check validation that was handover to the Terraform built-in validation * Improve syntax for include and exclude property Improve e2e tests for the ruleset and improve documentation * Use t context * Rewrite tests using the resource_github_organization_custom_properties Setup the tests case using the config instead of using the API * Refactor repository property names in organization ruleset tests for consistency * Refactor tests to use state checks for repository property validation in organization ruleset * Update repository property references to use default_branch in organization ruleset tests * Fix: Replace ExactlyOneOf with ConflictsWith/AtLeastOneOf for repository conditions ExactlyOneOf has known issues with nested optional list blocks in Terraform SDK. Use ConflictsWith + AtLeastOneOf pattern for reliable "exactly one" validation across repository_name, repository_id, and repository_property conditions. Updated test expectations to match new error message format from ConflictsWith. Addresses feedback from PR #2356 comment r2968116244, references fix from #3235 * Apply lint
1 parent 636eff4 commit 94f71cf

7 files changed

+1140
-54
lines changed

github/resource_github_organization_ruleset.go

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func resourceGithubOrganizationRuleset() *schema.Resource {
9494
Type: schema.TypeList,
9595
Optional: true,
9696
MaxItems: 1,
97-
Description: "Parameters for an organization ruleset condition. `ref_name` is required for `branch` and `tag` targets, but must not be set for `push` targets. One of `repository_name` or `repository_id` is always required.",
97+
Description: "Parameters for an organization ruleset condition.The branch and tag rulesets conditions object should contain both repository_name and ref_name properties, or both repository_id and ref_name properties, or both repository_property and ref_name properties. The push rulesets conditions object does not require the ref_name property.",
9898
Elem: &schema.Resource{
9999
Schema: map[string]*schema.Schema{
100100
"ref_name": {
@@ -123,13 +123,85 @@ func resourceGithubOrganizationRuleset() *schema.Resource {
123123
},
124124
},
125125
},
126+
"repository_property": {
127+
Type: schema.TypeList,
128+
Optional: true,
129+
MaxItems: 1,
130+
ConflictsWith: []string{"conditions.0.repository_id", "conditions.0.repository_name"},
131+
AtLeastOneOf: []string{"conditions.0.repository_name", "conditions.0.repository_id", "conditions.0.repository_property"},
132+
Description: "Conditions to target repositories by custom or system properties.",
133+
Elem: &schema.Resource{
134+
Schema: map[string]*schema.Schema{
135+
"include": {
136+
Type: schema.TypeList,
137+
Optional: true,
138+
ConfigMode: schema.SchemaConfigModeAttr,
139+
Description: "The repository properties and values to include. All of these properties must match for the condition to pass.",
140+
Elem: &schema.Resource{
141+
Schema: map[string]*schema.Schema{
142+
"name": {
143+
Type: schema.TypeString,
144+
Required: true,
145+
Description: "The name of the repository property to target.",
146+
},
147+
"property_values": {
148+
Type: schema.TypeList,
149+
Required: true,
150+
Description: "The values to match for the repository property.",
151+
Elem: &schema.Schema{
152+
Type: schema.TypeString,
153+
},
154+
},
155+
"source": {
156+
Type: schema.TypeString,
157+
Optional: true,
158+
Description: "The source of the repository property. Defaults to 'custom' if not specified. Can be one of: custom, system",
159+
Default: "custom",
160+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"custom", "system"}, false)),
161+
},
162+
},
163+
},
164+
},
165+
"exclude": {
166+
Type: schema.TypeList,
167+
Optional: true,
168+
ConfigMode: schema.SchemaConfigModeAttr,
169+
Description: "The repository properties and values to exclude. The ruleset will not apply if any of these properties match.",
170+
Elem: &schema.Resource{
171+
Schema: map[string]*schema.Schema{
172+
"name": {
173+
Type: schema.TypeString,
174+
Required: true,
175+
Description: "The name of the repository property to target.",
176+
},
177+
"property_values": {
178+
Type: schema.TypeList,
179+
Required: true,
180+
Description: "The values to match for the repository property.",
181+
Elem: &schema.Schema{
182+
Type: schema.TypeString,
183+
},
184+
},
185+
"source": {
186+
Type: schema.TypeString,
187+
Optional: true,
188+
Description: "The source of the repository property. Defaults to 'custom' if not specified. Can be one of: custom, system",
189+
Default: "custom",
190+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"custom", "system"}, false)),
191+
},
192+
},
193+
},
194+
},
195+
},
196+
},
197+
},
126198
"repository_name": {
127-
Type: schema.TypeList,
128-
Optional: true,
129-
MaxItems: 1,
130-
Description: "Targets repositories that match the specified name patterns.",
131-
ExactlyOneOf: []string{"conditions.0.repository_id"},
132-
AtLeastOneOf: []string{"conditions.0.repository_id"},
199+
Type: schema.TypeList,
200+
Optional: true,
201+
MaxItems: 1,
202+
ConflictsWith: []string{"conditions.0.repository_id", "conditions.0.repository_property"},
203+
AtLeastOneOf: []string{"conditions.0.repository_name", "conditions.0.repository_id", "conditions.0.repository_property"},
204+
Description: "Targets repositories that match the specified name patterns.",
133205
Elem: &schema.Resource{
134206
Schema: map[string]*schema.Schema{
135207
"include": {
@@ -158,9 +230,11 @@ func resourceGithubOrganizationRuleset() *schema.Resource {
158230
},
159231
},
160232
"repository_id": {
161-
Type: schema.TypeList,
162-
Optional: true,
163-
Description: "The repository IDs that the ruleset applies to. One of these IDs must match for the condition to pass.",
233+
Type: schema.TypeList,
234+
Optional: true,
235+
ConflictsWith: []string{"conditions.0.repository_name", "conditions.0.repository_property"},
236+
AtLeastOneOf: []string{"conditions.0.repository_name", "conditions.0.repository_id", "conditions.0.repository_property"},
237+
Description: "The repository IDs that the ruleset applies to. One of these IDs must match for the ruleset to apply.",
164238
Elem: &schema.Schema{
165239
Type: schema.TypeInt,
166240
},

0 commit comments

Comments
 (0)