Skip to content

Add typed cert-manager API for Kubernetes/AKS environments - #17008

Merged
Mitch Denny (mitchdenny) merged 17 commits into
mainfrom
mitchdenny/cert-manager-api-design
May 14, 2026
Merged

Add typed cert-manager API for Kubernetes/AKS environments#17008
Mitch Denny (mitchdenny) merged 17 commits into
mainfrom
mitchdenny/cert-manager-api-design

Conversation

@mitchdenny

@mitchdenny Mitch Denny (mitchdenny) commented May 13, 2026

Copy link
Copy Markdown
Member

Description

Adds a typed cert-manager API surface to Aspire.Hosting.Kubernetes so cert-manager can be installed, configured, and wired to gateways/ingress through the Aspire app model — without dropping into raw WithAnnotation calls or hand-written Helm values.

What's added

  • AddCertManager(name) on IResourceBuilder<KubernetesEnvironmentResource> — installs the cert-manager Helm chart (helm install --wait) and returns a CertManagerResource for further configuration.
  • AddIssuer(name) on CertManagerResource — declares a ClusterIssuer that gets applied at deploy time after cert-manager is healthy.
  • Issuer fluent configuration:
    • WithLetsEncryptProduction(email) / WithLetsEncryptProductionParam(parameter)
    • WithLetsEncryptStaging(email) / WithLetsEncryptStagingParam(parameter)
    • WithAcmeServer(serverUrl, email) / WithAcmeServer(serverUrl, parameter) for custom ACME servers
    • WithHttp01Solver() (DNS-01 deferred to a follow-up PR)
  • gateway.WithTls(issuer) overload — wires a cert-manager ClusterIssuer to a gateway listener via the cert-manager.io/cluster-issuer annotation. Validates that the gateway and issuer live in the same KubernetesEnvironment so cross-cluster mistakes fail loudly at app-model build time.

Pipeline

The AddCertManager(...) call enqueues the existing helm-install pipeline step. Each AddIssuer(...) enqueues a cm-issuer-apply-{name} step that depends on the helm install (so cert-manager's validating webhook is guaranteed to be Available before the ClusterIssuer is applied — otherwise we race the webhook and get failed calling webhook "webhook.cert-manager.io": no endpoints available).

For gateways with TLS but no explicit WithHostname, the integration also pre-creates a self-signed bootstrap TLS secret so the controller (e.g., AGC) will program the listener before cert-manager has issued the real certificate. Without this the listener would deadlock waiting for a secret that doesn't exist yet.

C# example (Express + React on AKS, Let's Encrypt prod via HTTP-01)

#pragma warning disable ASPIREPIPELINES001
#pragma warning disable ASPIRECOMPUTE003
#pragma warning disable ASPIREAZURE003

var builder = DistributedApplication.CreateBuilder(args);

var acmeEmail = builder.AddParameter("acmeemail");

var aks = builder.AddAzureKubernetesEnvironment("aks")
    .WithSystemNodePool(p => p.VmSize = "Standard_D2as_v5");

var certManager = aks.AddCertManager("cert-manager");

var letsEncrypt = certManager.AddIssuer("letsencrypt-prod")
    .WithLetsEncryptProductionParam(acmeEmail)
    .WithHttp01Solver();

var api = builder.AddProject<Projects.Api>("api")
    .WithHttpEndpoint();

var gateway = aks.AddGateway("api-gw")
    .WithGatewayPathRoute("/", api.GetEndpoint("http"))
    .WithTls(letsEncrypt);

builder.Build().Run();

TypeScript example (same pattern, polyglot apphost)

import { distributedApplication } from "@microsoft/aspire";

const builder = await distributedApplication();

const acmeEmail = await builder.addParameter("acme-email");

const aks = await builder.addAzureKubernetesEnvironment("aks");
await aks.addAzureVirtualNetwork("vnet", { addressPrefix: "10.224.0.0/12" });
await aks.withSystemNodePool({ vmSize: "Standard_D2as_v5" });

const certManager = await aks.addCertManager("cert-manager");

const letsEncrypt = await certManager.addIssuer("letsencrypt-prod");
await letsEncrypt.withLetsEncryptProductionParam(acmeEmail);
await letsEncrypt.withHttp01Solver();

const app = await builder.addNpmApp("app", "../app", "start");
await app.withHttpEndpoint();

const gateway = await aks.addGateway("api-gw");
await gateway.withGatewayPathRoute("/", app.getEndpoint("http"));
await gateway.withGatewayTlsIssuer(letsEncrypt);

await builder.build().run();

Tests

  • tests/Aspire.Hosting.Kubernetes.Tests/CertManagerTests.cs — unit coverage for AddCertManager, AddIssuer, the various WithLetsEncrypt* and WithAcmeServer overloads, WithHttp01Solver, WithTls(issuer), and the cross-environment validation.
  • tests/Aspire.Hosting.Kubernetes.Tests/KubernetesGatewayTests.cs and KubernetesIngressTests.cs — added regression tests covering the WithTls()-then-WithHostname() ordering case.
  • tests/PolyglotAppHosts/Aspire.Hosting.Kubernetes/TypeScript/apphost.ts — exercises the entire surface in TypeScript via tsc --noEmit (so the [AspireExport]-driven TS bindings stay valid).
  • tests/Aspire.Deployment.EndToEnd.Tests/AksAzureKubernetesEnvironmentCertManagerDeploymentTests.cs and AksAzureKubernetesEnvironmentCertManagerTypeScriptDeploymentTests.cs — full deploy E2E tests that stand up AKS + AGC, install cert-manager, issue a real Let's Encrypt production certificate via HTTP-01, verify trusted HTTPS, and then re-deploy to exercise the helm UPGRADE path before destroying the cluster.

Bug fixes pulled in along the way

  • Helm v4 --server-side flag parsing — Helm v4 changed --server-side from a bool flag to a string-valued one (true|false|auto) in helm/helm#13649. Our code shelled out --server-side --force-conflicts, which Helm v4 silently parses as --server-side=--force-conflicts, poisoning release metadata so every subsequent upgrade fails with invalid/unknown release server-side apply method: --force-conflicts. The first install appeared to succeed; the second always failed. Now using --server-side=true so the flag parses identically under v3.18 and v4.
  • Gateway/ingress TLS hostname orderingWithTls(...) snapshotted Resource.Hostnames at call time, so calling WithTls() before WithHostname() produced an HTTPS listener with no hostname (and cert-manager would then issue a cert for the wrong host). The TLS config records now resolve hostnames lazily at manifest-emit time so calling order doesn't matter.

Out of scope (follow-ups)

  • DNS-01 solver support (e.g. Azure DNS) — needed for wildcard certs and for hostnames that aren't yet publicly addressable.
  • Renewal monitoring / dashboard surface for cert-manager certificates.

@github-actions

github-actions Bot commented May 13, 2026

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/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17008

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17008"

@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@mitchdenny
Mitch Denny (mitchdenny) changed the base branch from main to mitchdenny/aks-gateway-api-and-app-load-balancer May 13, 2026 06:43
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot had a problem deploying to deployment-testing May 13, 2026 06:49 Failure
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot had a problem deploying to deployment-testing May 13, 2026 06:49 Failure
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing May 13, 2026 06:49 Inactive

@mitchdenny Mitch Denny (mitchdenny) left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Self-review: 4 issues found.

Comment thread src/Aspire.Hosting.Kubernetes/CertManagerIssuerResource.cs Outdated
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Outdated
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Outdated
- Fix doc-comment grammar in CertManagerIssuerResource.
- Log warning when an HTTP-01 issuer has no annotated parent gateway,
  instead of silently emitting an unsatisfiable solver.
- Narrow temp-dir cleanup catch to IOException/UnauthorizedAccessException
  so OperationCanceledException and unexpected failures aren't swallowed.
- Use ResourceNameComparer to match parent environment, matching the
  pattern in KubernetesEnvironmentContext / KubernetesEnvironmentResource.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

Pull request overview

This PR adds a first-class cert-manager modeling layer for Kubernetes/AKS environments so AppHost code can declare cert-manager installation, ClusterIssuers, and TLS-enabled Gateways/Ingresses without raw Helm/kubectl wiring.

Changes:

  • Adds CertManagerResource, CertManagerIssuerResource, and extension APIs for installing cert-manager, configuring ACME issuers, HTTP-01 solvers, and WithTls(issuer).
  • Adds an AKS-specific AddCertManager overload.
  • Adds unit coverage, an Azure deployment E2E test, and a playground app demonstrating the typed API.
Show a summary per file
File Description
src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Implements typed cert-manager API, Helm install setup, issuer apply pipeline step, and TLS annotation overloads.
src/Aspire.Hosting.Kubernetes/CertManagerResource.cs Adds cert-manager wrapper resource and underlying Helm chart reference.
src/Aspire.Hosting.Kubernetes/CertManagerIssuerResource.cs Adds typed ClusterIssuer resource and internal issuer/solver model types.
src/Aspire.Hosting.Azure.Kubernetes/AzureCertManagerExtensions.cs Adds AKS-specific forwarding overload for AddCertManager.
tests/Aspire.Hosting.Kubernetes.Tests/CertManagerTests.cs Adds unit tests for resource registration, issuer config, TLS annotations, and run-mode behavior.
tests/Aspire.Deployment.EndToEnd.Tests/AksAzureKubernetesEnvironmentCertManagerDeploymentTests.cs Adds live AKS cert-manager deployment E2E validation.
playground/CertManagerDemo/CertManagerDemo.AppHost/AppHost.cs Adds playground AppHost using AKS, AGC, cert-manager, issuer, and TLS gateway APIs.
playground/CertManagerDemo/CertManagerDemo.AppHost/CertManagerDemo.AppHost.csproj Adds playground AppHost project.
playground/CertManagerDemo/CertManagerDemo.AppHost/Properties/launchSettings.json Adds launch profiles for the playground AppHost.
playground/CertManagerDemo/CertManagerDemo.AppHost/appsettings.json Adds playground AppHost logging settings.
playground/CertManagerDemo/CertManagerDemo.ApiService/Program.cs Adds sample API endpoints for routing/TLS validation.
playground/CertManagerDemo/CertManagerDemo.ApiService/CertManagerDemo.ApiService.csproj Adds playground API service project.
playground/CertManagerDemo/CertManagerDemo.ApiService/Properties/launchSettings.json Adds API service launch profile.
playground/CertManagerDemo/CertManagerDemo.ApiService/appsettings.json Adds API service logging/host settings.
playground/CertManagerDemo/aspire.config.json Points Aspire tooling at the playground AppHost.
Aspire.slnx Includes the new CertManagerDemo projects in the solution.

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 16

Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Outdated
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Outdated
- Require explicit name on AddCertManager (no default 'cert-manager') so
  multiple cert-manager installations across environments don't collide
- Drop ingress WithTls(issuer) overload; the HTTP-01 solver only emits a
  gatewayHTTPRoute parentRefs block today, so the ingress overload would
  silently produce a non-functional config. Will revisit when DNS-01 lands.
- Cross-environment validation in gateway WithTls(issuer): throw if the
  gateway and the issuer's cert-manager installation aren't in the same
  Kubernetes environment (cert-manager is per-cluster).
- Normalize ClusterIssuer metadata.name, privateKeySecretRef.name suffix,
  and Gateway parentRef name via ToKubernetesResourceName() so DNS-1123
  rules are satisfied even when the user picks a mixed-case Aspire name.
- Validate {name}-chart against the 64-char DNS-1123 label limit at
  AddCertManager time.
- Add destroy step (cm-issuer-delete-{name}) that runs before
  helm-uninstall-{chart} so ClusterIssuers are torn down while the
  cert-manager controller is still alive to clean up account secrets and
  while the CRDs still exist.
- Fix CertManagerIssuerResource doc: manifests are kubectl applied, not
  baked into the helm chart output.
- Trim 'change the chart version' claim from CertManagerResource.HelmChart
  doc; ChartVersion is get-only.
- Add per-overload XML doc params/returns on parameterized
  WithLetsEncryptProduction/Staging/AcmeServer.
- New unit tests:
  * BuildClusterIssuerManifest_EmitsExpectedYamlForLetsEncryptHttp01
    (covers DNS-1123 normalisation and parentRef wiring end-to-end)
  * Gateway_WithTls_Issuer_FromDifferentEnvironment_Throws
- Drop Ingress_WithTls_Issuer_AddsClusterIssuerAnnotation test
  (overload removed).
- Update playground + E2E test to pass explicit 'cert-manager' name.
- Remove stale 'Bug 2 fix' comment from E2E test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/Aspire.Hosting.Kubernetes/CertManagerExtensions.cs Outdated
Per Dan's review feedback (#17008): v1.18.2 was ~10 months old with
v1.20.2 being the current stable. v1.20.x has been GA since 2025-09 and
keeps the same Gateway API solver shape we already exercise, so no API
changes required.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@davidfowl

Copy link
Copy Markdown
Collaborator

Where is the typescript API? I don't see it in the pr description.

@mitchdenny

Copy link
Copy Markdown
Member Author

Where is the typescript API? I don't see it in the pr description.

My bad. I'll get it added and I'll add an E2E test for it as well.

Mitch Denny and others added 5 commits May 14, 2026 13:25
Addresses David Fowler's review feedback (where is the typescript API?)
by exercising the [AspireExport]-generated TypeScript surface of the
cert-manager API in two ways:

- Polyglot apphost.ts: exercises addCertManager + addIssuer +
  withLetsEncryptProduction/Staging/Param + withAcmeServer/Param +
  withHttp01Solver + gateway.withGatewayTlsIssuer. CI runs aspire
  restore --apphost + tsc --noEmit on this file on every PR push.

- AksAzureKubernetesEnvironmentCertManagerTypeScriptDeploymentTests:
  TS-AppHost variant of the C# AKS cert-manager E2E test. Uses the
  Express/React starter and patches apphost.ts to wire AKS + AGC +
  cert-manager + Let's Encrypt production around the Express API,
  deploys to AKS, and verifies the served cert is from Let's Encrypt
  via openssl + that https://<fqdn>/ returns 2xx.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t-manager E2E tests

In Helm v4, --server-side changed from a bool flag to a string flag
that requires a 'true'|'false'|'auto' value
(helm/helm#13649). Our previous
'--server-side --force-conflicts' caused Helm v4 to consume
'--force-conflicts' as the value for --server-side, poisoning the
release metadata with the literal string '--force-conflicts' as the
apply-method enum. The first install appeared to succeed, but every
subsequent 'helm upgrade --install' for that release failed with:

  Error: UPGRADE FAILED: invalid/unknown release server-side apply
  method: --force-conflicts

Pass --server-side=true (with explicit value) so the flag parses
identically under Helm v3.18 (where the bool flag also accepts an
explicit value) and Helm v4.

Add a 'Step N: Re-deploying to validate helm upgrade idempotency'
step to both AKS cert-manager E2E tests (C# and TypeScript variants)
that runs 'aspire deploy' a second time without --clear-cache. This
exercises the helm UPGRADE path that the original single-deploy test
did not cover.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously, WithTls() on both KubernetesGatewayResource and KubernetesIngressResource
snapshotted Resource.Hostnames into the GatewayTlsConfig / IngressTlsConfig record at
the moment WithTls() was called. This meant calling order mattered:

    gateway.WithHostname("api.example.com")
           .WithTls("my-secret");          // OK — snapshot has hostname

    gateway.WithTls("my-secret")          // BUG — snapshot is empty
           .WithHostname("api.example.com");

In the buggy second form, the generated HTTPS listener fell back to the
no-hostname code path. With cert-manager + an auto-FQDN gateway controller
like Azure Application Gateway for Containers, the listener would then be
patched to use the controller-assigned FQDN, and cert-manager would issue
a certificate for the wrong hostname (the auto-FQDN, not the user's
custom hostname).

Fix: drop the Hosts field from both record types and resolve hostnames
from gatewayResource.Hostnames / ingressResource.Hostnames at manifest-emit
time. WithTls() now only stores the secret name; ordering with WithHostname()
no longer affects the generated manifests.

Add two regression tests:
- AddGateway_WithTls_BeforeWithHostname_HostnameStillAppliedToHttpsListener
- AddIngress_WithTls_BeforeWithHostname_HostnameIncludedInTlsHosts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…urce)

The C# WithAcmeServer parameterized overload signature is
(string serverUrl, IResourceBuilder<ParameterResource> email).
The TypeScript polyglot test was incorrectly calling it with two
parameters, which TypeScript rejected as TS2345.

Pass a literal URL for the ACME directory and keep the email as
the ParameterResource argument.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When Gateway FQDN discovery patches the listener hostname via 'kubectl patch',
the field manager defaults to 'kubectl-patch'. A subsequent 'helm upgrade'
that uses server-side apply with field manager 'helm' then conflicts:

  conflict with "kubectl-patch" using gateway.networking.k8s.io/v1:
    .spec.listeners[name="https"].hostname

Pass --field-manager=helm so Helm is the registered owner from the start
and SSA on the next deploy does not conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

The runner-image's preinstalled helm predates v3.18 (which added
`helm install/upgrade --server-side` and `--force-conflicts`). The
cert-manager E2E tests rely on those flags via `WithForceConflicts()`,
so they fail with:

  Error: unknown flag: --server-side

Pin helm to v3.21.0 so the flags are available regardless of the runner
image's helm version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

Mitch Denny and others added 2 commits May 14, 2026 17:39
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Older Aspire builds patched Gateway listener hostnames with kubectl's
default field manager ("kubectl-patch") rather than "helm". The
resulting Update entry persists in the resource's managedFields after
later builds switched to --field-manager=helm, and helm's server-side
apply still conflicts with the foreign Update ownership of
.spec.listeners[name="https"].hostname on every subsequent upgrade
(including the case where the user transitions from auto-discovered to
explicit hostname). Add a pre-helm-deploy step that scans Gateways with
TLS for stale non-helm Update entries owning listener fields and removes
them via JSON Patch on managedFields. No-op on first deploy and on
clusters with no foreign managers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

The previous 5-minute timeout was insufficient for AGC, which has been
observed taking 5-10 minutes to assign an address when the cluster and
AGC are freshly provisioned in the same deploy. The deployment-test for
the AKS cert-manager TypeScript scenario hit this exact case: AGC took
~6 minutes to publish the address, so discovery exhausted its 60 attempts
and bailed out with a logged warning. The deploy then 'succeeded'
without ever patching the listener hostname, so cert-manager's gateway
shim never created a Certificate, and the test failed downstream with
'certificates.cert-manager.io api-gw-tls not found'.

Two fixes:
- Bump MaxRetryAttempts to 179 (~15 minutes) to match the wait budget
  the E2E test uses for the same condition.
- Throw on timeout instead of logging a warning and continuing. A deploy
  that completes without patching the listener hostname produces no
  valid TLS, which is worse than failing visibly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #17008...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

Copy link
Copy Markdown
Contributor

Deployment E2E Tests failed — 36 passed, 2 failed, 0 cancelled

View test results and recordings

View workflow run

Test Result Recording
Deployment.EndToEnd-AzureLogAnalyticsDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureEventHubsDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureStorageDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureServiceBusDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-KubernetesGatewayTlsDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureKeyVaultDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-KubernetesHelmChartDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetKeyVaultConnectivityDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-NspStorageKeyVaultDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetSqlServerConnectivityDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetKeyVaultInfraDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-TypeScriptVnetSqlServerInfraDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetSqlServerInfraDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-TypeScriptExpressDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureAppConfigDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AzureContainerRegistryDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AuthenticationTests ✅ Passed
Deployment.EndToEnd-AcaCustomRegistryDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AcaManagedRedisDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AcaExistingRegistryDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AcaDeploymentErrorOutputTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AppServiceReactDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetStorageBlobConnectivityDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AcaStarterDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksStarterWithRedisHelmDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksAzureKubernetesEnvironmentGatewayDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksAzureKubernetesEnvironmentCertManagerTypeScriptDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksStarterDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksMultipleNodePoolsDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksVnetInfraDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksAzureKubernetesEnvironmentCertManagerDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksBlazorRedisDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksVnetWithAzureResourcesDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksWithAzureResourcesDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AksWithHelmChartDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-VnetStorageBlobInfraDeploymentTests ✅ Passed ▶️ View Recording
Deployment.EndToEnd-AcaCompactNamingDeploymentTests ❌ Failed ▶️ View Recording
Deployment.EndToEnd-FrontDoorDeploymentTests ❌ Failed ▶️ View Recording

@github-actions

Copy link
Copy Markdown
Contributor

🎬 CLI E2E Test Recordings — 82 recordings uploaded (commit 7a51bc2)

View all recordings
Status Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View Recording
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
Banner_NotDisplayedWithNoLogoFlag ▶️ View Recording
CertificatesClean_RemovesCertificates ▶️ View Recording
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate ▶️ View Recording
CertificatesTrust_WithUntrustedCert_TrustsCertificate ▶️ View Recording
ConfigSetGet_CreatesNestedJsonFormat ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunEmptyAppHostProject ▶️ View Recording
CreateAndRunJavaEmptyAppHostProject ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptEmptyAppHostProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateJavaAppHostWithViteApp ▶️ View Recording
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain ▶️ View Recording
DashboardRunWithOtelTracesReturnsNoTraces ▶️ View Recording
DeployK8sBasicApiService ▶️ View Recording
DeployK8sWithExternalHelmChart ▶️ View Recording
DeployK8sWithGarnet ▶️ View Recording
DeployK8sWithMongoDB ▶️ View Recording
DeployK8sWithMySql ▶️ View Recording
DeployK8sWithPostgres ▶️ View Recording
DeployK8sWithRabbitMQ ▶️ View Recording
DeployK8sWithRedis ▶️ View Recording
DeployK8sWithSqlServer ▶️ View Recording
DeployK8sWithValkey ▶️ View Recording
DeployTypeScriptAppToKubernetes ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance ▶️ View Recording
DoListStepsShowsPipelineSteps ▶️ View Recording
DocsCommand_RendersInteractiveMarkdownFromLocalSource ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
GlobalMigration_HandlesCommentsAndTrailingCommas ▶️ View Recording
GlobalMigration_HandlesMalformedLegacyJson ▶️ View Recording
GlobalMigration_PreservesAllValueTypes ▶️ View Recording
GlobalMigration_SkipsWhenNewConfigExists ▶️ View Recording
GlobalSettings_MigratedFromLegacyFormat ▶️ View Recording
InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot ▶️ View Recording
InteractiveCSharpInitCreatesExpectedFiles ▶️ View Recording
InvalidAppHostPathWithComments_IsHealedOnRun ▶️ View Recording
LatestCliCanStartStableChannelAppHost ▶️ View Recording
LatestCliCanStartStableChannelTypeScriptAppHost ▶️ View Recording
LegacySettingsMigration_AdjustsRelativeAppHostPath ▶️ View Recording
LogLevelTrace_ProducesTraceEntriesInCliLogFile ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
OtelLogsReturnsStructuredLogsFromStarterAppCore ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
PublishWithConfigureEnvFileUpdatesEnvOutput ▶️ View Recording
PublishWithDockerComposeServiceCallbackSucceeds ▶️ View Recording
PublishWithoutOutputPathUsesAppHostDirectoryDefault ▶️ View Recording
ResourceCommand_FailsWhenInteractionServiceIsRequired ▶️ View Recording
RestoreGeneratesSdkFiles ▶️ View Recording
RestoreGeneratesSdkFiles_WithConfiguredToolchain ▶️ View Recording
RestoreRefreshesGeneratedSdkAfterAddingIntegration ▶️ View Recording
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes ▶️ View Recording
RunFromParentDirectory_UsesExistingConfigNearAppHost ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View Recording
UpdateProjectChannelToStable_TypeScript_PicksUpStablePackages ▶️ View Recording

📹 Recordings uploaded automatically from CI run #25854215965

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants