Skip to content

feat(Kind): wait for CRD establishment after manifest apply and Helm install - #1624

Merged
aaronpowell merged 8 commits into
CommunityToolkit:mainfrom
andrey-noskov:prototype/manifest-health
Sep 30, 2026
Merged

aaronpowell merged 8 commits into
CommunityToolkit:mainfrom
andrey-noskov:prototype/manifest-health

Conversation

@andrey-noskov

@andrey-noskov andrey-noskov commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Kind-deployed resources can finish a Helm install or kubectl apply before Kubernetes has completed asynchronous reconciliation. Publishing Running at that point can release WaitFor dependents 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 reach Established, 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 applying ConstraintTemplates, without changing HelmManager or KubectlManager. Those checks are not implemented in this PR; the extension point is currently internal to the Kind integration.

Changes

  • Manifests supply CRD names reported by a successful apply. Helm compares cluster CRD snapshots before and after a successful install and supplies newly observed names.
  • The shared check waits once before 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; BestEffort logs unverified CRD readiness and allows startup after a handled CRD wait failure.

Breaking change and migration

This removes the public Helm WithCrdWaitRetry(...) API. Use WithCrdWait(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(...) and WithCrdWaitBehavior(...) methods, and the K8sManifestResource.CrdWaitTimeout and CrdWaitBehavior properties, remain available as obsolete compatibility shims. New code should use WithCrdWait. The obsolete manifest CrdWaitTimeout property 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 FailedToStart and leaves WaitFor dependents waiting; BestEffort allows them to proceed after handled failures without verified CRD readiness.

Verification

  • Kind test suite: 287 passed, 0 failed.
  • Kind Release multi-target build: 0 warnings, 0 errors.
  • The generated TypeScript AppHost test exercises withCrdWait callbacks for both Helm and manifest resource builders, and the retained manifest withCrdWaitTimeout and withCrdWaitBehavior methods.

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

  • Changes are on a feature branch in a fork; no merge commits
  • README and tests updated
  • Breaking change and migration path disclosed
  • Rebase onto the latest upstream main if required

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
Copilot AI lite review requested due to automatic review settings September 25, 2026 16:21
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1624

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1624"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 High severity · 1 Medium severity

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.

Comment thread src/CommunityToolkit.Aspire.Hosting.Kind/K8sManifestResource.cs
Comment thread src/CommunityToolkit.Aspire.Hosting.Kind/KindDeployedResourceBuilderExtensions.cs Outdated
Comment thread tests/CommunityToolkit.Aspire.Hosting.Kind.Tests/KindManifestTests.cs Outdated
Comment thread src/CommunityToolkit.Aspire.Hosting.Kind/KindCrdEstablishmentCheck.cs Outdated
andrey-noskov and others added 3 commits September 26, 2026 17:45
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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved moderate findings affect ATS exports, generated API surfaces, and polyglot CRD-wait configuration.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (4)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f4a6e49e-efde-4cdf-af03-0d197d72f2d1

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The retained manifest shims may break regenerated TypeScript SDKs, and documentation needs correction.

Review effort: Lite
Findings: 2 Medium severity

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 aaronpowell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some nits and a comment on why the test is failing.

Comment thread src/CommunityToolkit.Aspire.Hosting.Kind/CrdWaitOptions.cs Outdated
Comment thread src/CommunityToolkit.Aspire.Hosting.Kind/KindDeployedResourceBuilderExtensions.cs Outdated
@andrey-noskov andrey-noskov changed the title feat(Kind): add post-apply checks for CRD establishment feat(Kind): wait for CRD establishment after manifest apply and Helm install Sep 29, 2026
andrey-noskov and others added 2 commits September 29, 2026 14:25
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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 High severity

Open (2)
Resolved since last review (2)
Files not reviewed (1)
  • examples/kind/CommunityToolkit.Aspire.Hosting.Kind.AppHost.TypeScript/package-lock.json: Generated file

Comment on lines +9 to +10
[AspireExport(ExposeProperties = true)]
public sealed class CrdWaitOptions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@aaronpowell , I believe you suggested removing exactly this suppression in the discussion above. could you please recommend the next steps?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, Copilot is wrong here

Comment on lines +26 to +27
[AspireExport(RunSyncOnBackgroundThread = true)]
public static IResourceBuilder<T> WithCrdWait<T>(
@aaronpowell
aaronpowell merged commit f860c81 into CommunityToolkit:main Sep 30, 2026
17 checks passed
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.

3 participants