feat(primitives): shared WorkloadMutator interface for workload-kind-agnostic mutations#143
Merged
Merged
Conversation
Captures the design for issue #142: a shared primitives.WorkloadMutator interface plus per-kind LiftMutation adapters, so consumers can write one workload-kind-agnostic mutation and apply it across StatefulSet, Deployment, and DaemonSet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uards Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move LiftMutation to end-of-file in the deployment and daemonset mutators to match the statefulset layout, so the three adapters read identically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a shared, workload-kind-agnostic mutation surface to the framework so consumers can write a single emitter against a common interface and apply it to multiple pod-workload primitives (StatefulSet/Deployment/DaemonSet) via per-kind adapters.
Changes:
- Introduces
primitives.WorkloadMutator, an exported interface representing the shared editing surface across StatefulSet/Deployment/DaemonSet mutators. - Adds per-kind
LiftMutationadapters plus compile-time conformance guards instatefulset,deployment, anddaemonset. - Adds unit + cross-kind tests and documents the new interface/lift pattern in
docs/primitives.md(plus additional design/plan docs underdocs/superpowers/).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/primitives/workload_mutator.go | Adds the shared WorkloadMutator interface in the new top-level primitives package. |
| pkg/primitives/workload_mutator_test.go | Cross-kind test proving one emitter can target multiple workload kinds via LiftMutation. |
| pkg/primitives/statefulset/mutator.go | Adds conformance guard and LiftMutation adapter for StatefulSets. |
| pkg/primitives/statefulset/mutator_test.go | Adds tests covering lift adapter behavior (carry-over, gating, nil mutate). |
| pkg/primitives/deployment/mutator.go | Adds conformance guard and LiftMutation adapter for Deployments. |
| pkg/primitives/deployment/mutator_test.go | Adds tests covering lift adapter behavior (carry-over, gating, nil mutate). |
| pkg/primitives/daemonset/mutator.go | Adds conformance guard and LiftMutation adapter for DaemonSets. |
| pkg/primitives/daemonset/mutator_test.go | Adds tests covering lift adapter behavior (carry-over, gating, nil mutate). |
| docs/primitives.md | Documents workload-kind-agnostic mutations using WorkloadMutator + LiftMutation. |
| docs/superpowers/specs/2026-06-01-workload-mutator-interface-design.md | Adds a design note for the interface and lifting approach. |
| docs/superpowers/plans/2026-06-01-workload-mutator-interface.md | Adds an implementation plan for the change. |
Add the import block (matching the doc's example convention), a DaemonSet lift call, an explicit statement of what LiftMutation returns and why the lift is needed, and name the excluded spec editors while clarifying that EnsureReplicas is excluded because the DaemonSet mutator has no replica field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Name StatefulSet/Deployment/DaemonSet as the explicit set the interface spans, rather than implying it covers every pod-based primitive (pod, job, cronjob, replicaset also expose pod-template editing methods). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uctions Remove the design spec and implementation plan from version control (kept local via .gitignore) so internal planning artifacts stay out of the published diff. Add the new pkg/primitives top-level package to the "Source to read" list in the committed instruction files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #142
*statefulset.Mutator,*deployment.Mutator, and*daemonset.Mutatorshare an almostidentical container/env/podspec/metadata editing surface but are unrelated concrete types,
so a consumer could not write one workload-kind-agnostic mutation against a framework type.
This PR exports
primitives.WorkloadMutator, the interface covering exactly that sharedsurface, plus a per-kind
LiftMutationadapter so a single emitter can be applied to anypod-workload kind. The motivating case is a set of components that share env-emission
concerns but render as two different workload kinds.
Changes
pkg/primitivesexportingWorkloadMutator, the editing-surfaceintersection of the three pod-workload mutators (container, init-container, pod-spec,
pod-template-metadata, object-metadata, env, and arg methods).
LiftMutation(feature.Mutation[primitives.WorkloadMutator]) Mutationon each of thestatefulset, deployment, and daemonset packages, carrying
NameandFeaturegatingthrough unchanged and preserving a nil
Mutate.var _ primitives.WorkloadMutator = (*Mutator)(nil)) ineach mutator package, so a future rename or removal of a shared method breaks the build in
the framework instead of drifting silently downstream.
docs/primitives.mddocuments the interface and the lift pattern.Challenges
The interface is the intersection across all three kinds, not just the two named in the
issue. That excludes
EnsureReplicas(the daemonset mutator has no replica field) and theStatefulSet-only VolumeClaimTemplate methods, keeping the contract stable if a future
replica-less workload kind is added. The package must not import its own subpackages (they
already import it for the guards), so the interface depends only on the editor and selector
packages.
Testing
make all(fmt, lint,go test ./...) andmake build-examplesare green. Each kind hasunit tests for the lift adapter covering name/feature carry-over, gate-enabled apply,
gate-disabled no-op through
ApplyIntent, and nil-Mutatepreservation (asserting thenamed error rather than a panic). A cross-kind test applies one shared emitter to both a
StatefulSet and a Deployment and asserts the env var lands on both. The conformance guards
are the compile-time check that all three mutators satisfy the interface.
🤖 Generated with Claude Code