feat(organization_ruleset): support the repository target - #3598
Conversation
|
Please show a screenshot of an Org level ruleset with |
|
@deiga unless I do not understand my own GitHub org, my apologies if I did a mistake here, I honestly thought this is the normal flow Screen.Recording.2026-08-07.at.2.55.18.PM.mov |
|
@yordis you have understood totally fine. I wasn't aware that it's under a different UI menu! 🙏 |
deiga
left a comment
There was a problem hiding this comment.
Nice changes! Would you be open for improving the docs bit?
There was a problem hiding this comment.
question: would you have the courage to refactor this template to use the auto-generated schema instead of manually doing the schema changes?
There was a problem hiding this comment.
suggestion: Please split examples into multiple files and move them to examples/resources/github_organization_ruleset/resource_<name|number>.tf
|
@deiga check again and let me know 🙏🏻 |
There was a problem hiding this comment.
Pull request overview
These provider review instructions are being used.
Adds repository-target organization rulesets, including target-specific validation, rules, tests, examples, and generated documentation.
Changes:
- Adds five repository-target rules and serialization support.
- Adds target-aware validation and tests.
- Updates examples, imports, templates, and generated docs.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
github/resource_github_organization_ruleset.go |
Adds repository target schema. |
github/resource_github_organization_ruleset_test.go |
Adds acceptance and validation tests. |
github/util_rules.go |
Expands and flattens repository rules. |
github/util_rules_test.go |
Tests rule round-tripping. |
github/util_ruleset_validation.go |
Adds target-specific validation. |
github/util_ruleset_validation_test.go |
Tests validation and rule separation. |
examples/resources/github_organization_ruleset/resource_1.tf |
Retains the primary example. |
examples/resources/github_organization_ruleset/resource_2.tf |
Extracts the push example. |
examples/resources/github_organization_ruleset/resource_3.tf |
Adds a repository-target example. |
examples/resources/github_organization_ruleset/import.sh |
Documents CLI import. |
examples/resources/github_organization_ruleset/import-by-string-id.tf |
Documents import blocks. |
templates/resources/organization_ruleset.md.tmpl |
Modernizes generated documentation. |
docs/resources/organization_ruleset.md |
Publishes updated schema and examples. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| rulesetRules.RepositoryVisibility = &github.RepositoryVisibilityRuleParameters{ | ||
| Internal: repositoryVisibilityMap["internal"].(bool), | ||
| Private: repositoryVisibilityMap["private"].(bool), | ||
| } |
|
@deiga should I address Copilot until it is happy with things? |
GitHub organization rulesets accept a `repository` target that governs repository creation, deletion, naming, transfer and visibility, but the provider rejected it, leaving those org policies unmanageable in Terraform and silently destructive on import. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…urce schema Hand-maintained argument and attribute tables drift from the schema they describe, so the docs already disagreed with the resource on the push and repository targets. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…yout The page hardcoded prose the provider can supply itself and described importing in text the tooling can no longer verify against the resource. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…ead from the ID alone Import is the path where the old provider silently rewrote the ruleset as a branch ruleset, so the new target needs coverage that does not lean on config-seeded state. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
c054031 to
3f4cf32
Compare
|
Heads up on a related gap I hit while working on this, and filed upstream as google/go-github#4455. The I verified this against a live That means this PR ships Filing this so the limitation is on the record rather than discovered later. |
Resolves #2777
Before the change?
repositorytarget that governs repository creation, deletion, naming, transfer and visibility. The provider rejected it, so those org policies could not be managed in Terraform at all. Importing one was worse than unsupported:targetisRequiredbut notForceNew, so an import succeeded and the next apply silently rewrote the ruleset as a branch ruleset.github_organization_rulesetandgithub_repository_rulesetwithpushtarget #2958) shipped thepushtarget, notrepository. [FEAT]: Add Support for GitHub Enterprise Rulesets #3110 implements these rules only for a newgithub_enterprise_rulesetand treats the repository target as enterprise-only; the REST docs list it as a plain ruleset target ("Can be one of:branch,tag,push,repository"), and all of the testing below was done against a regular org on the Team plan.After the change?
github_organization_rulesetacceptstarget = "repository", so repository creation, deletion, naming, transfer and visibility policies are declarable and importable like every other ruleset.repository_create,repository_delete,repository_transfer,repository_name(pattern,negate) andrepository_visibility.targetis now checked against the four values the API documents instead of accepting any string.Testing
Verified end to end against a live organization using a local build of this branch via
dev_overrides. Create, read, update and delete all exercised against the API.Create. A ruleset using all five rules, applied clean, and the server stored exactly the intended payload:
This confirms the parameter shapes:
repository_create/repository_delete/repository_transfermarshal as bare rules with no parameters, andrepository_nameas{negate, pattern}. A follow-up plan was empty, so all five round-trip through read.Update. Removing a bare rule, flipping
negate, changingpatternand flippinginternalapplied as a single in-place change, the server reflected each one, and the follow-up plan was empty.Import. An existing repository-target ruleset created through the UI imported cleanly, both directly and through an
importblock (1 to import, 0 to add, 0 to change, 0 to destroy), with an empty plan afterwards.Delete. Destroy removed it; the API returns 404.
Validation, rejected at plan time:
repositorytarget withref_nameref_name must not be set for repository targetrepositorytarget withcreationrule "creation" is not valid for repository target; repository targets only support: [...]branchtarget withrepository_deleterule "repository_delete" is not valid for branch target; ...target = "bogus"expected target to be one of ["branch" "tag" "push" "repository"], got bogusUnit tests,
gofmt,go vetandgolangci-lintare clean. New unit coverage: round-trip expand/flatten for all five rules, a check that the rules are omitted forgithub_repository_ruleset(whose schema lacks them), a pairwise-disjointness test across the three target rule lists, and conditions validation for the new target. Acceptance tests are included but I cannot run the mutating suite in CI myself.Known gap:
publicvisibility, needs a go-github changego-github'sRepositoryVisibilityRuleParametershas onlyInternalandPrivate, in v89 and on master, while the API returns and acceptspublic. I confirmed the consequence on a throwaway ruleset rather than assuming it:public: trueout of band via the REST API.tofu planreported no changes. The provider cannot see the drift.repository_namepattern only).publiccame backfalse. The value was silently discarded.So a repository ruleset that permits public repos would have that quietly revoked by any unrelated apply. That is a data-loss path, and it is not fixable in this provider alone: the field has to exist in go-github first. I am happy to open that change and rebase this PR on it if maintainers agree that is the right order. Everything else here is unaffected, since the other four rules and the
internal/privateparameters round-trip correctly.Pull request checklist
The new rules are optional attributes on an existing resource, so no state migration is needed.
Does this introduce a breaking change?
Please see our docs on breaking changes to help!
Existing
branch,tagandpushconfigurations are untouched. The one behaviour change to call out is thattargetis now validated against those four values at plan time, where it previously accepted any string and failed at the API instead.I used an AI assistant while writing this. I have read every line, verified the API behaviour against the REST docs and against live calls rather than taking the model's word for it, and ran the resources end to end against a real organization before opening this, as tabulated above.