feat: add opt-in idle browser rebuilds - #114
Conversation
fbed696 to
cec6189
Compare
cec6189 to
0905dc6
Compare
|
Follow-up review items are addressed in 6bf94ae and e311fe4. For the viewport question, I experimentally confirmed with Terraform CLI that a known viewport object can contain an unknown width. The provider intentionally fails closed rather than treating an unknown required dimension as unchanged: |
Sayan-
left a comment
There was a problem hiding this comment.
The unknown handling is right, and I checked the viewport case you flagged: requireKnownOptional tests the object, not its attributes, so a known viewport carrying an unknown width does reach browserViewportChanged, returns true, sets discard_all_idle, and then expandViewport errors before any API call happens. Fail-closed, exactly as you described.
Worth noting explicitly why the rest is safe, since it's load-bearing and not obvious from the diff: validateUpdateKnownValues requires known values for every string and collection field that browserLaunchConfigurationChanged compares with a raw .Equal, which is what prevents an unknown from being read as "changed" and triggering a discard with no corresponding patch. The three bools aren't in that list, which is why knownBoolChanged has to exist. Those two lists now have to stay in sync — if a future field is added to the launch-change check without a matching known-value guard, the failure mode is discarding idle browsers on a no-op update. The comment above the function covers the patch list; it's worth extending it to say that too.
One thing I'd add before this ships: a plan-time warning. Today a user with rebuild_idle_browsers_on_update = true who flips stealth sees a plan reading stealth: false -> true and nothing else. Nothing in that output says applying it will discard the pool's idle browsers. It isn't data loss — leased and warming browsers are untouched — but it is a capacity and cost event, and a pool of 200 draining and refilling is worth knowing about before you type yes. ModifyPlan can append a warning diagnostic when the flag is set and browserLaunchConfigurationChanged is true, which is the normal way providers surface a destructive side effect that isn't visible as a resource replacement. That's the difference between an intended rebuild and a surprising one.
Minor, take it or leave it: planAttrs["refresh_rate"].(types.Int64) is an unchecked type assertion. It can't fail given the declared object type, but if the viewport shape ever changes it panics the provider instead of returning a diagnostic.
Cover each launch-setting classification independently, assert the non-disruptive schema default, and give acceptance browser cleanup a fresh release deadline.
Surface the possible idle-capacity impact during planning, including unknown launch inputs, while suppressing the update warning for replacement plans. Add fail-closed update and plan-hook regression coverage.
e311fe4 to
caa0c1a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit caa0c1a. Configure here.
Use Terraform configuration to distinguish omitted computed launch fields from unresolved configured values. Preserve conservative warnings for real unknown inputs and cover both planning cases.
Keep the planning classifier aligned with every launch field and prove invalid clear operations suppress the capacity warning because no update can proceed.
Sayan-
left a comment
There was a problem hiding this comment.
Warning gate looks right. Reading req.Config to separate an omitted Optional+Computed value (null) from an unresolved expression (unknown) is the correct distinction, and keeping the plan-time comparison separate from the apply-time one is the right call since they need opposite unknown handling. Skipping the warning on replacement and on updates that would already fail validation are both good catches.

Summary
rebuild_idle_browsers_on_updatetokernel_browser_pool, defaulting tofalsediscard_all_idle=trueonly when the option is enabled and profile, proxy, extensions, Chrome policy, viewport, headless, kiosk, stealth, or start URL changesfalseunless configured otherwiseWhy
Kernel browser-pool updates normally change the template for future browsers without replacing existing instances. This gives customers an explicit Terraform opt-in to rebuild browsers that are already idle when launch configuration changes.
Discarding idle browsers can temporarily reduce ready capacity while the pool refills. The plan warning exposes that effect before approval, including when interpolated launch inputs are not known until apply. Browsers that are warming or currently leased are not rebuilt, matching the Kernel API contract.
Acquire and release remain outside the Terraform provider surface. The acceptance test uses the SDK only to verify the resulting browser configuration.
Example
Verification
go test -race ./internal/resources/browserpool -run 'Test(ModifyPlanWarnsBeforeIdleBrowserRebuild|ExpandUpdateParamsRejectsUnknownLaunchComparisonValuesBeforeDiscard)' -count=20go test -short -timeout=2m ./...go vet ./...gofmt -l cmd internalbash scripts/check-docs.shbash scripts/check-markdown-links.shbash scripts/check-examples.shGo and docspassed atcaa0c1aThe browser-pool lifecycle acceptance test passed earlier in this PR in 64.99 seconds. It changed stealth from
falsetotrue, acquired a rebuilt browser withstealth=true, and released it withreuse=false. It was not rerun after the plan-warning follow-up because that change does not alter the API payload or lifecycle behavior; the warning and unknown-value paths are covered by focused framework, unit, and race tests.Note
Medium Risk
Updates can discard idle pool browsers and temporarily reduce ready capacity when opted in; behavior is gated and well-tested but affects live browser-pool runtime.
Overview
Adds
rebuild_idle_browsers_on_updatetokernel_browser_pool(optional/computed, defaultfalse, not stored by Kernel—imports default to false unless set in config).When the flag is true and launch-related fields change (profile, proxy, extensions, chrome policy, viewport, headless/kiosk/stealth, start URL), pool updates include
discard_all_idle=trueso idle browsers are replaced with the new template; warming/leased browsers are unchanged. Name, size, timeouts, fill rate, and toggling the flag alone stay non-disruptive—preference-only updates persist in state without an API PATCH.ModifyPlanemits a plan warning when rebuild may run (including unknown launch inputs), and skips it for create/destroy, project replacement, disabled preference, or non-launch edits.Docs and acceptance coverage are updated: the browser-pool lifecycle test opts into rebuild, waits for capacity, verifies stealth on an acquired browser (SDK acquire/release with
reuse=false), and ignores the provider-local attribute on import verify.Reviewed by Cursor Bugbot for commit a6bf679. Bugbot is set up for automated code reviews on this repo. Configure here.