KoalaSoft.Aspire.Hosting.ServiceSources
0.2.0
See the version list below for details.
dotnet add package KoalaSoft.Aspire.Hosting.ServiceSources --version 0.2.0
NuGet\Install-Package KoalaSoft.Aspire.Hosting.ServiceSources -Version 0.2.0
<PackageReference Include="KoalaSoft.Aspire.Hosting.ServiceSources" Version="0.2.0" />
<PackageVersion Include="KoalaSoft.Aspire.Hosting.ServiceSources" Version="0.2.0" />
<PackageReference Include="KoalaSoft.Aspire.Hosting.ServiceSources" />
paket add KoalaSoft.Aspire.Hosting.ServiceSources --version 0.2.0
#r "nuget: KoalaSoft.Aspire.Hosting.ServiceSources, 0.2.0"
#:package KoalaSoft.Aspire.Hosting.ServiceSources@0.2.0
#addin nuget:?package=KoalaSoft.Aspire.Hosting.ServiceSources&version=0.2.0
#tool nuget:?package=KoalaSoft.Aspire.Hosting.ServiceSources&version=0.2.0
Aspire.Hosting.ServiceSources
A .NET Aspire AppHost extension that lets builder.AddService("orders") resolve to a real,
running resource whose source is chosen per developer, not baked into the AppHost.
Why
AddProject<T>() assumes a service lives in the AppHost's own solution. In a real
microservice environment, services live in separate repositories, and different developers
want different things for the same service: clone it locally to edit, run it from an
already-checked-out working copy, reach an instance already running in a shared Kubernetes
dev cluster, hit a fixed URL, or just run a published container image. The AppHost should
only describe what it depends on; where that dependency actually comes from is a
per-developer choice, made without ever touching the AppHost's .csproj/.sln.
AddService() is the seam: the AppHost calls it once per service, and a developer-local
config file decides how it's actually resolved — a managed or self-managed local git
checkout ("local"), a kubectl port-forward against a dev cluster ("kubernetes"), a
fixed, already-known URL ("url"), or a published container image run locally
("container") — behind one stable return type, so the AppHost code never has to change
when a developer switches sources.
Install
Published on nuget.org as KoalaSoft.Aspire.Hosting.ServiceSources:
dotnet add package KoalaSoft.Aspire.Hosting.ServiceSources
Or reference the project directly from your AppHost instead:
<ItemGroup>
<ProjectReference Include="path/to/Aspire.Hosting.ServiceSources/Aspire.Hosting.ServiceSources.csproj" />
</ItemGroup>
Requires .NET 8 or later (net8.0, net9.0, and net10.0 are all supported) and an AppHost
project using the Aspire.AppHost.Sdk (aspire new / aspire restore sets this up).
Getting started
1. Declare the service in Program.cs:
using Aspire.Hosting.ServiceSources;
var builder = DistributedApplication.CreateBuilder(args);
var orders = builder.AddService("orders");
var api = builder.AddProject<Projects.Api>("api")
.WithReference(orders);
builder.Build().Run();
2. Add the shared catalog, servicesources.yaml, next to the AppHost project (commit this
file):
services:
orders:
repository: https://github.com/example/orders
project: src/Orders.Api/Orders.Api.csproj
defaultRef: main # optional; branch, tag, or commit SHA
3. Add your own servicesources.local.json next to it (gitignore this file — it's
per-developer):
{
"services": {
"orders": { "source": "local" }
}
}
That's it — running the AppHost now clones orders into
<AppHostDirectory>/.servicesources/checkouts/orders/, checks out main, and runs it via
Aspire's own project orchestration, wired up to api through service discovery exactly like
a project reference would be.
"local" source options
{
"services": {
"orders": { "source": "local" },
"payments": {
"source": "local",
"path": "/home/dev/code/payments",
"ref": "feature/new-checkout"
}
}
}
- Omit
pathfor a managed checkout: cloned once into<AppHostDirectory>/.servicesources/checkouts/<serviceName>/, and reconciled to the configuredref(or the catalog'sdefaultRef) on every run. Uncommitted edits are never discarded — if the checkout is dirty and the ref changed, resolution fails loudly instead of overwriting your work. The.servicesources/directory gitignores itself on first use — no need to add it to your own.gitignore. - Set
pathto point at a checkout you manage yourself (e.g. an existing local clone). It's used as-is — no clone, no checkout, no fetch, ever.refcannot be combined withpath.
"kubernetes" source
Point a service at an already-running instance in a Kubernetes dev cluster via
kubectl port-forward, instead of running it locally at all.
servicesources.yaml:
services:
orders:
kubernetes:
service: orders-svc
port: 8080
servicesources.local.json:
{
"services": {
"orders": {
"source": "kubernetes",
"context": "dev-west",
"namespace": "orders",
"port": 8080
}
}
}
Requires kubectl on PATH, authenticated against the named context.
"url" source
Point a service at a fixed, already-known URL — e.g. a Kubernetes ingress, a staging deployment, or any other reachable HTTP(S) endpoint. There's no underlying resource for Aspire to run; the facade's endpoint resolves straight to the configured URL.
servicesources.yaml:
services:
orders:
url:
url: https://orders.example.com
servicesources.local.json:
{
"services": {
"orders": { "source": "url" }
}
}
Set url in the developer config instead to override the catalog's URL for just that
developer (e.g. pointing at a personal tunnel or local proxy):
{
"services": {
"orders": { "source": "url", "url": "https://orders.dev.internal" }
}
}
"container" source
Run a published container image locally via Aspire's own container-runtime integration — image pull and lifecycle are managed entirely by Aspire.
servicesources.yaml:
services:
orders:
container:
image: ghcr.io/company/orders
port: 8080
defaultTag: latest
servicesources.local.json:
{
"services": {
"orders": { "source": "container" }
}
}
Set tag in the developer config to override the catalog's defaultTag for just that
developer:
{
"services": {
"orders": { "source": "container", "tag": "v1.4.2" }
}
}
Combining sources on one catalog entry
A single servicesources.yaml entry can carry blocks for every source at once — the catalog
just describes how each source would resolve the service; each developer's
servicesources.local.json picks which one actually applies to them:
services:
orders:
repository: https://github.com/example/orders
project: src/Orders.Api/Orders.Api.csproj
kubernetes:
service: orders-svc
port: 8080
url:
url: https://orders.example.com
container:
image: ghcr.io/example/orders
port: 8080
defaultTag: latest
A developer editing the service picks "local"; one debugging against a shared dev cluster
picks "kubernetes"; one who just needs it reachable picks "url" or "container" — same
catalog entry, same AddService("orders") call in the AppHost, no code changes either way.
Each developer's own servicesources.local.json just names which source applies to them —
editing orders locally:
{ "services": { "orders": { "source": "local" } } }
debugging against a shared dev cluster:
{ "services": { "orders": { "source": "kubernetes", "context": "dev-west", "namespace": "orders", "port": 8080 } } }
or just needing it reachable, not caring how:
{ "services": { "orders": { "source": "url" } } }
Sample
samples/DemoAppHost is a minimal working AppHost demonstrating all three easily-runnable
sources: orders via a real managed "local" git checkout (a small project cloned from
dotnet/aspire-samples), inventory via the
"url" source (pointing at httpbin.org, a live public test API), and
payments via the "container" source (the nginxdemos/hello hello-world image) — run it to
see the whole flow end to end. ("kubernetes" isn't demoed here since it needs a real cluster
and kubectl; see its section above.)
cd samples/DemoAppHost
cp servicesources.local.json.example servicesources.local.json
aspire run
Status
Early stage, evolving fast. "local", "kubernetes", "url", and "container" sources are
all implemented — see docs/superpowers/ for design and implementation
history, including the phase 2 backlog (repo auto-update, config discovery walk-up,
dependency/infrastructure resolution, and more).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Aspire.Hosting (>= 13.4.6)
- LibGit2Sharp (>= 0.32.0)
- YamlDotNet (>= 18.1.0)
-
net8.0
- Aspire.Hosting (>= 13.4.6)
- LibGit2Sharp (>= 0.32.0)
- YamlDotNet (>= 18.1.0)
-
net9.0
- Aspire.Hosting (>= 13.4.6)
- LibGit2Sharp (>= 0.32.0)
- YamlDotNet (>= 18.1.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on KoalaSoft.Aspire.Hosting.ServiceSources:
| Package | Downloads |
|---|---|
|
KoalaSoft.Aspire.Hosting.ServiceSources.Java
Java support for KoalaSoft.Aspire.Hosting.ServiceSources — lets an AddService() "local" source clone and run a Java service (Maven goal, Gradle task, or a jar) via the .NET Aspire Community Toolkit's Java integration. |
|
|
KoalaSoft.Aspire.Hosting.ServiceSources.JavaScript
JavaScript support for KoalaSoft.Aspire.Hosting.ServiceSources — runs a "local"-sourced service with kind "javascript" through Aspire.Hosting.JavaScript. |
GitHub repositories
This package is not used by any popular GitHub repositories.