Skip to content

Add sample Temporal integration for Aspire#127

Open
cecilphillip wants to merge 4 commits into
mainfrom
cp-aspire
Open

Add sample Temporal integration for Aspire#127
cecilphillip wants to merge 4 commits into
mainfrom
cp-aspire

Conversation

@cecilphillip
Copy link
Copy Markdown

What was changed

This PR adds comprehensive .NET Aspire integration for Temporal, including:

  • Custom Aspire resource definitions for Temporal server deployment with three deployment models:

    • Local test server using Temporalio.Testing.WorkflowEnvironment
    • Container-based deployment using Docker
    • CLI-based server for environments without Docker
  • Temporal.Extensions.Aspire.Hosting library with:

    • Extension methods for adding Temporal resources to Aspire applications
    • Health check integration for Temporal connectivity
    • Automatic service discovery and environment variable injection
    • Resource lifecycle management (start/stop) via Aspire dashboard
    • Configurable options for ports, namespaces, search attributes, and dynamic config
  • Sample Aspire application demonstrating the integration:

    • TemporalioSamples.SampleAppHost - Aspire app host configuring Temporal resources
    • TemporalioSamples.SampleWorker - Worker service consuming workflows/activities
    • TemporalioSamples.SampleClient - Client triggering workflow execution
    • TemporalioSamples.SampleWorkflow - Simple workflow and activity definitions

@cecilphillip cecilphillip requested a review from a team as a code owner February 21, 2026 15:30
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 21, 2026

CLA assistant check
All committers have signed the CLA.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Comment thread src/AspireIntegrations/TemporalioSamples.SampleAppHost/AppHost.cs Outdated
Comment on lines +7 to +10
var connectOptions = ClientEnvConfig.LoadClientConnectOptions();
Console.WriteLine("\nAttempting to connect client to temporal server...");

var client = await TemporalClient.ConnectAsync(connectOptions);
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.

Aren't you supposed to be able to use Aspire to get client connectivity information too? Even if it is powered by env vars under the hood, one might expect a type-safe Aspire way to get a client or client options for the given "temporal" reference from other project.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Aspire only does that through environment variables. There isn't anything type-safe configuration support specifically from aspire. Typically library authors would create their own using Microsoft.Extensions.Configuration bindings

Copy link
Copy Markdown
Contributor

@cretz cretz Feb 23, 2026

Choose a reason for hiding this comment

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

I mean from a caller POV. For instance, stuff like https://aspire.dev/integrations/databases/postgres/postgres-get-started/?lang=csharp#use-the-integration-in-client-projects. I would expect that you can just put a client on the DI container w/ a single Aspire helper. Sure you can always still manually create clients.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I mean we could create an extension method that makes that a little nicer, but that would be a client specific library/package. From an aspire API perspective, they just inject configuration properties that get consumed .

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.

They inject configuration properties for those not wanting to use the helper, but they also provide a helper. I figure the nice aspect of "Aspire helper to make server, Aspire helper to make client" is valuable even though they can use the env vars directly of course, same as Postgres there.

@cecilphillip cecilphillip requested a review from cretz February 23, 2026 16:16
@cecilphillip cecilphillip requested review from Copilot and removed request for cretz May 21, 2026 18:26
Copy link
Copy Markdown

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

This PR adds a new Aspire integration sample set for Temporal and introduces a Temporal.Extensions.Aspire.Hosting library that defines Temporal resources (local dev server, Docker container, and Temporal CLI) with health checks and environment variable wiring for dependent projects.

Changes:

  • Added an Aspire sample AppHost + client/worker + workflow projects under src/AspireIntegrations.
  • Introduced Temporal.Extensions.Aspire.Hosting with custom Temporal resources, options, lifecycle subscriber, and health check extensions.
  • Added documentation and Aspire settings for running the new sample.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
TemporalioSamples.sln Adds the new Aspire integration projects into the solution under a new folder.
src/AspireIntegrations/TemporalioSamples.SampleWorkflow/TemporalioSamples.SampleWorkflow.csproj New workflow project for the Aspire sample.
src/AspireIntegrations/TemporalioSamples.SampleWorkflow/SimpleWorkflow.cs Sample workflow definition.
src/AspireIntegrations/TemporalioSamples.SampleWorkflow/SimpleActivities.cs Sample activity definition.
src/AspireIntegrations/TemporalioSamples.SampleWorker/TemporalioSamples.SampleWorker.csproj New worker project for the Aspire sample.
src/AspireIntegrations/TemporalioSamples.SampleWorker/Program.cs Configures and runs a hosted Temporal worker via env-configured connectivity.
src/AspireIntegrations/TemporalioSamples.SampleClient/TemporalioSamples.SampleClient.csproj New client project for the Aspire sample.
src/AspireIntegrations/TemporalioSamples.SampleClient/Program.cs Connects to Temporal and starts the sample workflow.
src/AspireIntegrations/TemporalioSamples.SampleAppHost/TemporalioSamples.SampleAppHost.csproj New Aspire AppHost project referencing the Temporal Aspire hosting library and sample projects.
src/AspireIntegrations/TemporalioSamples.SampleAppHost/Properties/launchSettings.json Launch profiles for the AppHost.
src/AspireIntegrations/TemporalioSamples.SampleAppHost/appsettings.json Logging configuration for AppHost.
src/AspireIntegrations/TemporalioSamples.SampleAppHost/appsettings.Development.json Development logging configuration for AppHost.
src/AspireIntegrations/TemporalioSamples.SampleAppHost/AppHost.cs Wires up the Temporal local dev server resource and references it from worker/client.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalResourceOptions.cs Adds Temporal resource options layered on Temporal’s local environment options.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalResourceConstants.cs Defines endpoint names, default ports, and image constants.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalLocalResourceSubscriber.cs Manages local dev server lifecycle (start on init, shutdown on stop).
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalLocalResourceExtensions.cs Adds AddTemporalLocalDevServer, endpoints, health checks, and dashboard commands.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalLocalResource.cs Resource model for the local dev server.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalHealthCheckBuilderExtensions.cs Adds health check registration helper for Temporal connectivity.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalHealthCheck.cs Implements the Temporal connectivity health check.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalContainerResource.cs Container-based Temporal resource + connection string expression.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalContainerOptions.cs Container-specific options (image tag) for Temporal.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalContainerBuilderExtensions.cs Adds Docker-based Temporal dev server resource and wiring helpers.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalCliServerResourceExtensions.cs Adds Temporal CLI-based server resource and wiring helpers.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/TemporalCliServerResource.cs Executable-based Temporal resource + connection string expression.
src/AspireIntegrations/Temporal.Extensions.Aspire.Hosting/Temporal.Extensions.Aspire.Hosting.csproj New hosting library project definition and dependencies.
src/AspireIntegrations/README.md Adds documentation for running/using the new Aspire integration and configuration options.
src/AspireIntegrations/.aspire/settings.json Points Aspire tooling at the new AppHost project.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
Comment on lines +20 to +23
public new List<string> AdditionalNamespaces
{
get => additionalNamespaces.Count > 0 ? additionalNamespaces : [Namespace];
set => additionalNamespaces = value ?? [];
Comment on lines +79 to +97
if (resource.WorkflowEnvironment != null)
{
resourceLogger.LogInformation("Shutting down Temporal test server '{ResourceName}'...", resource.Name);
await resource.WorkflowEnvironment.ShutdownAsync();
resource.WorkflowEnvironment = null;
resourceLogger.LogInformation("Temporal test server '{ResourceName}' shut down successfully.", resource.Name);
}

// Publish ResourceStoppedEvent to trigger subscriber cleanup and keep _environments dictionary in sync
var resourceEvent = new ResourceEvent(resource, resource.Name, new CustomResourceSnapshot
{
ResourceType = "temporal-local",
CreationTimeStamp = DateTime.UtcNow,
State = KnownResourceStates.Exited,
Properties = []
});
var stoppedEvent = new ResourceStoppedEvent(resource, context.ServiceProvider, resourceEvent);
await eventing.PublishAsync(stoppedEvent, context.CancellationToken);

{
try
{
await TemporalClient.ConnectAsync(clientConnectOptions);

public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"{PrimaryEndpoint.Property(EndpointProperty.Url)}");
Comment on lines +56 to +66
var builder = DistributedApplication.CreateBuilder(args);

// Add Temporal local server
var temporal = builder.AddTemporalLocalTestServer();

// Add a worker project that depends on Temporal
builder.AddProject<Projects.SampleWorker>("worker")
.WaitFor(temporal)
.WithReference(temporal);

builder.Build().Run();
Comment on lines +99 to +101
options.DynamicConfigValues = [
"persistence.cassandra.hosts = cassandra-host:9042"
];
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.

4 participants