Skip to content

Add ConditionalReferenceExpression with polyglot codegen support#14919

Open
danegsta wants to merge 15 commits intorelease/13.2from
danegsta/redisTls
Open

Add ConditionalReferenceExpression with polyglot codegen support#14919
danegsta wants to merge 15 commits intorelease/13.2from
danegsta/redisTls

Conversation

@danegsta
Copy link
Member

@danegsta danegsta commented Mar 3, 2026

Description

Replaces DeferredValueProvider with ConditionalReferenceExpression, a new type that models conditional values in connection strings and other reference expressions. This enables proper manifest publishing and polyglot code generation for conditional logic like TLS ssl=true in Redis connection strings.

ConditionalReferenceExpression

A ternary-style expression type that evaluates a boolean IValueProvider condition and selects between two ReferenceExpression branches (whenTrue/whenFalse). Key design decisions:

  • Auto-generated names: The manifest entry name is derived from the condition's ValueExpression at construction time (e.g., {redis.bindings.tcp.tlsEnabled}cond-redis-bindings-tcp-tlsenabled), eliminating the need for explicit naming
  • Manifest integration: Written as value.v0 entries in the manifest, referenced via {name.value} in connection strings
  • Create() factory: Follows the same pattern as ReferenceExpression.Create

Polyglot ATS Support

All 5 polyglot language base files (TypeScript, Go, Python, Java, Rust) support:

  • create() factory method for client-side CRE construction
  • toJSON() serialization using $condExpr format: { "$condExpr": { "condition": <handle>, "whenTrue": <$expr>, "whenFalse": <$expr> } }
  • Server-side $condExpr unmarshalling via ConditionalReferenceExpressionRef in AtsMarshaller

Redis TLS

Re-enables TLS by default for Redis container endpoints. EndpointReference.GetTlsValue now returns a ConditionalReferenceExpression instead of using a closure-based DeferredValueProvider, making it compatible with polyglot code generation.

Fixes #13645

Changes

New files

  • src/Aspire.Hosting/ApplicationModel/ConditionalReferenceExpression.cs — Core type with Create(), auto-name generation, manifest support
  • src/Aspire.Hosting.RemoteHost/Ats/ConditionalReferenceExpressionRef.cs — Server-side $condExpr JSON unmarshalling
  • tests/Aspire.Hosting.Tests/ConditionalReferenceExpressionTests.cs — 10 unit tests

Modified files

  • EndpointReference.csGetTlsValue returns CRE instead of DeferredValueProvider
  • RedisResource.cs — Updated BuildConnectionString to use new GetTlsValue signature
  • ManifestPublishingContext.cs — Registers and writes CRE entries as value.v0 resources
  • 5 polyglot base files — create()/toJSON() for ConditionalReferenceExpression
  • 5 code generators — Skip logic for ConditionalReferenceExpression type
  • Redis tests — Pattern matching assertions for auto-generated CRE names + manifest entry verification
  • Marshaller tests — 4 $condExpr unmarshalling tests
  • Handle registry tests — CRE handle registration test

Removed files

  • DeferredValueProvider.cs — Replaced by ConditionalReferenceExpression
  • DeferredValueProviderTests.cs — Replaced by ConditionalReferenceExpressionTests

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No
  • Does the change require an update in our Aspire docs?

@danegsta danegsta requested a review from mitchdenny as a code owner March 3, 2026 22:10
Copilot AI review requested due to automatic review settings March 3, 2026 22:10
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

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

Or

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new lazy/deferred value provider to support reference-expression fragments that depend on state only known later in the lifecycle (notably Redis TLS), and updates Redis endpoint/URI scheme handling to be scheme-driven rather than hard-coded.

Changes:

  • Introduces DeferredValueProvider (runtime + manifest expression callbacks) and an EndpointReference.TlsValue(...) helper.
  • Adds EndpointAnnotation.TlsEnabled / EndpointReference.TlsEnabled and wires Redis TLS to endpoint annotations (including ssl=true connection string fragment).
  • Updates Redis tests/manifests to use binding {...scheme} and default Redis endpoint scheme to redis (and rediss when TLS is enabled).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/DeferredValueProviderTests.cs New unit tests covering deferred provider behavior and interaction with ReferenceExpressionBuilder.
tests/Aspire.Hosting.Redis.Tests/ConnectionPropertiesTests.cs Updates expected Redis URI manifest expression to use {...scheme} binding.
tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs Updates Redis endpoint scheme expectations and adds TLS/dynamic-resolution coverage.
src/Aspire.Hosting/ApplicationModel/EndpointReference.cs Adds TlsEnabled and TlsValue(...) to support TLS-dependent dynamic fragments.
src/Aspire.Hosting/ApplicationModel/EndpointAnnotation.cs Adds TlsEnabled flag for endpoint-level TLS state.
src/Aspire.Hosting/ApplicationModel/DeferredValueProvider.cs Adds new general-purpose deferred value provider implementation.
src/Aspire.Hosting.Redis/RedisResource.cs Switches TLS handling to endpoint-based TLS state and scheme-driven URI/connection string fragments.
src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs Sets Redis primary endpoint scheme to redis and updates TLS enablement to mutate endpoint annotation state.

You can also share your feedback on Copilot code review. Take the survey.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 02747ac:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
TypeScriptAppHostWithProjectReferenceIntegration ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22793531443

@danegsta danegsta force-pushed the danegsta/redisTls branch from 9404e2f to a5aa70a Compare March 3, 2026 23:27
@davidfowl
Copy link
Member

How does this affect the typescript support?

cc @sebastienros @IEvangelist

danegsta and others added 2 commits March 6, 2026 12:49
Replace DeferredValueProvider with ConditionalReferenceExpression, a new
type that models conditional values in connection strings (e.g., TLS
ssl=true/empty). The CRE auto-generates its manifest name from the
condition's ValueExpression at construction time.

Key changes:
- ConditionalReferenceExpression type with Create() factory, auto-name
  generation via condition sanitization, and manifest value.v0 support
- EndpointReference.GetTlsValue returns CRE instead of using closure
- ManifestPublishingContext writes CRE entries as value.v0 resources
- Polyglot create()/toJSON() in all 5 ATS base files (TS, Go, Python,
  Java, Rust) with $condExpr JSON serialization format
- ConditionalReferenceExpressionRef for server-side $condExpr
  unmarshalling in AtsMarshaller
- Redis connection string tests updated with pattern matching to handle
  auto-generated CRE names and verify manifest value entries

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danegsta danegsta changed the title Add a new deferred value provider for dynamic properties in endpoint references Add ConditionalReferenceExpression with polyglot codegen support Mar 7, 2026
danegsta and others added 3 commits March 6, 2026 20:42
The MarshalToJson_ConditionalReferenceExpression_PreservesValueAfterRoundTrip
test was asserting an exact name ('test-tls') but names are now auto-generated
from the condition's ValueExpression. Use StartsWith assertion instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The merge brought in updated EndpointReference.getTlsValue which no
longer takes parameterName. Updated all 5 language snapshots accordingly.

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

This should be merged into ReferenceExpression if we take this approach.

- Add ReferenceExpression.CreateConditional() factory method
- Add conditional mode with IsConditional, Condition, WhenTrue, WhenFalse properties
- Unify ATS wire format: conditional uses $expr with condition/whenTrue/whenFalse
- Remove ConditionalReferenceExpression class and ConditionalReferenceExpressionRef
- Remove $condExpr from ATS protocol, remove ConditionalReferenceExpressionTypeId
- Update all 5 polyglot base templates (TS, Python, Go, Java, Rust)
- Update all 5 codegen generators to remove CRE special-casing
- Make ReferenceExpression.Name internal
- Migrate all tests to use new API
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.

5 participants