-
Notifications
You must be signed in to change notification settings - Fork 912
[MAINT] Fix github_organization_ruleset and github_repository_ruleset with push target
#2958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
deiga
wants to merge
72
commits into
integrations:go-github-v68
Choose a base branch
from
F-Secure-web:org-ruleset-fix-push
base: go-github-v68
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
72 commits
Select commit
Hold shift + click to select a range
9909ecc
Ensure tests use `GITHUB_TEST_*` values for Owner and Organization
deiga d3bafe6
Update `skipUnlessMode` to check for enterprise ENV variables
deiga a4f929b
Use `testOwnerFunc` to set `testOwner` so that `GITHUB_TEST_OWNER` wo…
deiga fbc8707
Switch from `NewSubsystemLoggingHTTPTransport` to `NewLoggingHTTPTran…
deiga 6966690
Update to use Context aware CRUD functions
deiga a60ac7f
Ensure `update_allows_fetch_and_merge` isn't added for Org Ruleset
deiga 3e2cd38
Update name of resource, to make debugging failing tests easier
deiga d82c614
Need to have one of `repository_name` or `repository_id` defined
deiga b2c3570
Need to have a valid repo reference
deiga 6954994
Actions repository access level needs to be set properly
deiga a41b2f3
Required workflow needs to be in the `.github/workflows` folder
deiga 41b3dec
Update indentation
deiga 512db50
Need to have one of `repository_name` or `repository_id` defined
deiga bdc4729
Add handling of `AllowedMergeMethods`
deiga 405d3b6
Add `allowed_merge_methods` to `rules` for Org & Repo rulesets
deiga 986ae22
Fixed type conversion for `allowed_merge_methods`
deiga 581ff8c
Update test content to actually pass the GH API
deiga e97f75c
Convert `github_repository` to use `*Context` CRUD methods
deiga f096f44
Enable `TestGithubOrganizationRulesets/Creates_and_updates_organizati…
deiga 2d77c1e
`make fmt`
deiga 9d22505
Add workaround for GH API bug that OrgAdmin actor_id is returned as `…
deiga 74bcfe7
`make fmt`
deiga 4808483
Fix `TestGithubOrganizationRulesets/Creates_organization_ruleset_with…
deiga f698cd2
Fix tests regarding `bypass_actors` ordering
deiga 3752c16
Rename test resources for easier debugging
deiga cf35bf9
Update descriptions and validations
deiga 35ff668
Add `CustomizeDiff` logic to validate on `plan`
deiga a944da8
Allow `organization` in tests as well
deiga e471a58
Remove unused leftover
deiga 92fc538
Add first validation test
deiga 4f2ea6a
Update formatting
deiga 0e81c85
Add validation error when `conditions` is missing
deiga 056a70f
Add further validation tests
deiga 740c5e2
Remove unnecessary skip blocks as `individual` and `anonymous` access…
deiga 4fc2f51
Switch `ref_name` to `Optional` as `push` doesn't need a `ref_name`
deiga a70831e
Add Debug logging with `tflog` to validation
deiga 9d85734
Fix validation as `ref_name`, `repository_name` and `repository_id` a…
deiga 5b88bb2
Correctly use `enterprise` runner
deiga 08a73fc
Fix test output expectation
deiga 3f34fb6
Remove unnecessary panic test
deiga 776fc64
Improve validation output messages
deiga 7f65508
Update to use Context aware CRUD functions
deiga 2479b73
Fix condition to require only one of `repository_name` or `repository…
deiga 4666bbe
Add validation to `required_workflow.path`
deiga e9c10b4
`make fmt`
deiga 519ea54
Rename test resources for easier debugging
deiga 21e2e02
Fix linter issues
deiga 77e8cfe
Add validation to ensure `rules.required_status_checks.required_check…
deiga 6782aab
`go mod tidy`
deiga 97e2351
Add test to ensure that `required_checks` is always required
deiga 8717361
Remove `repository` as possible `target` value.
deiga e8b41f4
Improve legibility of `conditions` description
deiga 66e0a1d
Update descriptions
deiga 75e58b2
Add Acc test for push ruleset.
deiga be29a43
Add failing test for `flattenConditions` with no `ref_name` condition
deiga 73f817b
Fix `flattenConditions` to work with `push` rulesets
deiga b46cae4
Add more tests for `flattenConditions`
deiga 6b91f57
Enable debug logging in `flattenConditions`
deiga cec204f
Ensures that `flattenConditions` returns an empty list on empty API r…
deiga 18c860e
Add validation for `push` `rules`
deiga b3ca429
`github_repository`: Remove comment which doesn't hold true anymore
deiga bedfb34
`github_repository`: Ensures that we don't try to PATCH an archived repo
deiga 2e01393
`github_repository_ruleset`: Change `TestGithubRepositoryRulesetArchi…
deiga 760eee3
Rename test functions to include `Acc` prefix to conform to TF best p…
deiga bff5892
`github_team`: Update to use context-aware provider functions
deiga bdef67b
Get `TestAccGithubRepositoryRulesets` to work
deiga 55b9f29
`repository_ruleset`: Add tests for validations
deiga 7a06b31
`repository_ruleset`: Implement validations for `target`, `conditions…
deiga bc22f7a
Updated ruleset docs
deiga 4c2d01c
Ensure empty `bypass_actors` clear them from API first
deiga bfa4c88
Extract validation functions to separate utils file with unit tests
deiga 10baa83
Fix `ExpectError` message
deiga File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| package github | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "slices" | ||
|
|
||
| "github.com/hashicorp/terraform-plugin-log/tflog" | ||
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
| ) | ||
|
|
||
| // branchTagOnlyRules contains rules that are only valid for branch and tag targets. | ||
| // | ||
| // These rules apply to ref-based operations (branches and tags) and are not supported | ||
| // for push rulesets which operate on file content. | ||
| // | ||
| // To verify/maintain this list: | ||
| // 1. Check the GitHub API documentation for organization rulesets: | ||
| // https://docs.github.com/en/rest/orgs/rules?apiVersion=2022-11-28#create-an-organization-repository-ruleset | ||
| // 2. The API docs don't clearly separate push vs branch/tag rules. To verify, | ||
| // attempt to create a push ruleset via API or UI with each rule type. | ||
| // Push rulesets will reject branch/tag rules with "Invalid rule '<name>'" error. | ||
| // 3. Generally, push rules deal with file content (paths, sizes, extensions), | ||
| // while branch/tag rules deal with ref lifecycle and merge requirements. | ||
| var branchTagOnlyRules = []string{ | ||
| "creation", | ||
| "update", | ||
| "deletion", | ||
| "required_linear_history", | ||
| "required_signatures", | ||
| "pull_request", | ||
| "required_status_checks", | ||
| "non_fast_forward", | ||
| "commit_message_pattern", | ||
| "commit_author_email_pattern", | ||
| "committer_email_pattern", | ||
| "branch_name_pattern", | ||
| "tag_name_pattern", | ||
| "required_workflows", | ||
| "required_code_scanning", | ||
| "required_deployments", | ||
| "merge_queue", | ||
| } | ||
|
|
||
| // pushOnlyRules contains rules that are only valid for push targets. | ||
| // | ||
| // These rules apply to push operations and control what content can be pushed | ||
| // to repositories. They are not supported for branch or tag rulesets. | ||
| // | ||
| // To verify/maintain this list: | ||
| // 1. Check the GitHub API documentation for organization rulesets: | ||
| // https://docs.github.com/en/rest/orgs/rules?apiVersion=2022-11-28#create-an-organization-repository-ruleset | ||
| // 2. The API docs don't clearly separate push vs branch/tag rules. To verify, | ||
| // attempt to create a branch ruleset via API or UI with each rule type. | ||
| // Branch rulesets will reject push-only rules with an error. | ||
| // 3. Push rules control file content: paths, sizes, extensions, path lengths. | ||
| var pushOnlyRules = []string{ | ||
| "file_path_restriction", | ||
| "max_file_path_length", | ||
| "file_extension_restriction", | ||
| "max_file_size", | ||
| } | ||
|
|
||
| func validateRulesForTarget(ctx context.Context, d *schema.ResourceDiff) error { | ||
| target := d.Get("target").(string) | ||
| tflog.Debug(ctx, "Validating rules for target", map[string]any{"target": target}) | ||
|
|
||
| switch target { | ||
| case "push": | ||
| return validateRulesForPushTarget(ctx, d) | ||
| case "branch", "tag": | ||
| return validateRulesForBranchTagTarget(ctx, d) | ||
| } | ||
|
|
||
| tflog.Debug(ctx, "Rules validation passed", map[string]any{"target": target}) | ||
| return nil | ||
| } | ||
|
|
||
| func validateRulesForPushTarget(ctx context.Context, d *schema.ResourceDiff) error { | ||
| return validateRules(ctx, d, pushOnlyRules) | ||
| } | ||
|
|
||
| func validateRulesForBranchTagTarget(ctx context.Context, d *schema.ResourceDiff) error { | ||
| return validateRules(ctx, d, branchTagOnlyRules) | ||
| } | ||
|
|
||
| func validateRules(ctx context.Context, d *schema.ResourceDiff, allowedRules []string) error { | ||
| target := d.Get("target").(string) | ||
| rules := d.Get("rules").([]any)[0].(map[string]any) | ||
| for ruleName := range rules { | ||
| ruleValue, exists := d.GetOk(fmt.Sprintf("rules.0.%s", ruleName)) | ||
| if !exists { | ||
| continue | ||
| } | ||
| switch ruleValue := ruleValue.(type) { | ||
| case []any: | ||
| if len(ruleValue) == 0 { | ||
| continue | ||
| } | ||
| case map[string]any: | ||
| if len(ruleValue) == 0 { | ||
| continue | ||
| } | ||
| case any: | ||
| if ruleValue == nil { | ||
| continue | ||
| } | ||
| } | ||
| if slices.Contains(allowedRules, ruleName) { | ||
| continue | ||
| } else { | ||
| tflog.Debug(ctx, fmt.Sprintf("Invalid rule for %s target", target), map[string]any{"rule": ruleName, "value": ruleValue}) | ||
| return fmt.Errorf("rule %q is not valid for %[2]s target; %[2]s targets only support: %v", ruleName, target, allowedRules) | ||
| } | ||
| } | ||
| tflog.Debug(ctx, fmt.Sprintf("Rules validation passed for %s target", target)) | ||
| return nil | ||
| } | ||
|
|
||
| func validateRepositoryRulesetConditionsFieldForBranchAndTagTargets(ctx context.Context, target string, conditions map[string]any) error { | ||
| tflog.Debug(ctx, fmt.Sprintf("Validating conditions field for %s target", target), map[string]any{"target": target, "conditions": conditions}) | ||
|
|
||
| if conditions["ref_name"] == nil || len(conditions["ref_name"].([]any)) == 0 { | ||
| tflog.Debug(ctx, fmt.Sprintf("Missing ref_name for %s target", target), map[string]any{"target": target}) | ||
| return fmt.Errorf("ref_name must be set for %s target", target) | ||
| } | ||
|
|
||
| tflog.Debug(ctx, fmt.Sprintf("Conditions validation passed for %s target", target)) | ||
| return nil | ||
| } | ||
|
|
||
| func validateConditionsFieldForBranchAndTagTargets(ctx context.Context, target string, conditions map[string]any) error { | ||
| tflog.Debug(ctx, fmt.Sprintf("Validating conditions field for %s target", target), map[string]any{"target": target, "conditions": conditions}) | ||
|
|
||
| if conditions["ref_name"] == nil || len(conditions["ref_name"].([]any)) == 0 { | ||
| tflog.Debug(ctx, fmt.Sprintf("Missing ref_name for %s target", target), map[string]any{"target": target}) | ||
| return fmt.Errorf("ref_name must be set for %s target", target) | ||
| } | ||
|
|
||
| if (conditions["repository_name"] == nil || len(conditions["repository_name"].([]any)) == 0) && (conditions["repository_id"] == nil || len(conditions["repository_id"].([]any)) == 0) { | ||
| tflog.Debug(ctx, fmt.Sprintf("Missing repository_name or repository_id for %s target", target), map[string]any{"target": target}) | ||
| return fmt.Errorf("either repository_name or repository_id must be set for %s target", target) | ||
| } | ||
| tflog.Debug(ctx, fmt.Sprintf("Conditions validation passed for %s target", target)) | ||
| return nil | ||
| } | ||
|
|
||
| func validateConditionsFieldForPushTarget(ctx context.Context, conditions map[string]any) error { | ||
| tflog.Debug(ctx, "Validating conditions field for push target", map[string]any{"target": "push", "conditions": conditions}) | ||
|
|
||
| if conditions["ref_name"] != nil && len(conditions["ref_name"].([]any)) > 0 { | ||
| tflog.Debug(ctx, "Invalid ref_name for push target", map[string]any{"ref_name": conditions["ref_name"]}) | ||
| return fmt.Errorf("ref_name must not be set for push target") | ||
| } | ||
| tflog.Debug(ctx, "Conditions validation passed for push target") | ||
| return nil | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why we need this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't inititialize the
GitHubsubsystem anywhere and from my understanding subsystems are usually per-resource things.With an unitialized Subsystem the logs get spammed with warnings about it.
But this implementation is "actually" in this PR #2976 and any modifications to it should happen there