Skip to content

🤖 feat: hold CoderWorkspacePool members at a lowered owner cap, and keep the failure run across a rescale - #379

Merged
ThomasK33 merged 5 commits into
mainfrom
feat/workspace-pool-deletes
Oct 14, 2026
Merged

ThomasK33 merged 5 commits into
mainfrom
feat/workspace-pool-deletes

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Summary

This PR closes Codex security finding 4271920249 from #359, and it keeps the failure run of a CoderWorkspacePool across a rescale. Both changes are in the dormant pool and member reconcilers. Nothing registers them yet, so no user sees a change.

  1. A lowered maxWorkspaces holds. When an admin lowers the owner's maxWorkspaces, the pool can already have members that it created under the old cap and that have not sent their create request yet. Before this PR, those members still created workspaces above the new cap. Now:
    • The member checks the cap again right before it writes its create marker, after all its Coder reads, on a new uncached read of the control plane. It lists the namespace's members without the cache and counts the owner's other members on the same control plane that may have a workspace (a create marker or a workspace ID) and whose workspace is not deleted. At the cap, it waits with OwnerWorkspaceLimit and sends no create request.
    • The pool deletes its own members that sent no create request yet, newest first, while the owner has more live members than the cap allows. Otherwise these members would wait at their cap check until their deadline fails them, and each such failure would count toward the failure limit. Each delete carries the listed UID and resourceVersion, so a member that wrote its marker after the list answers 409 and stays.
  2. A rescale keeps the failure run. Before this PR, any spec change (metadata.generation) started a new run of failures. So a pool that an HPA rescales through /scale could get past the 5-failure limit. Now only a change of status.resolved starts a new run: the template, the version, the preset, the parameters, the owner, or readyTimeoutSeconds. A change of replicas or maxInFlight keeps the run. maxWorkspaces still caps creation either way.

Refs #153

Background

This is PR 10a of the CoderWorkspacePool stack (#153). PR 10b (delete order, new before old, used-member release, consent removal) stacks on this branch.

Decision on the run reset: the maintainer asked that a replicas-only change does not reset the run, and that only input changes that can fix a failure do. I added readyTimeoutSeconds to the list, because a longer timeout can fix a DeadlineExceeded failure. Without it, a pool that stalled on deadline failures could only leave MemberFailureLimit through a template, version, or parameter change. To detect that change without a stored copy of the spec, status.resolved now holds readyTimeoutSeconds, and new members pin it from there. The member input check does not compare it, so a timeout change does not make ready members outdated. The first resolve (no stored status.resolved) does not start a run.

This also removes the case where the failure write before the deletes stores the run but not observedGeneration: the reset no longer reads observedGeneration. I recorded the remaining effect (that write publishes an old observedGeneration until the final write) in the plan for PR 12, as asked.

API: one new optional status field, status.resolved.readyTimeoutSeconds. The CRD is still in config/crd/dormant/, and the pool has no API reference page yet, so make docs-reference changes nothing.

Validation

Red, then green. I wrote the two tests first and ran them on main (fb42486a):

--- FAIL: TestPoolFailureRunSurvivesRescale
    coderworkspacepool_failure_test.go:223: a rescale keeps the run (expected: 1, actual: 0)
--- FAIL: TestPoolLoweredOwnerCap
    coderworkspacepool_cap_test.go:44: one workspace at maxWorkspaces 1 (expected: 1, actual: 3)

With this PR, both pass.

  • TestPoolLoweredOwnerCap (new, coderworkspacepool_cap_test.go): 3 pending members, then maxWorkspaces goes from 10 to 1. Every member reconciles before the pool sees the new cap: Coder gets exactly 1 workspace, and the other two wait with OwnerWorkspaceLimit without a marker. The pool then deletes exactly those two, keeps the member with the workspace, and creates no new member (OwnerWorkspaceLimit).
  • TestPoolFailureRunSurvivesRescale (new): after one failure, a /scale write to 2 replicas, a maxInFlight change, and a new name of the same version keep consecutiveFailures: 1 and the backoff. A readyTimeoutSeconds change starts a new run, a failure of a member with the old timeout does not count in it, and the new members pin the new timeout.
  • Changed tests: TestPoolFailureBackoffAndLimit and TestPoolFailureRunResets now lift the limit with a readyTimeoutSeconds change instead of a maxInFlight change. TestPoolResolvesInputs expects the new field.

Codex review round 1 (all fixed in ee015d1b):

  • 4274233487: a deleting member that sent no create request no longer counts as live, so the next reconcile deletes no more members (TestPoolLoweredOwnerCapDeletesOnce).
  • 4274233497: a new name of the same version no longer starts a new run (poolRunInputsChanged ignores templateVersionName).
  • 4274233505: a failed member with an old readyTimeoutSeconds no longer counts in the new run. It is still deleted.

Codex review round 2 (fixed in 007545e9):

Codex review round 3 (fixed in 4612ad65):

  • 4274801753: while the pool's inputs do not resolve (any wait or stall of the resolve step), failed members are deleted without counting. A bad spec edit then leaves no failures in the run, and a revert to the same inputs needs no reset (TestPoolFailuresUncountedWhileUnresolved). Trade-off: failures during a Coder outage do not count either.
  • 4274801768: the MemberFailureLimit message names only inputs that a user can change (spec.template is immutable).

Mutation checks: I removed one control at a time, and each removal made a named test fail (10 of 10): the member's cap check, the pool's deletes above the cap, keeping members with a workspace out of those deletes, counting only members that may have a workspace in the member's check, the reset on a generation change, the resolved timeout, not counting deleting pending members as live, ignoring a version rename, not counting failures at an old timeout, and not counting failures while the inputs do not resolve. The final cap read has a red run instead: TestPoolMemberRechecksCapLast failed on the code before that fix.

Gates on the final commit: drift (codegen, manifests, installer, API reference: no diff), make docs-check, dormant-CRD guard, docs lint and spelling, make verify-vendor, make build, make lint, actionlint, make test, make test-integration, make vuln, race. All passed.

Size

468 hand-written lines (230 production, 238 test, counting removals). Generated: 15 lines of the dormant CRD.

Risks

None for users. The reconcilers are dormant. One limit, recorded in the plan for PR 12: the member's cap check is exact while member reconciles run one at a time (the controller-runtime default). With parallel member reconciles, two members can pass the check together.


Generated with mux • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $154.26

…p the failure run across a rescale

Change-Id: I06dd5f74f7c244bf1ce6b444438fee1f4fcea25e
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T21:06:56.747206Z e98d43f Manual request
🔒 Security Review ✅ Completed 2026-10-14T21:06:24.703592Z e98d43f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 92242ff0a2

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92242ff0a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/controller/coderworkspacepool_controller.go Outdated
Comment thread internal/controller/coderworkspacepool_controller.go Outdated
Comment thread internal/controller/coderworkspacepool_controller.go
…ilure run on a version rename, and skip failures at an old timeout

Change-Id: I669be22671a8a465f71f12ddfe4a5030676365ba
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: ee015d1bc9

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee015d1bc9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/controller/coderworkspacepoolmember_controller.go Outdated
…, and check pool consent uncached whatever the demand

Change-Id: I24972f715031adeae241dbf3b92f6e975046cc59
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 007545e9b8

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 007545e9b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/controller/coderworkspacepool_controller.go
Comment thread internal/controller/coderworkspacepool_controller.go Outdated
…and drop the template from the failure-limit advice

Change-Id: I74d2b9f228ea3f2a6f08307f1a565fa006609cbe
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 4612ad65ff

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

…eletes

Change-Id: I8f645bb2b9743fef214dceb47c5d91756fa08910
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 4612ad65ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: e98d43f829

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: e98d43f829

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit b56243c Oct 14, 2026
10 checks passed
@ThomasK33
ThomasK33 deleted the feat/workspace-pool-deletes branch October 14, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant