Skip to content

fix(branch_protection_v3): send each required status check only once - #3585

Merged
stevehipwell merged 6 commits into
integrations:mainfrom
dekokun:fix-branch-protection-v3-duplicate-contexts
Sep 10, 2026
Merged

fix(branch_protection_v3): send each required status check only once#3585
stevehipwell merged 6 commits into
integrations:mainfrom
dekokun:fix-branch-protection-v3-duplicate-contexts

Conversation

@dekokun

@dekokun dekokun commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Resolves #3420


Before the change?

Updating a github_branch_protection_v3 resource that has non-empty required_status_checks fails:

Error: PUT https://api.github.com/repos/<org>/<repo>/branches/main/protection: 422 Validation Failed
[{Resource: Field: Code: Message:Context must be unique per branch protection.}]

The branch protection API returns every required check under both contexts and checks, so flattenAndSetRequiredStatusChecks puts the same set into both state fields. Both are Optional + Computed, so the field that is not configured keeps its state value forever, and expandRequiredStatusChecks merges both fields into one checks array — sending each context twice.

Configuration cannot hit this on its own (checks conflicts with contexts); the duplicate always comes from state. import is one way to get there (as in #3420), but so is a plain apply: Create only sees the configured field and succeeds, and the read that follows it populates both. From then on any update to that resource fails, even when the change has nothing to do with status checks — I hit this in production on a change that only flipped require_code_owner_reviews, on resources this provider had created itself.

Note on #2232, which proposed a similar fix and was closed as unnecessary because both fields would be made Computed: true: both fields already are Optional + Computed in v6.13.0 and the bug is still there. The schema is not what produces the duplicate — the read path writing both fields plus the write path merging them is.

After the change?

Requests carry each context once. When a context is present in both fields, an app_id that came from checks wins, since contexts cannot express one.

A check read back as app_id: null allows any app, which is -1 on write, so the deduplicated check keeps app_id: -1 instead of omitting the field — omitting it makes GitHub select the app that recently provided the check, which would silently pin an app that was not pinned before.

Tests: a unit test on expandRequiredStatusChecks for the state shapes above, and an acceptance case that updates an unrelated setting after the first apply (the existing no-churn tests only re-plan the same config, so they never perform an update).

I ran the acceptance case against a real organization in organization mode. With only the fix reverted it fails at step 2 with the 422 above, for both the contexts and the checks variant; with the fix in place both pass. make test, golangci-lint run ./... and make lintcheck-new are clean.

Per the AI use policy: the patch and this description were drafted with an AI coding assistant. I reviewed the change and ran every test and lint run described above myself.

Pull request checklist

  • Schema migrations have been created if needed (example)
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)

Does this introduce a breaking change?

  • Yes
  • No

dekokun added 2 commits July 28, 2026 16:56
The branch protection API returns every required check under both
`contexts` and `checks`, so a read populates both fields even though
configuration can only set one of them. Updating the resource then sent
each check twice and GitHub rejected the request with "Context must be
unique per branch protection".

Deduplicate by context when building the request, keeping an app_id that
came from `checks`. A check read back with `app_id: null` allows any app,
which is -1 on write, so set that explicitly rather than omitting app_id
(omitting it lets GitHub pick an app).
The existing no-churn tests only re-plan the same config, so they never
exercise an update on a resource whose state holds both `contexts` and
`checks`. Add a case that changes an unrelated setting after the first
apply, for both status check fields.
@github-actions

Copy link
Copy Markdown

👋 Hi, and thank you for this contribution!

This repo is maintained by GitHub and community members on a best-effort basis. We'll get to this as soon as we can.

You can help us prioritize by joining the discussion on open issues and PRs, sharing details on the changes you need, and reviewing other contributions.


🤖 This is an automated message.

@github-actions github-actions Bot added the Type: Bug Something isn't working as documented label Jul 29, 2026
@dekokun
dekokun marked this pull request as ready for review July 29, 2026 09:17
@deiga
deiga requested a review from Copilot August 2, 2026 15:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The new acceptance step must use the repository-required ConfigStateChecks API.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

These provider review instructions are being used.

Fixes duplicate required-status-check contexts in branch protection updates.

Changes:

  • Deduplicates checks by context while preserving app_id.
  • Adds unit and acceptance regression coverage.
File summaries
File Description
github/resource_github_branch_protection_v3_utils.go Deduplicates expanded status checks.
github/resource_github_branch_protection_v3_utils_test.go Tests expansion and deduplication.
github/resource_github_branch_protection_v3_test.go Tests updates after status-check reads.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread github/resource_github_branch_protection_v3_test.go Outdated
Comment thread github/resource_github_branch_protection_v3_test.go Outdated
Comment thread github/resource_github_branch_protection_v3_test.go Outdated
… test

- use mustCreateTestRepository instead of an inline github_repository resource
- relax the precheck to skipUnauthenticated, since branch protection does not
  require an organization
- express assertions with ConfigStateChecks/statecheck instead of the legacy
  Check/TestCheckResourceAttr API
@dekokun

dekokun commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Pushed dd7463c addressing all three points:

  • use mustCreateTestRepository(t) instead of an inline github_repository resource
  • skipUnlessHasOrgsskipUnauthenticated, since branch protection does not require an org
  • assertions converted from Check/TestCheckResourceAttr to ConfigStateChecks + statecheck.ExpectKnownValue

@deiga ready for another look when you have a moment.

@dekokun

dekokun commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@deiga gentle ping on this one — the three review comments were addressed in dd7463c a week ago and CI is green. Happy to make further changes if anything still looks off.

For context on why this might be worth prioritising: with required_status_checks set, github_branch_protection_v3 currently cannot be updated in place at all — a read populates both contexts and checks, so any subsequent update sends every check twice and GitHub rejects it with 422 Context must be unique per branch protection (#3420). The only workaround today is reconciling the branch protection by hand via gh api, which needs admin rights on the repo.

Also happy to rebase onto main if you would prefer the branch up to date before merging.

deiga
deiga previously approved these changes Aug 13, 2026

@deiga deiga left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@deiga
deiga requested a review from stevehipwell August 13, 2026 12:33
@dekokun

dekokun commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

@stevehipwell friendly ping — this has been sitting on your review since @deiga approved it and requested you on Aug 13. CI is green and there are no conflicts with main.

The change is small and narrowly scoped: on update, the provider was sending each required status check twice (once from the deprecated contexts field, once from checks, both of which a read populates from the same API response), so GitHub rejected every update with 422 Context must be unique per branch protection. The practical impact is that a github_branch_protection_v3 resource with a non-empty required_status_checks block cannot be updated in place at all — even for unrelated fields — and the only workaround is reconciling branch protection by hand with gh api, which needs admin on the repo (#3420).

No rush if you are busy — happy to leave it in the queue, just flagging that it is unblocked from my side. I can also update the branch onto main whenever that helps.

@deiga

deiga commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

@dekokun To help get your PR reviewed, could you please help us with reviewing other open PRs?
That can help get this and other features implemented faster 🙏

For review guidance, familiarize yourself with our Contributing and Architecture guidelines ☺️

@dekokun

dekokun commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

@deiga Sure, happy to help. I have left a review on #3621 and I will keep picking up a couple of open PRs as I go.

@stevehipwell stevehipwell left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR looks good, just a minor nit.

Comment thread github/resource_github_branch_protection_v3_test.go Outdated

@deiga deiga left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@deiga deiga added the needs-github-review Request a review from GitHub label Sep 8, 2026
@team-review-router
team-review-router Bot requested a review from a team September 8, 2026 03:55
@dekokun
dekokun requested a review from stevehipwell September 8, 2026 04:21
@dekokun

dekokun commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @deiga! I've resolved the four review threads and the branch is up to date, so CI (including the required Continuous Integration check) is green.

The only thing left blocking the merge is @stevehipwell's change request from Sep 7, which was just the single-line formatting nit — fixed in f3fdde0 and replied to on the thread. I've re-requested their review. If it's easier for you to dismiss it, that works too, but no rush either way.

@stevehipwell stevehipwell left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@robert-crandall robert-crandall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this and adding regression coverage. The fix preserves app bindings while removing duplicate checks. Looks good to me!

@stevehipwell

Copy link
Copy Markdown
Collaborator

@dekokun if you rebase this PR we should be able to get it merged.

@dekokun

dekokun commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Updated onto main, @stevehipwell — should be good to go now. Thanks!

@stevehipwell
stevehipwell enabled auto-merge (squash) September 10, 2026 08:37
@stevehipwell
stevehipwell merged commit 29bdb01 into integrations:main Sep 10, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-github-review Request a review from GitHub r/branch_protection_v3 Type: Bug Something isn't working as documented

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: github_branch_protection_v3 imports both checks and contexts

5 participants