feat(Kind): wait for CRD establishment after manifest apply and Helm install - #1624
Conversation
Run a shared one-time post-apply CRD check for manifests and Helm charts instead of retrying Helm installs. Preserve cancellation, report rejected CRD names promptly, and cover the behavior with Kind tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e9f0e640-8889-4ab9-97b4-9750d337a9a3
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1624Or
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1624" |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Critical manifest API compatibility and API snapshot issues remain, along with a BestEffort client-factory failure path.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 3
Open (4)
What changed in this PR
Adds shared post-apply CRD establishment checks for Kind manifests and Helm charts before resources become Running.
Changes:
- Adds configurable strict and BestEffort CRD readiness checks.
- Replaces Helm CRD retry behavior with snapshot-based verification.
- Updates lifecycle integration, tests, documentation, and examples.
| File | Reviewed changes |
|---|---|
tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/KindPostApplyTests.cs |
Tests post-apply lifecycle behavior. |
tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/KindManifestTests.cs |
Tests manifest CRD checks and policies. |
tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/KindHelmChartTests.cs |
Tests Helm snapshots and readiness. |
tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/FakeCrdClient.cs |
Provides a Kubernetes client test double. |
tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/CommunityToolkit.Aspire.Hosting.Kind.Tests.csproj |
Adds test dependencies. |
src/CommunityToolkit.Aspire.Hosting.Kind/README.md |
Documents CRD readiness behavior and APIs. |
src/CommunityToolkit.Aspire.Hosting.Kind/KubectlTimeouts.cs |
Removes obsolete retry settings. |
src/CommunityToolkit.Aspire.Hosting.Kind/KubectlManager.cs |
Captures applied CRDs and queries snapshots. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindPostApplyChecks.cs |
Dispatches post-apply checks. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindManifestResourceBuilderExtensions.cs |
Runs checks after manifest application. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindInfrastructureExtensions.cs |
Registers post-apply infrastructure. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindHelmChartResourceBuilderExtensions.cs |
Runs checks after Helm installation. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindHelmChartResource.cs |
Removes Helm retry state. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindDeploymentOutcomeAnnotation.cs |
Stores deployment outcomes. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindDeployedResourceBuilderExtensions.cs |
Adds shared CRD policy APIs. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindCrdWaitPolicyAnnotation.cs |
Stores CRD wait configuration. |
src/CommunityToolkit.Aspire.Hosting.Kind/KindCrdEstablishmentCheck.cs |
Polls CRDs for establishment. |
src/CommunityToolkit.Aspire.Hosting.Kind/K8sManifestResource.cs |
Updates manifest CRD policy properties. |
src/CommunityToolkit.Aspire.Hosting.Kind/K8sManifestAnnotations.cs |
Updates manifest CRD policy metadata. |
src/CommunityToolkit.Aspire.Hosting.Kind/IKindPostApplyCheck.cs |
Defines the post-apply check contract. |
src/CommunityToolkit.Aspire.Hosting.Kind/HelmManager.cs |
Performs CRD snapshots around Helm installation. |
src/CommunityToolkit.Aspire.Hosting.Kind/CrdWaitBehavior.cs |
Updates CRD wait behavior documentation. |
examples/kind/CommunityToolkit.Aspire.Hosting.Kind.AppHost/AppHost.cs |
Removes obsolete retry configuration. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Preserve manifest API signatures as obsolete shims and validate timeout settings in options. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bf79db4b-7432-480c-963f-d3ea8eb4d12a
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bf79db4b-7432-480c-963f-d3ea8eb4d12a
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f4a6e49e-efde-4cdf-af03-0d197d72f2d1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f4a6e49e-efde-4cdf-af03-0d197d72f2d1
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The retained manifest shims may break regenerated TypeScript SDKs, and documentation needs correction.
Review effort: Lite
Findings: 2
Open (2)
Files not reviewed (1)
- examples/kind/CommunityToolkit.Aspire.Hosting.Kind.AppHost.TypeScript/package-lock.json: Generated file
The C# compatibility methods remained, but removing AspireExport hid them from regenerated TypeScript SDKs. Restore their exports and exercise both legacy calls in the TypeScript AppHost. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ea9e3ab7-35c0-4be7-9452-354d3b669967
aaronpowell
left a comment
There was a problem hiding this comment.
Some nits and a comment on why the test is failing.
Remove obsolete ASPIREATS001 suppressions and report the effective policy, reads, elapsed time, and cancellation state when the deadline assertion fails. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e5a18c4b-9d40-4015-a17d-211f294f75dd
Preserve the Kind test project Moq reference while adopting upstream removal of the direct MessagePack dependency. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e5a18c4b-9d40-4015-a17d-211f294f75dd
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Add the required ASPIREATS001 suppressions for the new exported declarations to prevent warnings-as-errors build failures.
Review effort: Lite
Findings: 2
Open (2)
Resolved since last review (2)
Files not reviewed (1)
- examples/kind/CommunityToolkit.Aspire.Hosting.Kind.AppHost.TypeScript/package-lock.json: Generated file
| [AspireExport(ExposeProperties = true)] | ||
| public sealed class CrdWaitOptions |
There was a problem hiding this comment.
@aaronpowell , I believe you suggested removing exactly this suppression in the discussion above. could you please recommend the next steps?
There was a problem hiding this comment.
Yeah, Copilot is wrong here
| [AspireExport(RunSyncOnBackgroundThread = true)] | ||
| public static IResourceBuilder<T> WithCrdWait<T>( |


Motivation
Kind-deployed resources can finish a Helm install or
kubectl applybefore Kubernetes has completed asynchronous reconciliation. PublishingRunningat that point can releaseWaitFordependents before required objects are ready.This PR adds a shared, extensible post-apply check stage before Kind-deployed resources become
Running. Its first check waits for discovered CRDs to reachEstablished, preserving the existing manifest CRD-readiness capability and extending it to Helm charts. Further checks could wait for Services or for CRDs Gatekeeper generates after applyingConstraintTemplates, without changingHelmManagerorKubectlManager. Those checks are not implemented in this PR; the extension point is currently internal to the Kind integration.Changes
Running, polls only CRDs still pending, and reports a rejected CRD name without waiting for unrelated reads. Caller cancellation and the CRD wait deadline remain effective even if a Kubernetes read returns late.WithCrdWait(options => ...)configures the timeout and failure behavior for both manifests and Helm charts. The default fails startup;BestEffortlogs unverified CRD readiness and allows startup after a handled CRD wait failure.Breaking change and migration
This removes the public Helm
WithCrdWaitRetry(...)API. UseWithCrdWait(options => { options.Timeout = ...; options.FailureBehavior = CrdWaitBehavior.BestEffort; })to configure the post-install CRD wait. These settings do not retry a failed Helm install. Charts needing external prerequisite CRDs must have them installed before the chart.The previously published manifest-specific
WithCrdWaitTimeout(...)andWithCrdWaitBehavior(...)methods, and theK8sManifestResource.CrdWaitTimeoutandCrdWaitBehaviorproperties, remain available as obsolete compatibility shims. New code should useWithCrdWait. The obsolete manifestCrdWaitTimeoutproperty now validates on assignment: zero, negative values, and values over one hour throw immediately; fractional seconds round up.Maintainer feedback on whether the Helm retry API removal needs a compatibility or deprecation path is welcome.
Limits
Helm's snapshot comparison does not prove chart ownership: it does not recheck pre-existing CRDs and may include CRDs created concurrently by another installer. The old opt-in retry path already used these snapshots; the new post-install check makes the same limitation apply to every successful Helm install by default. Manifest checks cover directly applied CRDs, not CRDs a controller generates later. A strict check failure sets
FailedToStartand leavesWaitFordependents waiting;BestEffortallows them to proceed after handled failures without verified CRD readiness.Verification
withCrdWaitcallbacks for both Helm and manifest resource builders, and the retained manifestwithCrdWaitTimeoutandwithCrdWaitBehaviormethods.Related work
Follows the manifest resource introduced in #1481. No issue is linked to this follow-up; the breaking change is disclosed above.
PR checklist
mainif required