From c9022a52dde540d79d57098fb56057760adcbe9e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 04:10:14 +0000
Subject: [PATCH 1/2] Initial plan
From 475f9e0a3f698a93d9e7688412a4c6058f7157ea Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Feb 2026 04:25:38 +0000
Subject: [PATCH 2/2] Create comprehensive Aspire 13.x migration guide
Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
---
.../src/content/docs/whats-new/aspire-13.mdx | 261 ++++++++++++++++--
1 file changed, 239 insertions(+), 22 deletions(-)
diff --git a/src/frontend/src/content/docs/whats-new/aspire-13.mdx b/src/frontend/src/content/docs/whats-new/aspire-13.mdx
index 613b8960..eb6a5503 100644
--- a/src/frontend/src/content/docs/whats-new/aspire-13.mdx
+++ b/src/frontend/src/content/docs/whats-new/aspire-13.mdx
@@ -1655,36 +1655,140 @@ var app = builder.AddNodeApp("frontend", "../frontend", "server.js")
### Migration guide
-#### Migrating from publishing callbacks to pipeline steps
+This comprehensive guide helps you migrate from Aspire 9.x to 13.x, covering all breaking changes across 13.0 and 13.1 releases.
-**Before (9.x)**:
+#### Quick migration checklist
+
+Follow these steps to migrate your Aspire 9.x application to 13.x:
+
+
+
+1. **Update the Aspire CLI** to version 13.x:
+
+
+
+
+
+2. **Update your Aspire packages** using the CLI:
+ ```bash
+ aspire update
+ ```
+
+3. **Update package references** - rename `Aspire.Hosting.NodeJs` to `Aspire.Hosting.JavaScript`
+
+4. **Migrate JavaScript APIs** - replace `AddNpmApp()` with `AddJavaScriptApp()` and update `AddNodeApp()` signatures
+
+5. **Migrate lifecycle hooks** - replace `IDistributedApplicationLifecycleHook` with `IDistributedApplicationEventingSubscriber`
+
+6. **Migrate publishing callbacks** - replace `WithPublishingCallback()` with `WithPipelineStepFactory()`
+
+7. **Update connection properties** (13.1) - rename `Model` to `ModelName` and `Database` to `DatabaseName` where applicable
+
+8. **Update Azure Redis** (13.1) - replace `AddAzureRedisEnterprise()` with `AddAzureManagedRedis()`
+
+9. **Review behavioral changes** - check `EndpointReference.GetValueAsync()` usage for waiting behavior
+
+10. **Test your application** thoroughly to ensure all changes work as expected
+
+
+
+#### Migrating package references
+
+The `Aspire.Hosting.NodeJs` package has been renamed to `Aspire.Hosting.JavaScript` to reflect broader JavaScript application support.
+
+**Update your project file:**
+
+```xml
+
+
+
+
+
+```
+
+**Using the CLI:**
+
+```bash
+# Before (9.x)
+aspire add nodejs
+
+# After (13.0)
+aspire add javascript
+```
+
+The `aspire update` command automatically handles this migration.
+
+#### Migrating JavaScript APIs
+
+##### AddNpmApp → AddJavaScriptApp
+
+The `AddNpmApp()` method has been removed. Use `AddJavaScriptApp()` with `WithRunScript()` instead:
+
+**Before (9.x):**
```csharp
-var api = builder.AddProject("api")
- .WithPublishingCallback(async (context, cancellationToken) =>
- {
- await CustomDeployAsync(context, cancellationToken);
- });
+builder.AddNpmApp("frontend", "../frontend", scriptName: "dev");
```
-**After (13.0)**:
+**After (13.0):**
```csharp
-var api = builder.AddProject("api")
- .WithPipelineStepFactory(context =>
- {
- return new PipelineStep()
- {
- Name = "CustomDeployStep",
- Action = CustomDeployAsync,
- RequiredBySteps = [WellKnownPipelineSteps.Publish]
- };
- });
+builder.AddJavaScriptApp("frontend", "../frontend")
+ .WithRunScript("dev");
```
-For more details, see [Deployment pipeline documentation](/get-started/pipelines/).
+
+
+##### AddNodeApp signature changes
+
+The `AddNodeApp()` API has been refactored with a new signature that uses `appDirectory` with a relative `scriptPath`:
+
+**Before (9.x):**
+```csharp
+// Absolute scriptPath with optional workingDirectory
+builder.AddNodeApp(
+ name: "frontend",
+ scriptPath: "/absolute/path/to/app.js",
+ workingDirectory: "/absolute/path/to",
+ args: ["--port", "3000"]);
+```
+
+**After (13.0):**
+```csharp
+// appDirectory with relative scriptPath
+builder.AddNodeApp(
+ name: "frontend",
+ appDirectory: "../frontend",
+ scriptPath: "app.js");
+```
+
+**Key changes:**
+
+- **First parameter changed**: `scriptPath` (absolute) → `appDirectory` (relative to AppHost)
+- **Second parameter changed**: `workingDirectory` (optional) → `scriptPath` (relative to appDirectory)
+- **Automatic npm integration**: If `package.json` exists in `appDirectory`, npm is automatically configured
+- **Package manager flexibility**: Use `WithNpm()`, `WithYarn()`, or `WithPnpm()` with `WithRunScript()` to execute scripts
+
+**Migration example:**
+
+```csharp
+// Before (9.x)
+var app = builder.AddNodeApp("frontend", "../frontend/server.js", "../frontend");
+
+// After (13.0) - Option 1: Direct script execution
+var app = builder.AddNodeApp("frontend", "../frontend", "server.js");
+
+// After (13.0) - Option 2: Using package.json script
+var app = builder.AddNodeApp("frontend", "../frontend", "server.js")
+ .WithNpm()
+ .WithRunScript("dev");
+```
+
+#### Migrating lifecycle hooks to events
-#### Migrating from lifecycle hooks to events
+Lifecycle hooks have been replaced with an eventing system that provides more flexibility and better async support.
-**Before (9.x)**:
+**Before (9.x):**
```csharp
public class MyLifecycleHook : IDistributedApplicationLifecycleHook
{
@@ -1699,7 +1803,7 @@ public class MyLifecycleHook : IDistributedApplicationLifecycleHook
builder.Services.TryAddLifecycleHook();
```
-**After (13.0)**:
+**After (13.0):**
```csharp
public class MyEventSubscriber : IDistributedApplicationEventingSubscriber
{
@@ -1726,6 +1830,119 @@ public class MyEventSubscriber : IDistributedApplicationEventingSubscriber
builder.Services.TryAddEventingSubscriber();
```
+**Event equivalents for lifecycle hooks:**
+
+| 9.x Lifecycle Hook | 13.0 Event |
+|-------------------|-----------|
+| `BeforeStartAsync()` | `BeforeStartEvent` |
+| `AfterEndpointsAllocatedAsync()` | `AfterEndpointsAllocatedEvent` |
+| `AfterResourcesCreatedAsync()` | `AfterResourcesCreatedEvent` |
+
+#### Migrating publishing callbacks to pipeline steps
+
+Publishing callbacks have been replaced with a more powerful pipeline step system through the `aspire do` command.
+
+**Before (9.x):**
+```csharp
+var api = builder.AddProject("api")
+ .WithPublishingCallback(async (context, cancellationToken) =>
+ {
+ await CustomDeployAsync(context, cancellationToken);
+ });
+```
+
+**After (13.0):**
+```csharp
+var api = builder.AddProject("api")
+ .WithPipelineStepFactory(context =>
+ {
+ return new PipelineStep()
+ {
+ Name = "CustomDeployStep",
+ Action = CustomDeployAsync,
+ RequiredBySteps = [WellKnownPipelineSteps.Publish]
+ };
+ });
+```
+
+For more details, see [Deployment pipeline documentation](/get-started/pipelines/).
+
+#### Migrating connection properties (13.1)
+
+Aspire 13.1 renamed several connection properties for consistency across resources. If your client applications reference these properties via environment variables, update them accordingly.
+
+| Resource | Old Property | New Property | Environment Variable Change |
+|----------|-------------|--------------|---------------------------|
+| GitHub Models | `Model` | `ModelName` | `{NAME}_MODEL` → `{NAME}_MODELNAME` |
+| OpenAI model | `Model` | `ModelName` | `{NAME}_MODEL` → `{NAME}_MODELNAME` |
+| Milvus database | `Database` | `DatabaseName` | `{NAME}_DATABASE` → `{NAME}_DATABASENAME` |
+| MongoDB database | `Database` | `DatabaseName` | `{NAME}_DATABASE` → `{NAME}_DATABASENAME` |
+| MySQL database | `Database` | `DatabaseName` | `{NAME}_DATABASE` → `{NAME}_DATABASENAME` |
+| Oracle database | `Database` | `DatabaseName` | `{NAME}_DATABASE` → `{NAME}_DATABASENAME` |
+
+**Example:**
+
+```csharp
+// Before (13.0) - Environment variable: CHAT_MODEL
+var chat = builder.AddGitHubModels("chat");
+
+// After (13.1) - Environment variable: CHAT_MODELNAME
+// No code change needed in AppHost, but client apps must update environment variable references
+var chat = builder.AddGitHubModels("chat");
+```
+
+In your client application:
+
+```csharp
+// Before (13.0)
+var modelName = configuration["CHAT_MODEL"];
+
+// After (13.1)
+var modelName = configuration["CHAT_MODELNAME"];
+```
+
+#### Migrating Azure Redis (13.1)
+
+The Azure Redis API has been renamed to align with Azure service naming conventions.
+
+**Before (13.0):**
+```csharp
+var cache = builder.AddAzureRedisEnterprise("cache");
+```
+
+**After (13.1):**
+```csharp
+var cache = builder.AddAzureManagedRedis("cache");
+```
+
+
+
+#### Behavioral changes
+
+##### EndpointReference.GetValueAsync now waits for allocation
+
+In Aspire 9.x, `EndpointReference.GetValueAsync()` would throw immediately if the endpoint wasn't allocated. In 13.0, it waits for allocation to complete.
+
+**Before (9.x):**
+```csharp
+// Would throw immediately if not allocated
+var value = await endpointRef.GetValueAsync(cancellationToken);
+```
+
+**After (13.0):**
+```csharp
+// Now waits for allocation - check IsAllocated if you need immediate failure
+if (!endpointRef.IsAllocated)
+{
+ throw new InvalidOperationException("Endpoint not allocated");
+}
+var value = await endpointRef.GetValueAsync(cancellationToken);
+```
+
+This change enables more flexible async workflows where you can wait for resources to be ready rather than polling or handling exceptions.
+
### Experimental features
The following features are marked as `[Experimental]` and may change in future releases: