fix: include configured false booleans on organization_settings create - #3570
fix: include configured false booleans on organization_settings create#3570somaz94 wants to merge 4 commits into
Conversation
|
👋 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. |
deiga
left a comment
There was a problem hiding this comment.
Nice work!
Could you refactor the unit tests to use a single testing function with a table for test cases?
There was a problem hiding this comment.
Please don't create a separate unit test file. Add the unit tests to the existing test file instead
There was a problem hiding this comment.
Done in 8cead3a — this file is deleted. The unit tests now live at the bottom of the existing github/resource_github_organization_settings_test.go.
| // attribute explicitly configured as false is included in the create payload. | ||
| // Regression test for the create path dropping false booleans (only fixed by a | ||
| // second apply through the update/HasChange path). | ||
| func TestBuildOrganizationSettingsCreateIncludesFalseBool(t *testing.T) { |
There was a problem hiding this comment.
Please use an underscore to separate function under test and the testcase in the name
There was a problem hiding this comment.
Done in 8cead3a — the five separate funcs are now a single table-driven Test_buildOrganizationSettings, following the repo's existing Test_getBaseURL / Test_configureProviderMeta convention. Testcase names use underscores (e.g. create_includes_explicitly_false_booleans, enterprise_create_includes_internal_repositories_boolean).
20e8bf1 to
8cead3a
Compare
|
@deiga Thanks for the review — all three points addressed in
I also verified the table still has teeth: temporarily reverting the Rebased on latest |
8cead3a to
0f86150
Compare
There was a problem hiding this comment.
suggestion: There is little benefit on using shouldInclude for boolean fields, if it will just return true. What id you instead remove the call to shouldInclude from the boolean fields?
There was a problem hiding this comment.
Done in cbe668a8, with one wrinkle worth flagging.
Removing the call outright would have changed the update path: shouldInclude returns true for booleans only on create — on update it still falls through to d.HasChange(fieldName), which is what keeps unchanged fields out of the payload and avoids the API validation errors the function comment mentions.
So I split it in two instead. The schema lookup and the TypeBool special case are gone, and the boolean fields no longer call shouldInclude:
// Non-boolean fields are included only when explicitly configured on create,
// and only when changed on update.
shouldInclude := func(fieldName string) bool {
if isUpdate {
return d.HasChange(fieldName)
}
_, ok := d.GetOk(fieldName)
return ok
}
// Boolean attributes always carry a definite value from their schema
// default, and d.GetOk cannot tell an explicit false from an unset field,
// so on create they are included unconditionally.
includeBool := func(fieldName string) bool {
return !isUpdate || d.HasChange(fieldName)
}Happy to collapse it further if you'd rather see something else.
There was a problem hiding this comment.
@stevehipwell do I remember correctly that we want to remove all unnecessary partial updates?
In that case the whole shouldInclude function wpuld be unnecessary
There was a problem hiding this comment.
@deiga — one data point that might make this cheaper to decide than it looks: shouldInclude is used in exactly one place in the repo. It's defined in this file and called 27 times, all inside the same function. So removing it entirely would be a single-resource change, not a cross-provider refactor.
I also went looking for the broader rule you're recalling and couldn't find it written down anywhere — no issue, PR or CONTRIBUTING note about removing partial updates. The closest thing is #3429, which is the bug this PR fixes.
stevehipwell hasn't been active since Jul 27, so rather than hold this on his answer: if you'd like the full-payload version, say the word and I'll push it in this PR. If you'd rather keep the current includeBool split and treat removing shouldInclude as its own change, that works too. Happy either way — I just don't want to guess and build the wrong one.
Separately, and regardless of the above: CI and CodeQL are sitting at action_required on ecd0631f and have never run on this branch, so the green checkmarks are only the pull_request_target workflows. The Go tests haven't actually executed here yet. If you approve the run we'd both be looking at real results.
Happy to rebase too — it's one commit behind.
|
@deiga @stevehipwell — happy to go either way on this, just let me know which you prefer so I do not build the wrong thing. Option A (this PR as it stands): keep Option B (what @deiga raised): remove I am glad to do B in this PR if that is the agreed direction. The only thing blocking me is knowing which one you want. For what it is worth, the three earlier review threads are already addressed ( |
|
I hit this on a first apply against a new organisation, so a data point in favour of fixing it, plus one thing worth weighing before The partial payload on create is load-bearing. It arrived in #2807 to fix #2305, where the resource returned a 422 on every apply for EMU organisations because unconfigured fields were being sent. Dropping There is also a live conflict with #3360. That PR fixes #2689, a 422 when an enterprise policy locks forking, by removing Option 1 in #3493 sidesteps both. Testing the raw configuration for a null attribute distinguishes a configured |
|
Thanks for digging into this — the #3360 point is a fair catch and I'd missed it. On which way to fix it, I don't think I should pick on my own. @deiga suggested the opposite direction on 28 Jul — dropping the Either answer is small work from here. If partial updates stay, I'll switch the create check to a raw-config null test (the sample patch in #3493), which fixes the explicit @stevehipwell @deiga — could I get a steer? Happy to re-cut either way. |
Resolves #3493
Before the change?
On create,
github_organization_settingsdropped any boolean attributeexplicitly set to
false.buildOrganizationSettingsgated every fieldthrough
shouldInclude, which on the create path usedd.GetOk(name).GetOkreturnsok=falsefor aTypeBoolwhose value isfalse, so itcannot tell an explicit
falsefrom an unset field. The attribute was omittedfrom the create PATCH and GitHub applied its own default. A second
applyfixed it because the update path uses
d.HasChange.After the change?
On create,
shouldIncludenow always includesschema.TypeBoolattributes.Every bool in this resource declares a schema
Default, so it always has adefinite value (there is no meaningful "unset"), and
d.Get(name).(bool)(already used by the bool setters) sends the configured value correctly,
including
false. Non-boolean fields are unchanged (still included only whenconfigured), and the update path is untouched.
Note: since these bools declare a schema default, an unconfigured bool now also
sends its default explicitly on create. That value equals the schema default,
so the resulting state is identical, just made explicit.
Pull request checklist
github/resource_github_organization_settings_unit_test.gowith 5 unittests (create includes false/true bool, unset string still omitted,
enterprise-only bool gating, update path still gates on
HasChange). Runsunder
make testwith no org credentials. The false-bool test fails oncurrent
mainand passes with this fix.user-facing schema/docs change; the
buildOrganizationSettingsdoccomment was updated to match the new behavior).
Does this introduce a breaking change?