Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
df058ca
exec setup
DeagleGross Jun 18, 2025
9462552
more setup
DeagleGross Jun 18, 2025
3391051
impl
DeagleGross Jun 19, 2025
d467001
tests
DeagleGross Jun 19, 2025
56c0434
setup RPC logs?
DeagleGross Jun 19, 2025
ca8d4f4
wip
DeagleGross Jun 23, 2025
9eb9317
does not work
DeagleGross Jun 23, 2025
7a65ce3
move
DeagleGross Jun 24, 2025
16ec8e0
ok it worked
DeagleGross Jun 24, 2025
0b755f2
wip
DeagleGross Jun 24, 2025
fd4884f
taking annotations and starting resource
DeagleGross Jun 25, 2025
ebb80c6
not working -_-
DeagleGross Jun 25, 2025
ded6f79
thanks Damian!!!
DeagleGross Jun 25, 2025
520159d
prettify
DeagleGross Jun 26, 2025
9451545
pass down options
DeagleGross Jun 26, 2025
3a2c5e3
try with cli
DeagleGross Jun 26, 2025
c25be00
no keepalive in command
DeagleGross Jun 26, 2025
3f2ed39
merge main & resolve conflicts
DeagleGross Jun 26, 2025
656f4c2
fix conflicts
DeagleGross Jun 26, 2025
3906abf
fix build
DeagleGross Jun 26, 2025
4a7dc36
fix serialization + annotations
DeagleGross Jun 26, 2025
9ca1c48
prettify the messages based on the state
DeagleGross Jun 26, 2025
c4048a9
localize the command
DeagleGross Jun 26, 2025
1d9a507
resources
DeagleGross Jun 26, 2025
d3ae369
e2e tests
DeagleGross Jun 26, 2025
fd3a92b
generate unit tests
DeagleGross Jun 26, 2025
b61f6bd
remove unused
DeagleGross Jun 26, 2025
d4084ec
not hang on no command and target resource
DeagleGross Jun 26, 2025
d1f092d
messages
DeagleGross Jun 26, 2025
8c8ca3a
rollback testing app host / retarget tetsts against databasemigration…
DeagleGross Jun 27, 2025
154c92c
address PR comments 1
DeagleGross Jun 27, 2025
d59b76d
merge main & resolve
DeagleGross Jun 27, 2025
065dda6
fix merge
DeagleGross Jun 27, 2025
5d1d40a
fix AOT
DeagleGross Jun 27, 2025
ef0d519
use postgres because its faster
DeagleGross Jun 27, 2025
02576bd
hide under exec
DeagleGross Jun 27, 2025
7100766
install dotnet ef for agents
DeagleGross Jun 27, 2025
0ffe730
provider is required on the api model?
DeagleGross Jun 27, 2025
2d578c7
add tools to resolve GetEFProjectMetadata
DeagleGross Jun 27, 2025
547f270
try with msbuildprojectextensionspath
DeagleGross Jun 27, 2025
4aa3e6d
merge main
DeagleGross Jun 30, 2025
5e807e0
fix build
DeagleGross Jun 30, 2025
aca3572
try diff arg
DeagleGross Jun 30, 2025
7144255
try with build before
DeagleGross Jun 30, 2025
b5a782f
rollback & try build the playground before
DeagleGross Jun 30, 2025
1fb877c
try build apimodel
DeagleGross Jun 30, 2025
3fef32b
add a step to check the obj
DeagleGross Jun 30, 2025
1b4da66
list more
DeagleGross Jun 30, 2025
806e0ca
unblock
DeagleGross Jun 30, 2025
3560e5e
merge main...
DeagleGross Jul 1, 2025
bba4642
remove keep-alive/ fix build
DeagleGross Jul 1, 2025
63be8d4
remove hardcode for "exec"
DeagleGross Jul 1, 2025
21048aa
address another PR commments
DeagleGross Jul 1, 2025
4369ca3
merge main
DeagleGross Jul 1, 2025
04c52e7
merge main
DeagleGross Jul 2, 2025
fb11c28
fix build
DeagleGross Jul 2, 2025
66533ca
address PR comments 1
DeagleGross Jul 2, 2025
637667b
address PR comments 2
DeagleGross Jul 2, 2025
5c78af7
place it differently
DeagleGross Jul 2, 2025
b88ab0b
address PR comments x10
DeagleGross Jul 2, 2025
840a888
merge main
DeagleGross Jul 2, 2025
95fd77e
debug assert for command
DeagleGross Jul 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" />

<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("ProductVersion", "8.0.17")
.HasAnnotation("Relational:MaxIdentifierLength", 128);

SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
Expand All @@ -27,6 +27,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");

b.Property<long>("Version")
.HasColumnType("bigint");

b.HasKey("Id");

b.ToTable("Entries");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public class MyDb1Context(DbContextOptions<MyDb1Context> options) : DbContext(op
public class Entry
{
public Guid Id { get; set; } = Guid.NewGuid();

public long Version { get; set; } = 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<AspireProjectOrPackageReference Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" />
<ProjectReference Include="..\..\Playground.ServiceDefaults\Playground.ServiceDefaults.csproj" />
<ProjectReference Include="..\DatabaseMigration.ApiModel\DatabaseMigration.ApiModel.csproj" />
</ItemGroup>

<ItemGroup>
<AspireProjectOrPackageReference Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@

builder.AddServiceDefaults();

builder.AddSqlServerDbContext<MyDb1Context>("db1", configureDbContextOptions: options =>
if (args.Contains("--postgres"))
{
options.UseSqlServer(sqlServerOptions =>
builder.Services.AddDbContextPool<MyDb1Context>(options =>
{
sqlServerOptions.MigrationsAssembly("DatabaseMigration.ApiModel");
var connectionString = builder.Configuration.GetConnectionString("db1");
options.UseNpgsql(connectionString, options =>
{
options.MigrationsAssembly("DatabaseMigration.ApiModel");
});
});
});
}
else
{
builder.AddSqlServerDbContext<MyDb1Context>("db1", configureDbContextOptions: options =>
{
options.UseSqlServer(sqlServerOptions =>
{
sqlServerOptions.MigrationsAssembly("DatabaseMigration.ApiModel");
});
});
}

var app = builder.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<ItemGroup>
<AspireProjectOrPackageReference Include="Aspire.Hosting.AppHost" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.SqlServer" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.PostgreSQL" />
<AspireProjectOrPackageReference Include="Aspire.Hosting.MySql" />

<ProjectReference Include="..\DatabaseMigration.ApiService\DatabaseMigration.ApiService.csproj" />
<ProjectReference Include="..\DatabaseMigration.MigrationService\DatabaseMigration.MigrationService.csproj" />
Expand Down
15 changes: 12 additions & 3 deletions playground/DatabaseMigration/DatabaseMigration.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@

var builder = DistributedApplication.CreateBuilder(args);

var db1 = builder.AddSqlServer("sql1").AddDatabase("db1");
IResourceBuilder<IResourceWithConnectionString> database;

if (args.Contains("--postgres"))
{
database = builder.AddPostgres("sql1").AddDatabase("db1");
}
else
{
database = builder.AddSqlServer("sql1").AddDatabase("db1");
}

builder.AddProject<Projects.DatabaseMigration_ApiService>("api")
.WithExternalHttpEndpoints()
.WithReference(db1);
.WithReference(database);

builder.AddProject<Projects.DatabaseMigration_MigrationService>("migration")
.WithReference(db1);
.WithReference(database);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
Expand Down
9 changes: 9 additions & 0 deletions src/Aspire.Cli/Aspire.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
</ItemGroup>

<ItemGroup>
<Compile Update="Resources\ExecCommandStrings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ExecCommandStrings.resx</DependentUpon>
</Compile>
<Compile Update="Resources\InteractionServiceStrings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand Down Expand Up @@ -108,6 +113,10 @@
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Resources\ExecCommandStrings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ExecCommandStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\InteractionServiceStrings.resx">
<XlfSourceFormat>Resx</XlfSourceFormat>
<XlfOutputItem>EmbeddedResource</XlfOutputItem>
Expand Down
43 changes: 27 additions & 16 deletions src/Aspire.Cli/Backchannel/AppHostBackchannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal interface IAppHostBackchannel
IAsyncEnumerable<PublishingActivity> GetPublishingActivitiesAsync(CancellationToken cancellationToken);
Task<string[]> GetCapabilitiesAsync(CancellationToken cancellationToken);
Task CompletePromptResponseAsync(string promptId, string?[] answers, CancellationToken cancellationToken);
IAsyncEnumerable<CommandOutput> ExecAsync(CancellationToken cancellationToken);
}

internal sealed class AppHostBackchannel(ILogger<AppHostBackchannel> logger, AspireCliTelemetry telemetry) : IAppHostBackchannel
Expand All @@ -32,8 +33,7 @@ internal sealed class AppHostBackchannel(ILogger<AppHostBackchannel> logger, Asp
public async Task<long> PingAsync(long timestamp, CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Sent ping with timestamp {Timestamp}", timestamp);

Expand All @@ -52,8 +52,7 @@ public async Task RequestStopAsync(CancellationToken cancellationToken)
// which will allow the CLI to await the pending run.

using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting stop");

Expand All @@ -66,8 +65,7 @@ await rpc.InvokeWithCancellationAsync(
public async Task<(string BaseUrlWithLoginToken, string? CodespacesUrlWithLoginToken)> GetDashboardUrlsAsync(CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting dashboard URL");

Expand All @@ -82,8 +80,7 @@ await rpc.InvokeWithCancellationAsync(
public async IAsyncEnumerable<BackchannelLogEntry> GetAppHostLogEntriesAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting AppHost log entries");

Expand All @@ -103,8 +100,7 @@ public async IAsyncEnumerable<BackchannelLogEntry> GetAppHostLogEntriesAsync([En
public async IAsyncEnumerable<RpcResourceState> GetResourceStatesAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting resource states");

Expand Down Expand Up @@ -170,8 +166,7 @@ public async Task ConnectAsync(string socketPath, CancellationToken cancellation
public async IAsyncEnumerable<PublishingActivity> GetPublishingActivitiesAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task;
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting publishing activities.");

Expand All @@ -191,8 +186,7 @@ public async IAsyncEnumerable<PublishingActivity> GetPublishingActivitiesAsync([
public async Task<string[]> GetCapabilitiesAsync(CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task.ConfigureAwait(false);
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting capabilities");

Expand All @@ -207,8 +201,7 @@ public async Task<string[]> GetCapabilitiesAsync(CancellationToken cancellationT
public async Task CompletePromptResponseAsync(string promptId, string?[] answers, CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();

var rpc = await _rpcTaskCompletionSource.Task.ConfigureAwait(false);
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Providing prompt responses for prompt ID {PromptId}", promptId);

Expand All @@ -217,5 +210,23 @@ await rpc.InvokeWithCancellationAsync(
[promptId, answers],
cancellationToken).ConfigureAwait(false);
}

public async IAsyncEnumerable<CommandOutput> ExecAsync([EnumeratorCancellation] CancellationToken cancellationToken)
{
using var activity = telemetry.ActivitySource.StartActivity();
var rpc = await _rpcTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false);

logger.LogDebug("Requesting execution.");
var commandOutputs = await rpc.InvokeWithCancellationAsync<IAsyncEnumerable<CommandOutput>>(
"ExecAsync",
Array.Empty<object>(),
cancellationToken);

logger.LogDebug("Requested execution.");
await foreach (var commandOutput in commandOutputs.WithCancellation(cancellationToken))
{
yield return commandOutput;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace Aspire.Cli.Backchannel;
[JsonSerializable(typeof(RequestId))]
[JsonSerializable(typeof(IEnumerable<DisplayLineState>))]
[JsonSerializable(typeof(ValidationResult))]
[JsonSerializable(typeof(IAsyncEnumerable<CommandOutput>))]
[JsonSerializable(typeof(MessageFormatterEnumerableTracker.EnumeratorResults<CommandOutput>))]
internal partial class BackchannelJsonSerializerContext : JsonSerializerContext
{
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Using the Json source generator.")]
Expand Down
Loading