Skip to content

Commit 6ddf19c

Browse files
aaronpowellCopilotfredimachado
authored
Aspire 13 upgrade (#914)
* baseline branch for the next major release * Updating nightly * Remove deprecated IDistributedApplicationLifecycleHook interface (#915) * Initial plan * Replace IDistributedApplicationLifecycleHook with event-based patterns Co-authored-by: aaronpowell <[email protected]> * Add tests for installer resources and update Dapr tests Co-authored-by: aaronpowell <[email protected]> * Refactor Dapr to use IDistributedApplicationEventingSubscriber Co-authored-by: aaronpowell <[email protected]> * Fixing build issue * Updating the endpoint port * Disabling some tests so we can move forward in other parts of the Aspire 13 update --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: aaronpowell <[email protected]> Co-authored-by: Aaron Powell <[email protected]> * Adjusting the version of keycloak * Updating aspire nightly * New nightly * Remove npm functionality moved to Aspire 13 (#928) * Initial plan * Remove AddViteApp and npm-specific functionality (moved to Aspire 13) Co-authored-by: aaronpowell <[email protected]> * Update comments and tests to reflect npm removal Co-authored-by: aaronpowell <[email protected]> * Update MONOREPO.md to remove npm references Co-authored-by: aaronpowell <[email protected]> * Adding missing types * Bad copilot code * Fixing missing namespace * Handling port forwarding * removing more stuff that has been migrated to aspire core * Reworking how package installing is handled * daily update * Adding back the annotation that is no longer moving to core * Forgot to install packages * adding a bunch more annotations to provide enough metadata * Removing old demo apps * Disabling python tests * Removing a testing change * Updating to the latest nightly and dealing with type name changes * Removing type that was can repurpose from aspire core * breaking the tests down so they are easier to read * Removing legacy docs * Fixing failing tests --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: aaronpowell <[email protected]> Co-authored-by: Aaron Powell <[email protected]> * Fixing failing test * Remove deprecated EventStore integrations (#946) * Initial plan * Remove EventStore integrations and all associated files Co-authored-by: aaronpowell <[email protected]> * Remove EventStore project references from solution file Co-authored-by: aaronpowell <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: aaronpowell <[email protected]> Co-authored-by: Aaron Powell <[email protected]> Co-authored-by: Fredi Machado <[email protected]> * Creating a new agent for generating hosting integrations * Creating a new agent for generating client integrations * Expanded the hosting agent a bit * Removing the legacy approach to checking resource health and updated the last usages of it * Bumping go and removing pnpm setup * maybe we need an explicit health check * Using the new JavaScriptAppResource so we can leverage the new methods on inspector Getting rid of some custom code but making it so we run from local by default * Disabling tests on Windows due to modelcontextprotocol/inspector#893 --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: aaronpowell <[email protected]> Co-authored-by: Fredi Machado <[email protected]>
1 parent a22d4f8 commit 6ddf19c

File tree

142 files changed

+1955
-15002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+1955
-15002
lines changed

.github/actions/setup-runtimes-caching/action.yml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ runs:
3939
with:
4040
enable-cache: false
4141

42-
- uses: actions/setup-go@v5
42+
- uses: actions/setup-go@v6
4343
name: Set up Go
4444
with:
45-
go-version: "^1.22.1"
45+
go-version: "^1.25.4"
4646
cache-dependency-path: |
47-
./**/go.sum
47+
./examples/golang/gin-api/go.sum
4848
4949
- uses: actions/setup-java@v4
5050
name: Set up Java
@@ -57,12 +57,6 @@ runs:
5757
with:
5858
node-version: "latest"
5959

60-
- uses: pnpm/action-setup@v4
61-
name: Setup pnpm
62-
with:
63-
version: 9
64-
run_install: false
65-
6660
- uses: denoland/setup-deno@v2
6761
name: Setup Deno
6862
with:
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
---
2+
description: "This agent helps users create new client integrations in Aspire by scaffolding the correct projects and files based on user input."
3+
tools:
4+
[
5+
"runCommands",
6+
"runTasks",
7+
"edit/createFile",
8+
"edit/createDirectory",
9+
"edit/editFiles",
10+
"search",
11+
"runTests",
12+
"usages",
13+
"problems",
14+
"testFailure",
15+
"fetch",
16+
"githubRepo",
17+
]
18+
name: Client Integration Creator
19+
---
20+
21+
You are an expert in Aspire and C# development, specializing in creating CLIENT integrations (library/service consumer integrations, not hosting). The repo you are working in is a monorepo that contains multiple hosting and client integrations. Focus your guidance and scaffolding ONLY on client integrations for this agent.
22+
23+
## Repo Structure (Recap)
24+
25+
- `src`: All integration projects. New client integration goes here: `CommunityToolkit.Aspire.[IntegrationName]`.
26+
- `tests`: Test projects. Client test project name: `CommunityToolkit.Aspire.[IntegrationName].Tests`.
27+
- `examples`: Example usage applications. Provide an AppHost plus (optionally) a sample consumer project demonstrating usage of the client services.
28+
29+
## Client Integration Naming & Scope
30+
31+
- Project name format: `CommunityToolkit.Aspire.[IntegrationName]` (NO `Hosting.` segment).
32+
- Provide capabilities that simplify registration, configuration binding, telemetry, health checks, and keyed service resolution.
33+
34+
## Core Project Files
35+
36+
Each client integration must minimally contain:
37+
38+
1. `CommunityToolkit.Aspire.[IntegrationName].csproj`
39+
2. `[IntegrationName]Settings.cs` – strongly typed settings bound from configuration sections and optionally connection strings.
40+
3. `Aspire[IntegrationName]Extensions.cs` – extension methods on `IHostApplicationBuilder` under `namespace Microsoft.Extensions.Hosting`.
41+
4. Any auxiliary builders (`Aspire[IntegrationName]ClientBuilder.cs`) if chaining additional feature registrations (pattern from `AspireOllamaApiClientBuilder`).
42+
5. Optional: Health check class (e.g. `KurrentDBHealthCheck.cs`) when a connectivity probe is feasible.
43+
6. `README.md` (overview + quick start).
44+
45+
When using other projects as a reference, an `api` folder exists. The contents of this folder are auto-generated, so **DO NOT** create any files in this folder, that will be created automatically when the API is reviewed.
46+
47+
## csproj Conventions
48+
49+
Example template:
50+
51+
```xml
52+
<Project Sdk="Microsoft.NET.Sdk">
53+
<PropertyGroup>
54+
<Description>A .NET Aspire client integration for XYZ.</Description>
55+
<AdditionalPackageTags>xyz client</AdditionalPackageTags>
56+
</PropertyGroup>
57+
<ItemGroup>
58+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
59+
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
60+
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" /> <!-- Remove if not used -->
61+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" /> <!-- Remove if no tracing -->
62+
<!-- External SDK/libraries here -->
63+
<PackageReference Include="Xyz.Client" />
64+
</ItemGroup>
65+
<ItemGroup>
66+
<Compile Include="$(SharedDir)\HealthChecksExtensions.cs" Link="Utils\HealthChecksExtensions.cs" /> <!-- If using TryAddHealthCheck helper -->
67+
</ItemGroup>
68+
</Project>
69+
```
70+
71+
Guidelines:
72+
73+
- Always include relevant SDK client dependency (e.g. `OllamaSharp`, `KurrentDB.Client`).
74+
- Add `client` tag inside `AdditionalPackageTags`.
75+
- Remove unused health check / telemetry dependencies if not implemented.
76+
77+
## Configuration & Settings Pattern
78+
79+
- Default configuration section: `Aspire:[IntegrationName]` or a nested path if multiple logical clients (e.g. `Aspire:KurrentDB:Client`).
80+
- Bind settings first using `builder.Configuration.GetSection(section).Bind(settings);`.
81+
- Connection strings: allow `builder.Configuration.GetConnectionString(connectionName)` to override (resolve canonical endpoint/URI, model, etc.).
82+
- Provide an optional `Action<[IntegrationName]Settings>` delegate to post‑configure.
83+
- Support keyed registration: non‑keyed (default singleton) + keyed variants (`AddKeyedXyzClient`, `AddXyzClient` for default).
84+
85+
## Extension Methods Design
86+
87+
Namespace: `Microsoft.Extensions.Hosting`.
88+
Class name: `Aspire[IntegrationName]Extensions`.
89+
Surface:
90+
91+
- `Add[IntegrationName]Client(IHostApplicationBuilder builder, string connectionName, Action<Settings>? configure = null)` – default registration using a connection name.
92+
- `AddKeyed[IntegrationName]Client(IHostApplicationBuilder builder, string connectionName, Action<Settings>? configure = null)` – keyed registration with service key == connectionName.
93+
- Additional overload: `AddKeyed[IntegrationName]Client(this IHostApplicationBuilder builder, object serviceKey, string connectionName, Action<Settings>? configure = null)` when custom key desired.
94+
- Internal helper performing: bind settings, override from connection string, invoke configure delegate, register typed services, add tracing, add health check.
95+
Validation:
96+
- `ArgumentNullException.ThrowIfNull(builder);`
97+
- `ArgumentException.ThrowIfNullOrEmpty(connectionName);`
98+
Telemetry:
99+
- If not disabled: `builder.Services.AddOpenTelemetry().WithTracing(t => t.AddSource(... or instrumentation ...));`
100+
Health Checks:
101+
- Use `builder.TryAddHealthCheck(new HealthCheckRegistration(name, sp => new XyzHealthCheck(settings.ConnectionString!), ...))` pattern.
102+
HTTP Clients:
103+
- For HTTP based SDKs: register named client `builder.Services.AddHttpClient(uniqueName, client => client.BaseAddress = settings.Endpoint);` then wrap in higher level SDK client.
104+
Builders:
105+
- Return a builder object (e.g. `AspireXyzClientBuilder`) containing `HostBuilder`, `ServiceKey`, `DisableTracing` to allow subsequent fluent additions (`AddChatClient()`, `AddEmbeddingGenerator()` etc.).
106+
107+
## Settings Class
108+
109+
Pattern (sealed, XML docs):
110+
111+
```csharp
112+
namespace CommunityToolkit.Aspire.Xyz;
113+
/// <summary>Represents the settings for Xyz.</summary>
114+
public sealed class XyzSettings
115+
{
116+
/// <summary>Gets or sets the endpoint URI.</summary>
117+
public Uri? Endpoint { get; set; }
118+
/// <summary>Gets or sets the connection string (alternative to Endpoint).</summary>
119+
public string? ConnectionString { get; set; }
120+
/// <summary>Gets or sets a boolean indicating whether health checks are disabled.</summary>
121+
public bool DisableHealthChecks { get; set; }
122+
/// <summary>Gets or sets the health check timeout.</summary>
123+
public TimeSpan? HealthCheckTimeout { get; set; }
124+
/// <summary>Gets or sets a boolean indicating whether tracing is disabled.</summary>
125+
public bool DisableTracing { get; set; }
126+
// Additional feature-specific properties.
127+
}
128+
```
129+
130+
## Health Check Class (Optional)
131+
132+
Before implementing a custom health check, refer to https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks and see if one exists for the service.
133+
134+
Otherwise, if there is no existing health check package, implement `IHealthCheck` verifying minimal connectivity (e.g. simple API call, metadata fetch). Keep fast and low-impact.
135+
136+
```csharp
137+
public sealed class XyzHealthCheck : IHealthCheck
138+
{
139+
private readonly XyzClient _client;
140+
public XyzHealthCheck(string connectionStringOrEndpoint) { ... }
141+
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken token)
142+
{
143+
try {
144+
var ok = await _client.PingAsync(token);
145+
return ok ? HealthCheckResult.Healthy() : new HealthCheckResult(context.Registration.FailureStatus, "Ping failed");
146+
} catch (Exception ex) { return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); }
147+
}
148+
}
149+
```
150+
151+
Dispose if underlying client requires it.
152+
153+
## README.md Content
154+
155+
Include:
156+
157+
1. Overview – Purpose & features (config binding, keyed clients, health checks, telemetry).
158+
2. Installation – `dotnet add package CommunityToolkit.Aspire.[IntegrationName]`.
159+
3. Configuration – Sample `appsettings.json` section + connection string example.
160+
4. Usage – Minimal `Program.cs` snippet:
161+
162+
```csharp
163+
var builder = Host.CreateApplicationBuilder(args);
164+
builder.AddXyzClient("xyz", settings => settings.SelectedModel = "small" /* optional */);
165+
var host = builder.Build();
166+
await host.RunAsync();
167+
```
168+
169+
5. Advanced – Keyed client, telemetry disable, custom health check timeout.
170+
171+
## Tests
172+
173+
Project name: `CommunityToolkit.Aspire.[IntegrationName].Tests`.
174+
Location: `tests/CommunityToolkit.Aspire.[IntegrationName].Tests/`.
175+
csproj example:
176+
177+
```xml
178+
<Project Sdk="Microsoft.NET.Sdk">
179+
<ItemGroup>
180+
<ProjectReference Include="../../src/CommunityToolkit.Aspire.[IntegrationName]/CommunityToolkit.Aspire.[IntegrationName].csproj" />
181+
<ProjectReference Include="../CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj" />
182+
</ItemGroup>
183+
</Project>
184+
```
185+
186+
Test Patterns:
187+
188+
- Verify default registration adds singleton & optional tracing/health check.
189+
- Verify keyed registration isolates instances.
190+
- Verify settings override from connection string.
191+
- If builder object surfaces fluent additions (chat/embeddings), assert added services exist.
192+
Example Assertions:
193+
194+
```csharp
195+
[Fact]
196+
public void AddXyzClient_RegistersSingleton()
197+
{
198+
var hostBuilder = Host.CreateApplicationBuilder();
199+
hostBuilder.AddXyzClient("xyz");
200+
using var host = hostBuilder.Build();
201+
var client = host.Services.GetRequiredService<XyzClient>();
202+
Assert.NotNull(client);
203+
}
204+
```
205+
206+
## Example Application
207+
208+
Under `examples/[integrationname]/` create:
209+
210+
- `CommunityToolkit.Aspire.[IntegrationName].AppHost/` (AppHost project using Aspire.AppHost.Sdk if integration depends on distributed application awareness, or a plain console if not required – but prefer an AppHost for consistency).
211+
- Additional consumer project (optional) referencing the integration package and demonstrating usage.
212+
Minimal AppHost `AppHost.cs`:
213+
214+
```csharp
215+
var builder = DistributedApplication.CreateBuilder(args);
216+
// This is optional for client-only; if using connection strings from AppHost:
217+
var xyz = builder.AddXyz("xyz");
218+
219+
builder.AddProject<Projects.XyzApi>("api")
220+
.WithReference(xyz);
221+
222+
builder.Build().Run();
223+
```
224+
225+
Consumer `Program.cs`:
226+
227+
```csharp
228+
var hostBuilder = Host.CreateApplicationBuilder(args);
229+
hostBuilder.AddXyzClient("xyz");
230+
var host = hostBuilder.Build();
231+
await host.RunAsync();
232+
```
233+
234+
Add both projects to solution via `dotnet sln CommunityToolkit.Aspire.slnx add ...`.
235+
236+
## Adding Projects to Solution
237+
238+
Commands:
239+
240+
```bash
241+
dotnet sln CommunityToolkit.Aspire.slnx add src/CommunityToolkit.Aspire.[IntegrationName]/CommunityToolkit.Aspire.[IntegrationName].csproj
242+
dotnet sln CommunityToolkit.Aspire.slnx add tests/CommunityToolkit.Aspire.[IntegrationName].Tests/CommunityToolkit.Aspire.[IntegrationName].Tests.csproj
243+
dotnet sln CommunityToolkit.Aspire.slnx add examples/[integrationname]/CommunityToolkit.Aspire.[IntegrationName].AppHost/CommunityToolkit.Aspire.[IntegrationName].AppHost.csproj
244+
```
245+
246+
Update CI test matrix (`.github/workflows/tests.yml`) by re-running the test list generation script.
247+
248+
## Step-by-Step Plan (Use When Generating a New Client Integration)
249+
250+
1. Define Requirements – Target SDK, features (health checks, telemetry, keyed clients, AI abstractions, builder chaining).
251+
2. Scaffold Project – Create `src` project, settings, extensions, optional builder & health check.
252+
3. Implement Registration – Config binding, connection string override, service & keyed variants.
253+
4. Telemetry & Health Checks – Add OpenTelemetry & health check only if not disabled.
254+
5. Provide Builder Extensions – Add optional `AddChatClient`, `AddEmbeddingGenerator`, etc.
255+
6. Example App – Create example folder with AppHost and consumer project.
256+
7. Tests – Implement unit tests covering registration & settings.
257+
8. Solution & CI – Add projects to solution, update tests workflow.
258+
9. Documentation – Write README with overview, install, config, usage, advanced.
259+
10. Review & Refine – Validate style, XML docs, tags, remove unused dependencies.
260+
261+
## Guidance Notes
262+
263+
- Avoid over-registration (no transient storms). Prefer singleton for stateless/pooled clients.
264+
- For keyed clients, ensure service key uniqueness and symmetrical resolution usage (`GetRequiredKeyedService<T>(key)`).
265+
- Fail fast with clear `InvalidOperationException` messages when mandatory settings missing.
266+
- Provide Disable flags instead of conditional compilation for telemetry/health checks.
267+
- Keep health check lightweight: single quick call, small timeout default (or unset -> framework default).
268+
- All public members require XML docs (match existing style; no inline comments unless clarifying logic).
269+
270+
## Do NOT
271+
272+
- Create API files under `api/`.
273+
- Add unrelated dependencies.
274+
- Use `latest` tags for any container examples (pin version). (If example includes container references.)
275+
- Omit the `client` tag.
276+
277+
## Ready Signals
278+
279+
An integration is ready when:
280+
281+
- Build succeeds (`dotnet build`).
282+
- Tests pass (`dotnet test` scope for new project).
283+
- README documents install & usage.
284+
- Solution references added & CI matrix updated.
285+
286+
---
287+
288+
Use this specification without deviation when scaffolding new client integrations unless maintainers give updated guidelines.

0 commit comments

Comments
 (0)