From 1d027d7c9a40e31702f1f80d4d9b6b4e2396cc8b Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:05:02 -0500 Subject: [PATCH 1/5] docs: split host-only community integrations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b0414d35-db01-4c94-9902-319b4420d708 --- src/frontend/.starlight-icons/safelist.json | 7 - src/frontend/config/redirects.mjs | 7 + .../config/sidebar/integrations.topics.ts | 102 ++++- .../content/docs/integrations/devtools/k6.mdx | 240 ---------- .../devtools/k6/k6-get-started.mdx | 113 +++++ .../docs/integrations/devtools/k6/k6-host.mdx | 205 +++++++++ .../integrations/devtools/sql-projects.mdx | 355 --------------- .../sql-projects/sql-projects-get-started.mdx | 121 +++++ .../sql-projects/sql-projects-host.mdx | 261 +++++++++++ .../integrations/frameworks/deno-apps.mdx | 144 ------ .../frameworks/deno/deno-get-started.mdx | 97 ++++ .../frameworks/deno/deno-host.mdx | 215 +++++++++ .../docs/integrations/frameworks/java.mdx | 142 ------ .../frameworks/java/java-get-started.mdx | 92 ++++ .../frameworks/java/java-host.mdx | 349 ++++++++++++++ .../docs/integrations/frameworks/perl.mdx | 424 ------------------ .../frameworks/perl/perl-get-started.mdx | 118 +++++ .../frameworks/perl/perl-host.mdx | 321 +++++++++++++ .../integrations/frameworks/powershell.mdx | 200 --------- .../powershell/powershell-get-started.mdx | 100 +++++ .../frameworks/powershell/powershell-host.mdx | 231 ++++++++++ .../docs/integrations/frameworks/rust.mdx | 118 ----- .../frameworks/rust/rust-get-started.mdx | 101 +++++ .../frameworks/rust/rust-host.mdx | 206 +++++++++ src/frontend/src/data/integration-docs.json | 16 +- 25 files changed, 2640 insertions(+), 1645 deletions(-) delete mode 100644 src/frontend/src/content/docs/integrations/devtools/k6.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/devtools/sql-projects.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/deno-apps.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/java.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/perl.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/powershell.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/rust.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx diff --git a/src/frontend/.starlight-icons/safelist.json b/src/frontend/.starlight-icons/safelist.json index 3f0bad057..9070882e5 100644 --- a/src/frontend/.starlight-icons/safelist.json +++ b/src/frontend/.starlight-icons/safelist.json @@ -29,14 +29,10 @@ "i-material-icon-theme:folder-controller-open", "i-material-icon-theme:folder-docs", "i-material-icon-theme:folder-docs-open", - "i-material-icon-theme:folder-lib", - "i-material-icon-theme:folder-lib-open", "i-material-icon-theme:folder-plugin", "i-material-icon-theme:folder-plugin-open", "i-material-icon-theme:folder-public", "i-material-icon-theme:folder-public-open", - "i-material-icon-theme:folder-scripts", - "i-material-icon-theme:folder-scripts-open", "i-material-icon-theme:folder-src", "i-material-icon-theme:folder-src-open", "i-material-icon-theme:folder-template", @@ -53,14 +49,11 @@ "i-material-icon-theme:next", "i-material-icon-theme:nodejs", "i-material-icon-theme:nuget", - "i-material-icon-theme:perl", "i-material-icon-theme:powershell", - "i-material-icon-theme:prolog", "i-material-icon-theme:python", "i-material-icon-theme:python-misc", "i-material-icon-theme:razor", "i-material-icon-theme:react-ts", - "i-material-icon-theme:rust", "i-material-icon-theme:settings", "i-material-icon-theme:skill", "i-material-icon-theme:svg", diff --git a/src/frontend/config/redirects.mjs b/src/frontend/config/redirects.mjs index 64c11cbe1..da01fc764 100644 --- a/src/frontend/config/redirects.mjs +++ b/src/frontend/config/redirects.mjs @@ -180,6 +180,13 @@ export const redirects = { '/integrations/devtools/mailpit/': '/integrations/devtools/mailpit/mailpit-get-started/', '/integrations/frameworks/go/': '/integrations/frameworks/go/go-get-started/', '/integrations/frameworks/go-apps/': '/integrations/frameworks/go/go-get-started/', + '/integrations/frameworks/deno-apps/': '/integrations/frameworks/deno/deno-get-started/', + '/integrations/frameworks/java/': '/integrations/frameworks/java/java-get-started/', + '/integrations/frameworks/perl/': '/integrations/frameworks/perl/perl-get-started/', + '/integrations/frameworks/powershell/': '/integrations/frameworks/powershell/powershell-get-started/', + '/integrations/frameworks/rust/': '/integrations/frameworks/rust/rust-get-started/', + '/integrations/devtools/k6/': '/integrations/devtools/k6/k6-get-started/', + '/integrations/devtools/sql-projects/': '/integrations/devtools/sql-projects/sql-projects-get-started/', '/ja/integrations/frameworks/go-apps/': '/integrations/frameworks/go/go-get-started/', '/integrations/frameworks/csharp-file-based-apps/': '/integrations/dotnet/csharp-file-based-apps/', '/integrations/frameworks/maui/': '/integrations/dotnet/maui/', diff --git a/src/frontend/config/sidebar/integrations.topics.ts b/src/frontend/config/sidebar/integrations.topics.ts index 9003ee9e4..616b8ff20 100644 --- a/src/frontend/config/sidebar/integrations.topics.ts +++ b/src/frontend/config/sidebar/integrations.topics.ts @@ -1361,7 +1361,20 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, ], }, - { label: 'Java', slug: 'integrations/frameworks/java' }, + { + label: 'Java', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/java/java-get-started', + }, + { + label: 'Set up Java apps in the AppHost', + slug: 'integrations/frameworks/java/java-host', + }, + ], + }, { label: 'JavaScript and Node.js', collapsed: true, @@ -1384,15 +1397,67 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, items: [ { label: 'Bun', slug: 'integrations/frameworks/bun-apps' }, - { label: 'Deno', slug: 'integrations/frameworks/deno-apps' }, + { + label: 'Deno', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/deno/deno-get-started', + }, + { + label: 'Set up Deno apps in the AppHost', + slug: 'integrations/frameworks/deno/deno-host', + }, + ], + }, { label: 'JavaScript', slug: 'integrations/frameworks/javascript' }, { label: 'Node.js extensions', slug: 'integrations/frameworks/nodejs-extensions' }, ], }, - { label: 'Perl', slug: 'integrations/frameworks/perl' }, - { label: 'PowerShell', slug: 'integrations/frameworks/powershell' }, + { + label: 'Perl', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/perl/perl-get-started', + }, + { + label: 'Set up Perl apps in the AppHost', + slug: 'integrations/frameworks/perl/perl-host', + }, + ], + }, + { + label: 'PowerShell', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/powershell/powershell-get-started', + }, + { + label: 'Set up PowerShell scripts in the AppHost', + slug: 'integrations/frameworks/powershell/powershell-host', + }, + ], + }, { label: 'Python', slug: 'integrations/frameworks/python' }, - { label: 'Rust', slug: 'integrations/frameworks/rust' }, + { + label: 'Rust', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/rust/rust-get-started', + }, + { + label: 'Set up Rust apps in the AppHost', + slug: 'integrations/frameworks/rust/rust-host', + }, + ], + }, ], }, { @@ -1643,7 +1708,20 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, ], }, - { label: 'k6', slug: 'integrations/devtools/k6' }, + { + label: 'k6', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/devtools/k6/k6-get-started', + }, + { + label: 'Set up k6 tests in the AppHost', + slug: 'integrations/devtools/k6/k6-host', + }, + ], + }, { label: 'MailPit', collapsed: true, @@ -1664,7 +1742,17 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, { label: 'SQL Database Projects', - slug: 'integrations/devtools/sql-projects', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/devtools/sql-projects/sql-projects-get-started', + }, + { + label: 'Set up SQL projects in the AppHost', + slug: 'integrations/devtools/sql-projects/sql-projects-host', + }, + ], }, ], }, diff --git a/src/frontend/src/content/docs/integrations/devtools/k6.mdx b/src/frontend/src/content/docs/integrations/devtools/k6.mdx deleted file mode 100644 index 46cb780b6..000000000 --- a/src/frontend/src/content/docs/integrations/devtools/k6.mdx +++ /dev/null @@ -1,240 +0,0 @@ ---- -title: Set up k6 in the AppHost -description: Learn how to use the Aspire k6 Hosting integration to orchestrate and configure a Grafana k6 load-testing resource in an Aspire solution. ---- - -import { Image } from 'astro:assets'; -import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; -import LearnMore from '@components/LearnMore.astro'; -import k6Icon from '@assets/icons/k6-icon.svg'; - - - -k6 logo - -This article is the reference for the Aspire k6 Hosting integration. It enumerates the AppHost APIs that you use to model a [Grafana k6](https://k6.io/) performance and load-testing resource in your [`AppHost`](/get-started/app-host/) project. - -## Installation - -To start building an Aspire app that uses k6, install the [📦 CommunityToolkit.Aspire.Hosting.k6](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.k6) NuGet package: - - - - -```bash title="Terminal" -aspire add k6 -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -Or, choose a manual installation approach: - -```csharp title="AppHost.cs" -#:package CommunityToolkit.Aspire.Hosting.k6@* -``` - -```xml title="AppHost.csproj" - -``` - - - - -```bash title="Terminal" -aspire add k6 -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -This updates your `aspire.config.json` with the k6 hosting integration package: - -```json title="aspire.config.json" ins={3} -{ - "packages": { - "CommunityToolkit.Aspire.Hosting.k6": "*" - } -} -``` - -The TypeScript AppHost bindings for k6 are provided by the Community Toolkit package. After installation, the `.aspire/modules/aspire.mjs` file in your project includes `addK6` and related APIs. - - - - -## Add k6 resource - -Once you've installed the hosting integration in your AppHost project, you can add a k6 resource as shown in the following example: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var myService = builder.AddProject("myService"); - -var k6 = builder.AddK6("k6") - .WithBindMount("scripts", "/scripts", isReadOnly: true) - .WithScript("/scripts/main.js") - .WithReference(myService) - .WaitFor(myService); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const myService = await builder.addProject("myService", "../MyService/MyService.csproj"); - -const k6 = await builder.addK6("k6"); -await k6.withBindMount("scripts", "/scripts", { isReadOnly: true }); -await k6.withScript("/scripts/main.js"); -await k6.withReference(myService); -await k6.waitFor(myService); - -// After adding all resources, run the app... -``` - - - - -When Aspire adds a container image to the AppHost, as shown in the preceding example with the `docker.io/grafana/k6` image, it creates a new k6 instance on your local machine. - - - -## Scripts configuration - -You need to provide a JavaScript file for k6 to execute. Here is a minimal example: - -```js title="scripts/main.js" -import http from "k6/http"; -import { sleep } from "k6"; - -export default function () { - http.get(`${__ENV.services__myService__http__0}/hello`); - - sleep(1); -} -``` - -The `services__myService__http__0` environment variable resolves to the `http` endpoint of the `myService` resource. - -For more information on writing k6 scripts, see [Write your first test with Grafana k6](https://grafana.com/docs/k6/latest/get-started/write-your-first-test/). - -## Customize ports - -To use a fixed host port instead of a randomly assigned one, pass the `port` parameter to `AddK6` or `addK6`: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var myService = builder.AddProject("myService"); - -var k6 = builder.AddK6("k6", port: 6565) - .WithBindMount("scripts", "/scripts", isReadOnly: true) - .WithScript("/scripts/main.js") - .WithReference(myService) - .WaitFor(myService); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const myService = await builder.addProject("myService", "../MyService/MyService.csproj"); - -const k6 = await builder.addK6("k6", { port: 6565 }); -await k6.withBindMount("scripts", "/scripts", { isReadOnly: true }); -await k6.withScript("/scripts/main.js"); -await k6.withReference(myService); -await k6.waitFor(myService); - -// After adding all resources, run the app... -``` - - - - -The `port` parameter sets the host port for the k6 HTTP API endpoint. When omitted, Aspire assigns a random port. - -## Enable browser extensions - -To enable the k6 browser module — which adds browser-level APIs and frontend performance metrics to your k6 tests — pass `enableBrowserExtensions: true` to `AddK6` or `addK6`: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var myService = builder.AddProject("myService"); - -var k6 = builder.AddK6("k6", enableBrowserExtensions: true) - .WithBindMount("scripts", "/scripts", isReadOnly: true) - .WithScript("/scripts/main.js") - .WithReference(myService) - .WaitFor(myService); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const myService = await builder.addProject("myService", "../MyService/MyService.csproj"); - -const k6 = await builder.addK6("k6", { enableBrowserExtensions: true }); -await k6.withBindMount("scripts", "/scripts", { isReadOnly: true }); -await k6.withScript("/scripts/main.js"); -await k6.withReference(myService); -await k6.waitFor(myService); - -// After adding all resources, run the app... -``` - - - - -For more information on the k6 browser module, see [Using k6 browser](https://grafana.com/docs/k6/latest/using-k6-browser/). - -## See also - -- [Grafana k6 website](https://k6.io/) -- [Grafana k6 documentation](https://grafana.com/docs/k6/latest/) -- [Aspire Community Toolkit GitHub](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx new file mode 100644 index 000000000..60c0e29ae --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx @@ -0,0 +1,113 @@ +--- +title: Get started with the Grafana k6 integration +description: Model Grafana k6 load tests as Aspire resources, run scripts in containers, and inspect their health, logs, and endpoints. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import k6Icon from '@assets/icons/k6-icon.svg'; + + + +k6 logo + +[Grafana k6](https://k6.io/) is an open-source performance and load-testing tool. The Aspire Community Toolkit k6 hosting integration models a k6 container and its HTTP API as an AppHost resource. This lets you run load tests beside the services they test and inspect their logs, endpoint, and health in the Aspire dashboard. + +## How the integration fits together + +The hosting integration runs the k6 container. Your test script is mounted into that container, and can use the connection information Aspire supplies for referenced resources. + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group test(logos:javascript)[k6 test] + + service hosting(server)[k6 hosting integration] in apphost + service k6(server)[k6 container resource] in apphost + service script(logos:javascript)[JavaScript test script] in test + service targetapp(server)[Application service] in apphost + + hosting:R --> L:k6 + script:R --> L:k6 + k6:B --> T:targetapp +``` + +## Prerequisites + +- Install [Docker](https://docs.docker.com/get-docker/) and make sure it is running. +- Install the [Aspire CLI](/get-started/install-cli/) and create an AppHost. +- Create a JavaScript test script that k6 can execute. + +## Setup + +### Add the hosting package + +Add `CommunityToolkit.Aspire.Hosting.k6` to your AppHost. See [Set up k6 in the AppHost](/integrations/devtools/k6/k6-host/#installation) for package installation options. + +### Add and configure the resource + +Mount the directory that contains your tests, then select the script to run: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddK6("k6") + .WithBindMount("./scripts", "/scripts", isReadOnly: true) + .WithScript("/scripts/main.js"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const k6 = await builder.addK6('k6'); +await k6.withBindMount('./scripts', '/scripts', { isReadOnly: true }); +await k6.withScript('/scripts/main.js'); + +await builder.build().run(); +``` + + + + +### Write the test + +Use the k6 APIs in the mounted script: + +```javascript title="scripts/main.js" +import http from 'k6/http'; +import { sleep } from 'k6'; + +export default function () { + http.get('http://host.docker.internal:8080/'); + sleep(1); +} +``` + +Replace the URL with the address appropriate for the service under test. When the service is also an Aspire resource, reference it from k6 and use the service-discovery configuration supplied by Aspire. + +## Next steps + +The [k6 hosting reference](/integrations/devtools/k6/k6-host/) covers the resource endpoint, health check, script arguments, browser image, OpenTelemetry environment variables, and publish behavior. + +## See also + +- [Grafana k6 documentation](https://grafana.com/docs/k6/latest/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx new file mode 100644 index 000000000..f40bc1eb0 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx @@ -0,0 +1,205 @@ +--- +title: Set up Grafana k6 in the Aspire AppHost +seoTitle: Grafana k6 hosting integration for Aspire +description: Configure the Community Toolkit k6 resource in Aspire, including scripts, browser testing, endpoints, health checks, and OpenTelemetry. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import LearnMore from '@components/LearnMore.astro'; +import k6Icon from '@assets/icons/k6-icon.svg'; + + + +k6 logo + +This reference describes the Community Toolkit k6 hosting integration APIs for the Aspire [AppHost](/get-started/app-host/). If you're new to the integration, start with [Get started with the k6 integration](/integrations/devtools/k6/k6-get-started/). + +## Installation + +Add [📦 CommunityToolkit.Aspire.Hosting.k6](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.k6) to the AppHost: + + + + +```bash title="Terminal" +aspire add k6 +``` + +Or add the package manually: + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.k6@* +``` + + + + +```bash title="Terminal" +aspire add k6 +``` + +The command adds the package to `aspire.config.json`: + +```json title="aspire.config.json" +{ + "packages": { + "CommunityToolkit.Aspire.Hosting.k6": "*" + } +} +``` + + + + + + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. + + +## Add a k6 resource + +Use `AddK6` / `addK6` to add a Grafana k6 container resource. The resource uses the `docker.io/grafana/k6` image, exposes its HTTP API as the `http` endpoint, and is visible in the dashboard. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var k6 = builder.AddK6("k6"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const k6 = await builder.addK6('k6'); + +await builder.build().run(); +``` + + + + +`name` identifies the resource and is used as its connection name when another resource references it. + +### Endpoint, health, and container behavior + +`AddK6` / `addK6` configures these behaviors: + +- An internal `http` endpoint targets port `6565`. Specify `port` to bind a fixed host port; otherwise Aspire allocates one. +- Aspire checks `GET /health` on that endpoint. +- The resource is a container resource, so its logs, lifecycle actions, endpoint link, and health state appear in the dashboard. +- The integration configures an OTLP exporter for the container. Use `WithK6OtlpEnvironment` / `withK6OtlpEnvironment` when k6 should consume the corresponding k6 environment variables. + +Use `PrimaryEndpoint` / `primaryEndpoint()` when an AppHost API needs the k6 HTTP endpoint directly. + +### Use a fixed port or browser-enabled image + +The optional `enableBrowserExtensions` parameter selects the k6 image variant with browser support. The optional `port` parameter selects the host port for the HTTP API. + + + + +```csharp title="AppHost.cs" +var k6 = builder.AddK6( + "browser-tests", + enableBrowserExtensions: true, + port: 6565); +``` + + + + +```typescript title="apphost.mts" +const k6 = await builder.addK6('browser-tests', { + enableBrowserExtensions: true, + port: 6565, +}); +``` + + + + +The default image does not include browser support. Enable it only for tests that use the [k6 browser module](https://grafana.com/docs/k6/latest/using-k6-browser/). + +## Run a script + +`WithScript` / `withScript` configures the container command as `k6 run`, binds it to `0.0.0.0:6565`, and sets the virtual-user and duration arguments. `virtualUsers` defaults to `10` and `duration` defaults to `30s`. + +Mount the script directory with the standard container `WithBindMount` / `withBindMount` API before selecting a path in the container: + + + + +```csharp title="AppHost.cs" +var k6 = builder.AddK6("load-test") + .WithBindMount("./scripts", "/scripts", isReadOnly: true) + .WithScript("/scripts/main.js", virtualUsers: 25, duration: "45s"); +``` + + + + +```typescript title="apphost.mts" +const k6 = await builder.addK6('load-test'); +await k6.withBindMount('./scripts', '/scripts', { isReadOnly: true }); +await k6.withScript('/scripts/main.js', { + virtualUsers: 25, + duration: '45s', +}); +``` + + + + +`scriptPath` must be a path the container can read. The integration doesn't set a container working directory, so use an absolute container path or a path valid for the configured image. `WithScript` / `withScript` rejects a null script path and a zero or negative virtual-user count. + +## Export k6 telemetry + +`WithK6OtlpEnvironment` / `withK6OtlpEnvironment` copies every existing `OTEL_*` environment variable for the resource to a corresponding `K6_OTEL_*` variable. This enables the k6 OpenTelemetry output to use the OTLP configuration that Aspire has already set for the resource. + + + + +```csharp title="AppHost.cs" +var k6 = builder.AddK6("load-test") + .WithK6OtlpEnvironment(); +``` + + + + +```typescript title="apphost.mts" +const k6 = await builder.addK6('load-test'); +await k6.withK6OtlpEnvironment(); +``` + + + + +## References and publishing + +Use the standard `WithReference` / `withReference` and `WaitFor` / `waitFor` APIs to model the relationship between the test and the resources it exercises. Referenced resources provide their connection information through Aspire's normal resource configuration. + +The integration doesn't add k6-specific publish or export callbacks. It remains a normal Aspire container resource with its configured image, endpoint, and container settings available to publishers. + +## See also + +- [Get started with the k6 integration](/integrations/devtools/k6/k6-get-started/) +- [Grafana k6 documentation](https://grafana.com/docs/k6/latest/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects.mdx deleted file mode 100644 index 6c4b8debb..000000000 --- a/src/frontend/src/content/docs/integrations/devtools/sql-projects.mdx +++ /dev/null @@ -1,355 +0,0 @@ ---- -title: SQL Database Projects integration -description: Learn about the Aspire hosting integration for SQL Database Projects — model your schema, deploy DACPACs to SQL Server containers, and wire up CI/CD database pipelines. -next: false ---- - -import { Image } from 'astro:assets'; -import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; -import InstallPackage from "@components/InstallPackage.astro"; -import sqlIcon from '@assets/icons/sql-icon.png'; - - - -SQL Database Projects icon - -The Aspire SQL Database Projects hosting integration enables you to deploy SQL database schemas from SQL projects or DACPAC files during local development and testing. This integration supports both [MSBuild.Sdk.SqlProj](https://github.com/rr-wfm/MSBuild.Sdk.SqlProj) and [Microsoft.Build.Sql](https://www.nuget.org/packages/Microsoft.Build.Sql) project formats. - -## Hosting integration - -To get started with the Aspire SQL Database Projects hosting integration, install the [CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects) NuGet package in the app host project. - - - - - - - - - -```bash title="Terminal" -aspire add CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects -``` - -This updates your `aspire.config.json` with the SQL Database Projects hosting integration package: - -```json title="aspire.config.json" ins={3} -{ - "packages": { - "CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects": "*" - } -} -``` - - - - -The TypeScript AppHost bindings for SQL Database Projects are provided by the Community Toolkit package. After installation, the `.aspire/modules/aspire.mjs` file in your project includes `addSqlProject` and related APIs. - -### Add SQL project - -To deploy a SQL project to a SQL Server database, use the `AddSqlProject` extension method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -builder.AddSqlProject("database-project") - .WithReference(sql); - -builder.AddProject() - .WithReference(sql); - -// After adding all resources, run the app... -``` - -This method takes a project reference to your SQL database project and deploys it to the specified database when the app host starts. - - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await builder.addSqlServer("sql"); -const sqldb = await sql.addDatabase("sqldb"); - -const databaseProject = await builder.addSqlProject("database-project"); -await databaseProject.withReference(sqldb); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(sqldb); - -// After adding all resources, run the app... -``` - - - - -### Add SQL package (NuGet) - -To deploy a SQL database schema from a NuGet package, use the `AddSqlPackage` extension method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -builder.AddSqlPackage("Contoso.DatabasePackage", "1.0.0") - .WithReference(sql); - -builder.AddProject() - .WithReference(sql); - -// After adding all resources, run the app... -``` - -This method downloads the specified NuGet package and deploys the DACPAC it contains to the database. - - - - - - - - - - -### Add DACPAC file - -To deploy a DACPAC file directly, use the `WithDacpac` extension method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -sql.WithDacpac("path/to/database.dacpac"); - -builder.AddProject() - .WithReference(sql); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await builder.addSqlServer("sql"); -const sqldb = await sql.addDatabase("sqldb"); - -const databaseProject = await builder.addSqlProject("database-project"); -await databaseProject.withDacpac("path/to/database.dacpac"); -await databaseProject.withReference(sqldb); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(sqldb); - -// After adding all resources, run the app... -``` - - - - -### Configure DAC deployment options - -You can customize the DACPAC deployment behavior using the `WithConfigureDacDeployOptions` method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -sql.AddSqlProject("database-project") - .WithConfigureDacDeployOptions(options => - { - options.BlockOnPossibleDataLoss = false; - options.DropObjectsNotInSource = true; - }); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await builder.addSqlServer("sql"); -const sqldb = await sql.addDatabase("sqldb"); - -const databaseProject = await builder.addSqlProject("database-project"); -await databaseProject.withReference(sqldb); -await databaseProject.withDacDeployOptions("path/to/database.publish.xml"); - -// After adding all resources, run the app... -``` - - - - - - -### Redeploy action - -The SQL Database Projects integration adds a custom "Redeploy" action to the Aspire dashboard. This action allows you to manually trigger a redeployment of the database schema without restarting the entire app host. - -To use the Redeploy action: -1. Open the Aspire dashboard -2. Find your SQL database resource -3. Click the "Redeploy" action in the resource's menu - -This is useful during development when you make changes to your database schema and want to quickly apply them. - -### Multiple SQL projects - -You can add multiple SQL projects to the same database or different databases: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql"); - -var db1 = sql.AddDatabase("db1"); -db1.AddSqlProject("db1-project"); - -var db2 = sql.AddDatabase("db2"); -db2.AddSqlProject("db2-project"); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await builder.addSqlServer("sql"); - -const db1 = await sql.addDatabase("db1"); -const db1Project = await builder.addSqlProject("db1-project"); -await db1Project.withReference(db1); - -const db2 = await sql.addDatabase("db2"); -const db2Project = await builder.addSqlProject("db2-project"); -await db2Project.withReference(db2); - -// After adding all resources, run the app... -``` - - - - -### Ability to skip deployment - -You can use the `WithSkipWhenDeployed` method to avoid re-deploying your SQL Database Project if no changes have been made. This is useful in scenarios where the SQL container database is persisted to permanent storage and will significantly reduce the app host startup time. - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .WithDataVolume("data") - .WithLifetime(ContainerLifetime.Persistent); - -var db1 = sql.AddDatabase("db1"); - -db1.AddSqlProject("db1-project") - .WithSkipWhenDeployed(); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await builder.addSqlServer("sql"); -await sql.withDataVolume("data"); -await sql.withLifetime("Persistent"); - -const db1 = await sql.addDatabase("db1"); - -const db1Project = await builder.addSqlProject("db1-project"); -await db1Project.withReference(db1); -await db1Project.withSkipWhenDeployed(); - -// After adding all resources, run the app... -``` - - - - -## See also - -- [MSBuild.Sdk.SqlProj](https://github.com/rr-wfm/MSBuild.Sdk.SqlProj) -- [Microsoft.Build.Sql](https://www.nuget.org/packages/Microsoft.Build.Sql) -- [SQL Server Data Tools (SSDT)](https://learn.microsoft.com/sql/ssdt/sql-server-data-tools) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Aspire integrations overview](/integrations/overview/) -- [Aspire GitHub repo](https://github.com/microsoft/aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx new file mode 100644 index 000000000..e6ab39e57 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx @@ -0,0 +1,121 @@ +--- +title: Get started with SQL Database Projects +description: Learn how Aspire deploys a SQL Database Project DACPAC to a SQL Server database during local development and testing. +--- + +import { + Badge, + LinkButton, + Tabs, + TabItem, +} from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; + +import sqlIcon from '@assets/icons/sql-database-projects-icon.png'; + + + +SQL Database Projects icon + +The [SQL Database Projects](https://learn.microsoft.com/sql/tools/sql-database-projects/sql-database-projects) hosting integration deploys a DACPAC to a SQL Server database as part of your Aspire AppHost. Use it to keep a database schema alongside the services that depend on it during local development and testing. + +## How the pieces fit together + +This is a hosting-only integration. Your AppHost models a SQL project resource and a target database. When the target database is ready, the integration publishes the DACPAC. The SQL project resource is a deployment task, not a connection resource; applications that need database access reference the SQL Server database directly. + +```mermaid +architecture-beta + group apphost(server)[AppHost] + group app(server)[Application] + + service sqlproject(database)[SQL project resource] in apphost + service database(database)[SQL Server database] in apphost + service application(server)[App] in app + + sqlproject:R --> L:database + database:R --> L:application +``` + +## Prerequisites + +- [Install the Aspire CLI](/get-started/install-cli/) and use an AppHost with the [SQL Server hosting integration](/integrations/databases/sql-server/sql-server-host/). +- Build your database with either [MSBuild.Sdk.SqlProj](https://github.com/rr-wfm/MSBuild.Sdk.SqlProj) or [Microsoft.Build.Sql](https://www.nuget.org/packages/Microsoft.Build.Sql). The integration deploys the resulting `.dacpac` file. +- For a C# AppHost, you can add a project reference to the SQL project and use the generated `Projects.*` metadata type. For a TypeScript AppHost, supply the DACPAC path. + +## Add a SQL project resource + +Install the Community Toolkit hosting package in the AppHost: + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects +``` + +Then add the SQL Server database and a SQL project resource. Update the DACPAC path to match your database project's output. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var database = builder.AddSqlServer("sql") + .AddDatabase("catalog"); + +builder.AddSqlProject("catalog-schema") + .WithDacpac("../Database/bin/Debug/net10.0/Database.dacpac") + .WithReference(database); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); +const appHostDirectory = path.dirname(fileURLToPath(import.meta.url)); +const dacpacPath = path.join( + appHostDirectory, + '../Database/bin/Debug/net10.0/Database.dacpac' +); + +const sql = await builder.addSqlServer('sql'); +const database = await sql.addDatabase('catalog'); +const databaseProject = await builder.addSqlProject('catalog-schema'); + +await databaseProject.withDacpac(dacpacPath); +await databaseProject.withReference(database); + +await builder.build().run(); +``` + + + + +For all resource APIs, deployment options, dashboard actions, and support for an existing SQL Server, see the hosting reference. + + + Configure SQL Database Projects in the AppHost + + +## See also + +- [MSBuild.Sdk.SqlProj](https://github.com/rr-wfm/MSBuild.Sdk.SqlProj) +- [Microsoft.Build.Sql](https://www.nuget.org/packages/Microsoft.Build.Sql) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx new file mode 100644 index 000000000..01e0f0de6 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx @@ -0,0 +1,261 @@ +--- +title: Configure SQL Database Projects in AppHost +seoTitle: Configure SQL Database Projects in the Aspire AppHost +description: Reference the SQL Database Projects AppHost APIs for deploying DACPAC files, project outputs, and package schemas to SQL Server. +--- + +import { Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import InstallPackage from '@components/InstallPackage.astro'; +import LearnMore from '@components/LearnMore.astro'; + +import sqlIcon from '@assets/icons/sql-database-projects-icon.png'; + + + +SQL Database Projects icon + +This reference covers the Community Toolkit SQL Database Projects hosting integration. If you are new to it, start with [Get started with SQL Database Projects](/integrations/devtools/sql-projects/sql-projects-get-started/). + +## Installation + +Add [📦 CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects) to your AppHost: + + + +Or add it manually: + + + + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects@* +``` + + + + +```json title="aspire.config.json" +{ + "packages": { + "CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects": "*" + } +} +``` + + + + +Run `aspire restore` after changing a TypeScript AppHost package configuration to regenerate `.aspire/modules/`. + +## Add a project or DACPAC resource + +`AddSqlProject` creates a `SqlProject` dashboard resource in the waiting state. It is a deployment resource, so it has no endpoint, environment variables, connection string, or health check. It implements standard wait support, which lets other resources use `WaitForCompletion`. + +In a C# AppHost, use `AddSqlProject` when the AppHost references an MSBuild SQL project. The generic project metadata overload resolves the project's `SqlTargetPath` or `TargetPath` output. Use the non-generic overload with `WithDacpac` when you already have a DACPAC. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var database = builder.AddSqlServer("sql") + .AddDatabase("catalog"); + +builder.AddSqlProject("catalog-schema") + .WithReference(database); + +builder.AddSqlProject("imported-schema") + .WithDacpac("../artifacts/imported-schema.dacpac") + .WithReference(database); + +builder.Build().Run(); +``` + +Add the SQL project as an AppHost project reference before using `Projects.Database`: + +```xml title="AppHost.csproj" + +``` + +:::note +Adding a SQL project reference currently produces warning `ASPIRE004` because the SQL project is not executable. The warning does not prevent the integration from resolving the DACPAC. +::: + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const sql = await builder.addSqlServer('sql'); +const database = await sql.addDatabase('catalog'); +const databaseProject = await builder.addSqlProject('catalog-schema'); + +await databaseProject.withDacpac('../artifacts/catalog-schema.dacpac'); +await databaseProject.withReference(database); + +await builder.build().run(); +``` + + + + +`WithDacpac` accepts a path to a `.dacpac` file. At deployment time, a relative DACPAC path is resolved against the AppHost content root. The integration does not set a working directory. + +:::note +The generic `AddSqlProject` overload is C# only. It requires `IProjectMetadata`, so TypeScript uses `addSqlProject(name)` and `withDacpac(path)` instead. +::: + +## Deploy a DACPAC from a NuGet package + +In C#, `AddSqlPackage` models a DACPAC contained in a NuGet package. Mark the package reference with `IsAspirePackageResource` so the generated `Packages.*` metadata type is available: + +```xml title="AppHost.csproj" + + true + +``` + +```csharp title="AppHost.cs" +var packageSchema = builder.AddSqlPackage("chinook") + .WithDacpac("tools/ErikEJ.Dacpac.Chinook.dacpac") + .WithReference(database); +``` + +The package resource uses `tools/.dacpac` by default; `WithDacpac` selects a different path relative to the package. It also supports `WithDacDeployOptions`, `WithConfigureDacDeployOptions`, `WithSkipWhenDeployed`, and both `WithReference` target overloads. `AddSqlPackage` and these package APIs aren't exported to TypeScript because they require `IPackageMetadata`. + +## Configure deployment + +Use a DACFx publish profile with `WithDacDeployOptions`, or configure `DacDeployOptions` directly in a C# AppHost. A publish-profile path is loaded as supplied, so use a path that is valid for the AppHost process. + + + + +```csharp title="AppHost.cs" +var databaseProject = builder.AddSqlProject("catalog-schema") + .WithDacpac("../artifacts/catalog-schema.dacpac") + .WithConfigureDacDeployOptions(options => + { + options.BlockOnPossibleDataLoss = false; + options.DropObjectsNotInSource = true; + }) + .WithReference(database); + +var profileProject = builder.AddSqlProject("profile-schema") + .WithDacpac("../artifacts/profile-schema.dacpac") + .WithDacDeployOptions("../Database/Database.publish.xml") + .WithReference(database); +``` + + + + +```typescript title="apphost.mts" +const databaseProject = await builder.addSqlProject('catalog-schema'); + +await databaseProject.withDacpac('../artifacts/catalog-schema.dacpac'); +await databaseProject.withDacDeployOptions('../Database/Database.publish.xml'); +await databaseProject.withReference(database); +``` + + + + +`WithConfigureDacDeployOptions(Action)` is C# only because callback options aren't exported to TypeScript. `WithDacDeployOptions(path)` is available in both AppHost languages. + +## Avoid unchanged deployments + +`WithSkipWhenDeployed` records a DACPAC checksum in the target database. On later deployments, the integration skips the DACPAC if the checksum is unchanged. It sets `DropExtendedPropertiesNotInSource` to `false` while this option is active. + + + + +```csharp title="AppHost.cs" +var databaseProject = builder.AddSqlProject("catalog-schema") + .WithDacpac("../artifacts/catalog-schema.dacpac") + .WithSkipWhenDeployed() + .WithReference(database); +``` + + + + +```typescript title="apphost.mts" +const databaseProject = await builder.addSqlProject('catalog-schema'); + +await databaseProject.withDacpac('../artifacts/catalog-schema.dacpac'); +await databaseProject.withSkipWhenDeployed(); +await databaseProject.withReference(database); +``` + + + + +Use this with a persistent database when avoiding an unchanged schema deployment improves AppHost startup time. + +## Target a database + +`WithReference` establishes a parent relationship to the target, waits for that target to be ready, and then deploys the DACPAC. A SQL Server database target supplies the database name automatically. You can instead target any connection-string resource; its connection string must contain `Database` or `Initial Catalog` so DACFx can infer the target database. + + + + +```csharp title="AppHost.cs" +var connection = builder.AddConnectionString("catalog"); + +builder.AddSqlProject("catalog-schema") + .WithDacpac("../artifacts/catalog-schema.dacpac") + .WithReference(connection); +``` + + + + +```typescript title="apphost.mts" +const connection = await builder.addConnectionString('catalog'); +const databaseProject = await builder.addSqlProject('catalog-schema'); + +await databaseProject.withDacpac('../artifacts/catalog-schema.dacpac'); +await databaseProject.withConnectionReference(connection); +``` + + + + +The SQL Server database overload is `withReference` in TypeScript. The connection-string overload is separately exported as `withConnectionReference`. + +## Dashboard behavior and resource properties + +When a referenced target becomes ready, the integration publishes the DACPAC and reports the deployment resource as `Running`, then `Finished` with exit code `0`; failures are reported in the resource logs and state. Use standard `WithExplicitStart` on a project or package resource to prevent that automatic deployment, then invoke its highlighted **Deploy** dashboard command. The command also deploys a schema again manually and is disabled while the resource is starting or running. + +The `SqlProjectResource` is exported with properties for TypeScript AppHosts: + +- `dacpacPath()` returns the path configured by `withDacpac`, or `null`. +- `dacDeployOptionsPath()` returns the publish-profile path configured by `withDacDeployOptions`, or `null`. +- `skipWhenDeployed()` returns whether `withSkipWhenDeployed` was applied. + +`AddSqlProject(name)`, `withDacpac`, `withDacDeployOptions`, `withSkipWhenDeployed`, `withReference` for SQL Server databases, and `withConnectionReference` are marked for Aspire export and are available in the generated TypeScript module. The C# generic project/package APIs and the callback configuration API are explicitly excluded from Aspire export. + +SQL project and package deployment resources are excluded from the Aspire manifest. Publishing/exporting the AppHost therefore doesn't emit a runnable SQL-project resource or deployment command; arrange schema deployment separately in the target environment. + + + Learn how to configure the target SQL Server database in the [SQL Server + hosting integration](/integrations/databases/sql-server/sql-server-host/). + + +## See also + +- [MSBuild.Sdk.SqlProj](https://github.com/rr-wfm/MSBuild.Sdk.SqlProj) +- [Microsoft.Build.Sql](https://www.nuget.org/packages/Microsoft.Build.Sql) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno-apps.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno-apps.mdx deleted file mode 100644 index 34d900a30..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/deno-apps.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: Deno integration -seoTitle: Deno integration for Aspire AppHost (Community Toolkit) -description: Learn how to use the Aspire Deno Hosting integration to run Deno applications alongside your other Aspire resources in the AppHost. ---- - -import { Image } from 'astro:assets'; -import { Aside, Badge, TabItem, Tabs } from '@astrojs/starlight/components'; -import InstallPackage from "@components/InstallPackage.astro"; -import denoIcon from '@assets/icons/deno-icon.png'; - -Deno logo - - - -:::note -TypeScript AppHost support for the Deno hosting integration is not yet available. The `CommunityToolkit.Aspire.Hosting.Deno` package does not currently expose `addDenoApp` or `addDenoTask` APIs in the TypeScript SDK. All examples on this page use the C# AppHost. -::: - -The Aspire Deno hosting integration enables you to run [Deno](https://deno.com/) applications — a modern, secure JavaScript and TypeScript runtime — alongside your other resources in the [AppHost](/get-started/app-host/). - -## Hosting integration - - - -### Add Deno app - -Use the `AddDenoApp` extension method to add a Deno application to your AppHost: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var denoApp = builder.AddDenoApp( - name: "deno-api", - workingDirectory: "../deno-app", - scriptPath: "main.ts", - args: ["--allow-net", "--allow-env"]) - .WithHttpEndpoint(port: 8000, env: "PORT"); - -builder.AddProject("api") - .WithReference(denoApp); - -builder.Build().Run(); -``` - -The `AddDenoApp` method accepts the following parameters: - -| Parameter | Description | -|-----------|-------------| -| `name` | The name of the resource in the Aspire dashboard. | -| `workingDirectory` | Path to the directory containing your Deno application. | -| `scriptPath` | Path to the Deno script to run, relative to the working directory. | -| `args` | Deno permission flags and other arguments passed at startup. | - -:::note -Deno requires explicit permissions for various operations. Common permission flags include: -- `--allow-net`: Network access -- `--allow-env`: Environment variables -- `--allow-read`: File system reading -- `--allow-write`: File system writing -::: - -### Add Deno task - -To run a task defined in `deno.json`, use the `AddDenoTask` extension method: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var denoApp = builder.AddDenoTask( - name: "deno-api", - workingDirectory: "../deno-app", - taskName: "start") - .WithHttpEndpoint(port: 8000, env: "PORT"); - -builder.Build().Run(); -``` - -This runs `deno task start` in the specified working directory. - -### Package installation - -To ensure packages are installed before running your Deno application, call `WithDenoPackageInstallation`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var denoApp = builder.AddDenoApp( - name: "deno-api", - workingDirectory: "../deno-app", - scriptPath: "main.ts", - args: ["--allow-net", "--allow-env"]) - .WithDenoPackageInstallation() - .WithHttpEndpoint(port: 8000, env: "PORT"); - -builder.Build().Run(); -``` - -:::note -Package installation requires a `deno.lock` file in your Deno project. If the file doesn't exist, run `deno install` in your Deno project directory to generate it. -::: - -### Configure HTTP endpoints - -Deno applications read the port to listen on from an environment variable. Use `WithHttpEndpoint` to expose a port and inject it into the process: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var denoApp = builder.AddDenoApp( - name: "deno-api", - workingDirectory: "../deno-app", - scriptPath: "main.ts", - args: ["--allow-net", "--allow-env"]) - .WithHttpEndpoint(port: 8000, env: "PORT"); - -builder.Build().Run(); -``` - -Inside your Deno application, read the `PORT` environment variable using `Deno.env.get`: - -```typescript title="main.ts" -const port = Number(Deno.env.get("PORT")) || 8000; - -Deno.serve({ port }, () => { - return new Response("Hello from Deno!"); -}); - -console.log(`Server listening on port ${port}`); -``` - -## See also - -- [Deno documentation](https://docs.deno.com/) -- [Aspire Community Toolkit on GitHub](https://github.com/CommunityToolkit/Aspire) -- [📦 CommunityToolkit.Aspire.Hosting.Deno on NuGet](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Deno) -- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx new file mode 100644 index 000000000..46c2989b6 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx @@ -0,0 +1,97 @@ +--- +title: Get started with Deno and Aspire +description: Run Deno applications with Aspire, model them as AppHost resources, and configure their local development environment. +--- + +import { + Badge, + LinkButton, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import denoIcon from '@assets/icons/deno-icon.png'; + + + +Deno logo + +The [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) Deno hosting integration adds Deno scripts and tasks to your [AppHost](/get-started/app-host/). Aspire starts the Deno process locally, shows it in the dashboard, and lets you connect it to the rest of your distributed application. + +## How the integration works + +The integration is a hosting integration: install it in the AppHost, then model each application with an `AddDenoApp` / `addDenoApp` resource or an `AddDenoTask` / `addDenoTask` resource. The resource runs the local `deno` command. You configure its working directory, permissions, arguments, endpoints, environment variables, and health checks in the AppHost. + +`AddDenoApp` runs a script with `deno run`; `AddDenoTask` runs a task from `deno.json` or `deno.jsonc` with `deno task`. Both resource types participate in service discovery and can be referenced by other resources. + +## Prerequisites + +- Install [Deno](https://docs.deno.com/runtime/getting_started/installation/) and ensure `deno` is available on your `PATH`. +- Install the [Aspire CLI](/get-started/install-cli/) and meet the [Aspire prerequisites](/get-started/prerequisites/). +- Create an AppHost in C# or TypeScript. + +## Add a Deno resource + +Add `CommunityToolkit.Aspire.Hosting.Deno` to your AppHost. Then add a Deno task or script resource: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var app = builder.AddDenoTask( + name: "web", + workingDirectory: "../web", + taskName: "dev") + .WithHttpEndpoint(env: "PORT") + .WithHttpHealthCheck("/"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const app = await builder + .addDenoTask('web', { + workingDirectory: '../web', + taskName: 'dev', + }) + .withHttpEndpoint({ env: 'PORT' }) + .withHttpHealthCheck({ path: '/' }); + +await builder.build().run(); +``` + + + + +Have the Deno application listen on the endpoint environment variable. For example, grant the `--allow-env` permission when an application reads `PORT`. + + + Set up Deno apps in the AppHost + + +## See also + +- [Deno documentation](https://docs.deno.com/) +- [Deno AppHost API reference](/integrations/frameworks/deno/deno-host/) +- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx new file mode 100644 index 000000000..cfbccc671 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx @@ -0,0 +1,215 @@ +--- +title: Set up Deno apps in the AppHost +description: Configure Deno script and task resources, permissions, endpoints, health checks, package installation, and publishing behavior in Aspire. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import InstallPackage from '@components/InstallPackage.astro'; +import LearnMore from '@components/LearnMore.astro'; +import { Image } from 'astro:assets'; +import denoIcon from '@assets/icons/deno-icon.png'; + + + +Deno logo + +This reference covers the Deno AppHost API from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). For an introduction, see [Get started with the Deno integration](/integrations/frameworks/deno/deno-get-started/). + +## Installation + +Install the hosting package in your AppHost: + + + +The Deno executable must be available on `PATH` when Aspire runs the resource. + +## Add a Deno script + +`AddDenoApp` / `addDenoApp` creates an executable resource that runs `deno run`, followed by permission flags, the script path, and application arguments. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddDenoApp( + name: "deno-api", + scriptPath: "main.ts", + workingDirectory: "../deno-api", + permissionFlags: ["--allow-env", "--allow-net"], + args: ["--verbose"]); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder.addDenoApp('deno-api', 'main.ts', { + workingDirectory: '../deno-api', + permissionFlags: ['--allow-env', '--allow-net'], + args: ['--verbose'], +}); + +await builder.build().run(); +``` + + + + +`name` identifies the dashboard resource. `scriptPath` is passed to `deno run`. `workingDirectory` is resolved from the AppHost directory; when omitted, it defaults to `../`. `permissionFlags` and `args` are optional arrays. Use Deno permission flags appropriate to the application, such as `--allow-net` for network access and `--allow-env` when it reads environment variables. + +Script resources set `DENO_ENV` to `development` in the development environment and `production` otherwise. They also configure the OTLP exporter. + +## Add a Deno task + +`AddDenoTask` / `addDenoTask` runs `deno task `, using the task configuration in the resource's working directory. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var web = builder.AddDenoTask( + name: "web", + workingDirectory: "../web", + taskName: "dev", + args: ["--host", "0.0.0.0"]); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const web = await builder.addDenoTask('web', { + workingDirectory: '../web', + taskName: 'dev', + args: ['--host', '0.0.0.0'], +}); + +await builder.build().run(); +``` + + + + +`taskName` defaults to `start`; the working-directory default is also `../`. Task resources run the `deno` command with `task`, the task name, and the supplied arguments. + +## Install Deno packages before startup + +`WithDenoPackageInstallation` / `withDenoPackageInstallation` adds a `deno install` setup resource named `-deno-install`. The application waits for that setup resource to complete. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddDenoApp("deno-api", "main.ts") + .WithDenoPackageInstallation(); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder + .addDenoApp('deno-api', 'main.ts') + .withDenoPackageInstallation(); + +await builder.build().run(); +``` + + + + +In C#, an overload also accepts a callback that configures the installer resource. That callback overload is not exported to TypeScript AppHosts. + +## Configure endpoints, environment, and health checks + +Deno resources are executable resources with endpoint, environment, argument, wait, and service-discovery support. Use the standard AppHost APIs to pass a listening port, configure additional environment variables, and define a probe: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddDenoApp( + "deno-api", + "main.ts", + permissionFlags: ["--allow-env", "--allow-net"]) + .WithHttpEndpoint(port: 8000, env: "PORT") + .WithEnvironment("LOG_LEVEL", "debug") + .WithHttpHealthCheck("/health"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder + .addDenoApp('deno-api', 'main.ts', { + permissionFlags: ['--allow-env', '--allow-net'], + }) + .withHttpEndpoint({ port: 8000, env: 'PORT' }) + .withEnvironment('LOG_LEVEL', 'debug') + .withHttpHealthCheck({ path: '/health' }); + +await builder.build().run(); +``` + + + + +The application must read the `PORT` variable and listen on that port. It must also have the Deno permissions required to read its environment and serve network traffic. `WithHttpHealthCheck` / `withHttpHealthCheck` makes Aspire poll the specified HTTP path. Add `WithEndpoint` / `withEndpoint` when you need an additional endpoint definition, as in the Toolkit Deno samples. + +## Resource actions and references + +The dashboard exposes the normal executable-resource lifecycle controls for Deno resources. Other AppHost resources can use `WithReference` / `withReference` and dependency APIs with a Deno resource because it supports service discovery. Add explicit endpoints before consumers need an address. + +## Publishing behavior + +`WithDenoPackageInstallation` only creates its installer resource in run mode. The installer is excluded from the application manifest and is not created during publishing. The integration does not implement a Deno-specific container build or publish artifact; provide deployment packaging appropriate for your Deno application. + + + For deployment guidance, see the [Aspire deployment overview](/deployment/). + + +## See also + +- [Deno documentation](https://docs.deno.com/) +- [📦 CommunityToolkit.Aspire.Hosting.Deno](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Deno) +- [Get started with the Deno integration](/integrations/frameworks/deno/deno-get-started/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/java.mdx b/src/frontend/src/content/docs/integrations/frameworks/java.mdx deleted file mode 100644 index b639fbe92..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/java.mdx +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Java integration -seoTitle: Java integration for Aspire AppHost and apps -description: Learn how to use the Aspire Java hosting integration from the Community Toolkit to run Spring Boot and other Java applications alongside your Aspire projects. ---- - -import { Badge } from '@astrojs/starlight/components'; -import InstallPackage from '@components/InstallPackage.astro'; -import { Image } from 'astro:assets'; -import javaIcon from '@assets/icons/java-icon.png'; - - - -Java logo - -This article is the reference for the Aspire Java hosting integration from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). It enumerates the AppHost APIs you use to model Java applications — including Spring Boot apps — in your [`AppHost`](/get-started/app-host/) project. - -:::note -TypeScript AppHost support for this integration is not yet available. All AppHost examples on this page are in C#. -::: - -## Hosting integration - - - -:::note -This integration requires the OpenTelemetry Java agent for observability support. Download the agent JAR and place it in the `./agents` directory relative to your AppHost project. Download from: [OpenTelemetry Java Agent releases](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases). -::: - -### Add Spring Boot app - -To add a Spring Boot application to your AppHost, use the `AddSpringApp` extension method: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var javaApp = builder.AddSpringApp( - name: "spring-api", - workingDirectory: "../spring-app", - otelAgentPath: "../agents/opentelemetry-javaagent.jar") - .WithHttpEndpoint(port: 8080); - -builder.AddProject("apiservice") - .WithReference(javaApp); - -builder.Build().Run(); -``` - -The `AddSpringApp` method accepts: -- **name**: The resource name shown in the Aspire dashboard. -- **workingDirectory**: The path to the directory containing your Spring Boot application. -- **otelAgentPath**: The path to the OpenTelemetry Java agent JAR file. - -### Container hosting - -For production scenarios, host Java applications in containers using `JavaAppContainerResourceOptions`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var javaApp = builder.AddSpringApp( - name: "spring-api", - new JavaAppContainerResourceOptions - { - OtelAgentPath = "../agents/opentelemetry-javaagent.jar", - ContainerImageName = "my-spring-app:latest", - ContainerRegistry = "myregistry.azurecr.io" - }) - .WithHttpEndpoint(port: 8080); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - -### Executable hosting - -For local development, run Java applications as executables using `JavaAppExecutableResourceOptions`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var javaApp = builder.AddSpringApp( - name: "spring-api", - new JavaAppExecutableResourceOptions - { - ApplicationName = "spring-app", - OtelAgentPath = "../agents/opentelemetry-javaagent.jar", - WorkingDirectory = "../spring-app" - }) - .WithHttpEndpoint(port: 8080); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - -### Configure endpoints - -Spring Boot applications use the `server.port` property to configure the port. Use `WithHttpEndpoint` to expose the endpoint to other resources in the AppHost: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var javaApp = builder.AddSpringApp( - "spring-api", - "../spring-app", - "../agents/opentelemetry-javaagent.jar") - .WithHttpEndpoint(port: 8080); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - -### Certificate trust (Linux and macOS) - -On Linux and macOS, add the following to your Spring Boot application's `application.properties` to trust the Aspire development certificates: - -```properties title="application.properties" -server.ssl.trust-store=/path/to/aspire/dev/certificate.p12 -server.ssl.trust-store-password=p@ssw0rd1 -``` - -For more information, see the [Spring Boot SSL documentation](https://docs.spring.io/spring-boot/reference/features/ssl.html). - -## Observability - -The Java integration uses the OpenTelemetry Java agent to automatically instrument your application and export telemetry to the Aspire dashboard. - -Download the OpenTelemetry Java agent and specify its path when calling `AddSpringApp`. For more information, see [OpenTelemetry Java instrumentation](https://opentelemetry.io/docs/languages/java/). - -## See also - -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Spring Boot documentation](https://spring.io/projects/spring-boot) -- [OpenTelemetry Java](https://opentelemetry.io/docs/languages/java/) -- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx new file mode 100644 index 000000000..d2baf00e3 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx @@ -0,0 +1,92 @@ +--- +title: Get started with Java and Aspire +description: Run Java applications with Aspire, model executable and container resources, and configure Maven or Gradle development workflows. +--- + +import { + Badge, + LinkButton, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import javaIcon from '@assets/icons/java-icon.png'; + + + +Java logo + +The [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) Java hosting integration adds Java executable and container applications to your [AppHost](/get-started/app-host/). It supports Maven and Gradle wrapper workflows, running an existing JAR, and container images. + +## How the integration works + +The integration is a hosting integration: install it in the AppHost, create a Java app resource, and apply a launch mode. An executable resource runs the local Java command, Maven wrapper, or Gradle wrapper from the configured project directory. A container resource runs an image. Both resource types can have endpoints, environment variables, health checks, and references configured through the AppHost. + +Build helpers create setup resources that the executable application waits for during local development. JVM arguments and optional OpenTelemetry Java-agent configuration are supplied through `JAVA_TOOL_OPTIONS`. + +## Prerequisites + +- Install a compatible [JDK](https://adoptium.net/) and ensure `java` is available on your `PATH` for executable resources. +- Include the Maven or Gradle wrapper in your Java project and ensure its script is executable when you use those launch modes. +- Install the [Aspire CLI](/get-started/install-cli/) and meet the [Aspire prerequisites](/get-started/prerequisites/). +- Download the [OpenTelemetry Java agent](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases) if you plan to configure an agent path. + +## Add a Java app + +Add `CommunityToolkit.Aspire.Hosting.Java` to the AppHost, then configure an executable Java application. This short example runs a Spring Boot application through its Maven wrapper: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddJavaApp("java-api", "../java-api") + .WithMavenGoal("spring-boot:run") + .WithHttpEndpoint(targetPort: 8080, env: "SERVER_PORT") + .WithHttpHealthCheck("/health"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder + .addJavaApp('java-api', '../java-api') + .withMavenGoal('spring-boot:run', []) + .withHttpEndpoint({ targetPort: 8080, env: 'SERVER_PORT' }) + .withHttpHealthCheck({ path: '/health' }); + +await builder.build().run(); +``` + + + + + + Set up Java apps in the AppHost + + +## See also + +- [Java documentation](https://dev.java/learn/) +- [Java AppHost API reference](/integrations/frameworks/java/java-host/) +- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx new file mode 100644 index 000000000..8e8b5ad56 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx @@ -0,0 +1,349 @@ +--- +title: Set up Java apps in the AppHost +description: Configure Java executable and container resources, Maven and Gradle commands, JVM settings, endpoints, health checks, and publishing behavior. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import InstallPackage from '@components/InstallPackage.astro'; +import LearnMore from '@components/LearnMore.astro'; +import { Image } from 'astro:assets'; +import javaIcon from '@assets/icons/java-icon.png'; + + + +Java logo + +This reference covers the Java AppHost API from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). For an introduction, see [Get started with the Java integration](/integrations/frameworks/java/java-get-started/). + +## Installation + +Install the hosting package in your AppHost: + + + +Executable Java resources require the Java command and, when used, the Maven or Gradle wrapper to be available from the resource's configured project directory. + +## Add an executable Java app + +`AddJavaApp` / `addJavaApp` creates a Java executable resource with a working directory relative to the AppHost directory. Configure it with a Maven or Gradle task, or add a JAR path. + +### Run a Maven or Gradle task + +`WithMavenGoal` / `withMavenGoal` and `WithGradleTask` / `withGradleTask` replace the executable command with the respective wrapper in run mode. Maven defaults to `mvnw` (`mvnw.cmd` on Windows), and Gradle defaults to `gradlew` (`gradlew.bat` on Windows). + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var mavenApp = builder.AddJavaApp("maven-api", "../maven-api") + .WithMavenGoal("spring-boot:run", "-Dspring-boot.run.profiles=dev"); + +var gradleApp = builder.AddJavaApp("gradle-api", "../gradle-api") + .WithGradleTask("bootRun", "--args=--spring.profiles.active=dev"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const mavenApp = await builder + .addJavaApp('maven-api', '../maven-api') + .withMavenGoal('spring-boot:run', ['-Dspring-boot.run.profiles=dev']); + +const gradleApp = await builder + .addJavaApp('gradle-api', '../gradle-api') + .withGradleTask('bootRun', ['--args=--spring.profiles.active=dev']); + +await builder.build().run(); +``` + + + + +Do not combine a Maven goal or Gradle task with a JAR path; the integration rejects that configuration. + +### Run a JAR + +Provide a JAR path relative to the resource working directory. The resource runs `java -jar ` followed by the application arguments. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var app = builder.AddJavaApp( + name: "java-api", + workingDirectory: "../java-api", + jarPath: "target/java-api.jar", + args: ["--spring.main.banner-mode=off"]); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const app = await builder.addJavaAppWithJar( + 'java-api', + '../java-api', + 'target/java-api.jar', + { args: ['--spring.main.banner-mode=off'] } +); + +await builder.build().run(); +``` + + + + +The TypeScript export is named `addJavaAppWithJar`. The Java executable resource also exposes its `JarPath` / `jarPath` property when you need to update the configured JAR path programmatically. + +## Build before running + +`WithMavenBuild` / `withMavenBuild` and `WithGradleBuild` / `withGradleBuild` add a child setup resource in run mode. The Java app waits for it to finish. Maven runs `clean package` by default and Gradle runs `clean build` by default; passing arguments replaces those defaults. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var mavenApp = builder.AddJavaApp("maven-api", "../maven-api", "target/api.jar") + .WithMavenBuild("-DskipTests"); + +var gradleApp = builder.AddJavaApp("gradle-api", "../gradle-api", "build/libs/api.jar") + .WithGradleBuild("-x", "test", "--parallel"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const mavenApp = await builder + .addJavaAppWithJar('maven-api', '../maven-api', 'target/api.jar') + .withMavenBuild(['-DskipTests']); + +const gradleApp = await builder + .addJavaAppWithJar('gradle-api', '../gradle-api', 'build/libs/api.jar') + .withGradleBuild(['-x', 'test', '--parallel']); + +await builder.build().run(); +``` + + + + +Use `WithWrapperPath` / `withWrapperPath` before a build or launch method to use a wrapper at a relative or absolute path instead of the platform default. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var app = builder.AddJavaApp("java-api", "../java-api") + .WithWrapperPath("tools/mvnw") + .WithMavenGoal("spring-boot:run"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const app = await builder + .addJavaApp('java-api', '../java-api') + .withWrapperPath('tools/mvnw') + .withMavenGoal('spring-boot:run', []); + +await builder.build().run(); +``` + + + + +## Configure JVM and OpenTelemetry options + +`WithJvmArgs` / `withJvmArgs` appends JVM options to `JAVA_TOOL_OPTIONS`, which works with JAR, Maven, Gradle, and container launches. `WithOtelAgent` / `withOtelAgent` configures the OTLP exporter; when you provide an agent JAR path, it also appends `-javaagent:` to `JAVA_TOOL_OPTIONS`. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var app = builder.AddJavaApp("java-api", "../java-api") + .WithMavenGoal("spring-boot:run") + .WithJvmArgs(["-Xms256m", "-Xmx512m"]) + .WithOtelAgent("../agents/opentelemetry-javaagent.jar"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const app = await builder + .addJavaApp('java-api', '../java-api') + .withMavenGoal('spring-boot:run', []) + .withJvmArgs(['-Xms256m', '-Xmx512m']) + .withOtelAgent({ agentPath: '../agents/opentelemetry-javaagent.jar' }); + +await builder.build().run(); +``` + + + + +Download the agent JAR before configuring its path. `WithOtelAgent` without a path configures the exporter but does not add a Java agent argument. + +## Add a Java container app + +`AddJavaContainerApp` / `addJavaContainerApp` models an existing container image and configures the OTLP exporter. Pass an optional image tag; configure endpoints and environment variables with standard container-resource APIs. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var app = builder.AddJavaContainerApp( + "java-api", + "ghcr.io/contoso/java-api", + imageTag: "1.0") + .WithJvmArgs(["-Djava.awt.headless=true"]) + .WithHttpEndpoint(targetPort: 8080, env: "SERVER_PORT"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const app = await builder + .addJavaContainerApp('java-api', 'ghcr.io/contoso/java-api', { + imageTag: '1.0', + }) + .withJvmArgs(['-Djava.awt.headless=true']) + .withHttpEndpoint({ targetPort: 8080, env: 'SERVER_PORT' }); + +await builder.build().run(); +``` + + + + +## Configure endpoints, environment, health checks, and references + +Java executable and container resources support standard AppHost endpoints, environment variables, health checks, waits, and service discovery. Pass Spring Boot's listening port through an endpoint environment variable, add a health-check path, and reference the resource from consumers: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddJavaApp("java-api", "../java-api") + .WithMavenGoal("spring-boot:run") + .WithHttpEndpoint(targetPort: 8080, env: "SERVER_PORT") + .WithEnvironment("SPRING_PROFILES_ACTIVE", "development") + .WithHttpHealthCheck("/actuator/health"); + +builder.AddProject("web") + .WithReference(api); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder + .addJavaApp('java-api', '../java-api') + .withMavenGoal('spring-boot:run', []) + .withHttpEndpoint({ targetPort: 8080, env: 'SERVER_PORT' }) + .withEnvironment('SPRING_PROFILES_ACTIVE', 'development') + .withHttpHealthCheck({ path: '/actuator/health' }); + +const web = await builder.addProject('web', '../Web/Web.csproj'); +await web.withReference(api); + +await builder.build().run(); +``` + + + + +The Java application is responsible for reading `SERVER_PORT` and listening on the endpoint target port. `WithHttpHealthCheck` / `withHttpHealthCheck` makes Aspire poll the configured path. Executable resources run `java` unless a Maven or Gradle task changes the command in run mode; build resources and application resources expose normal dashboard lifecycle controls. + +## Publishing behavior + +Maven and Gradle build helper resources are created only in run mode and are excluded from the application manifest. The integration does not generate a JAR, Dockerfile, or Java-specific publish artifact. For executable resources, arrange the JAR and runtime packaging in your deployment process. Container resources use the image you configured. + + + For deployment guidance, see the [Aspire deployment overview](/deployment/). + + +## Deprecated C# compatibility APIs + +The package retains C#-only compatibility APIs that are not exported to TypeScript AppHosts: + +- `AddJavaApp` and `AddSpringApp` overloads that accept `JavaAppContainerResourceOptions`; use `AddJavaContainerApp` instead. +- `AddJavaApp` and `AddSpringApp` overloads that accept `JavaAppExecutableResourceOptions`; use `AddJavaApp` with a JAR path, `WithJvmArgs`, `WithOtelAgent`, and explicit endpoints instead. +- `WithMavenBuild(MavenOptions)`; use `WithMavenBuild(params string[] args)` instead. + +Do not use these deprecated APIs in new applications. + +## See also + +- [Java documentation](https://dev.java/learn/) +- [OpenTelemetry Java instrumentation](https://opentelemetry.io/docs/zero-code/java/agent/) +- [📦 CommunityToolkit.Aspire.Hosting.Java](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Java) +- [Get started with the Java integration](/integrations/frameworks/java/java-get-started/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx deleted file mode 100644 index cb4bd65ef..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx +++ /dev/null @@ -1,424 +0,0 @@ ---- -title: Perl integration -seoTitle: Perl hosting integration for Aspire · Community Toolkit -description: Run Perl scripts and API servers in Aspire with the Community Toolkit hosting integration — cpanm, Carton, local::lib, and perlbrew support. ---- - -import { Badge, FileTree, Steps, TabItem, Tabs } from '@astrojs/starlight/components'; -import { Image } from 'astro:assets'; -import LearnMore from '@components/LearnMore.astro'; -import perlIcon from '@assets/icons/perl-096-1500.svg'; - - - -Perl Camel - -This document explains how key hosting API calls map to on-disk -directory layout, environment variable configuration, and runtime behavior. - -## Installation - -To start building an Aspire app that uses Meilisearch, install the [📦 CommunityToolkit.Aspire.Hosting.Perl](https://nuget.org/packages/CommunityToolkit.Aspire.Hosting.Perl) NuGet package: - - - - -```bash title="Terminal" -aspire add CommunityToolkit.Aspire.Hosting.Perl -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -Or, choose a manual installation approach: - -```csharp title="C# — AppHost.cs" -#:package CommunityToolkit.Aspire.Hosting.Meilisearch@* -``` - -```xml title="XML — AppHost.csproj" - -``` - - - - -```bash title="Terminal" -aspire add CommunityToolkit.Aspire.Hosting.Perl -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -This updates your `aspire.config.json` with the Meilisearch hosting integration package: - -```json title="aspire.config.json" ins={3} -{ - "packages": { - "CommunityToolkit.Aspire.Hosting.Perl": "*" - } -} -``` - - - - -## Add Perl resource - -Add a Perl script resource in your `AppHost.cs`: - -```csharp -var builder = DistributedApplication.CreateBuilder(args); - -builder.AddPerlScript("my-worker", "scripts", "Worker.pl") - .WithCpanMinus() - .WithPackage("Some::Module", skipTest: true) - .WithLocalLib("local"); - -builder.Build().Run(); -``` - -## Core concepts - -The integration provides two entry points for adding Perl resources: - -| Method | Purpose | -|--------|---------| -| `AddPerlScript(name, appDirectory, scriptName)` | Adds a Perl script (worker, CLI tool, etc.) | -| `AddPerlApi(name, appDirectory, scriptName)` | Adds a Perl API server (e.g., Mojolicious `daemon`) | - -Both create a `PerlAppResource` that appears in the Aspire dashboard. All subsequent configuration -methods (`.WithCpanMinus()`, `.WithLocalLib()`, etc.) chain off the resource builder. - -## The `appDirectory` Parameter - -`appDirectory` is the **anchor for all relative path resolution** in the integration. It determines: - -- The resource's `WorkingDirectory` — where Perl runs -- Where `WithLocalLib("local")` resolves to -- Where cpanfile discovery happens (for `WithProjectDependencies`) -- The base for the script path - -`appDirectory` is resolved relative to the **AppHost project directory** (the folder containing -the `.csproj`). - -### `"."` — AppHost-rooted - -When `appDirectory` is `"."`, the working directory is the AppHost project folder itself. Files like -`cpanfile`, `cpanfile.snapshot`, and the `local/` directory all live alongside the `.csproj`: - - - -- MyApp.AppHost - - AppHost.cs - - MyApp.AppHost.csproj - - cpanfile discovered here - - cpanfile.snapshot - - local WithLocalLib("local") resolves here - - lib/perl5 - - Properties -- scripts - - API.pl script path "../scripts/API.pl" - - - -### `"../scripts"` — sibling folder - -When `appDirectory` is `"../scripts"`, the working directory shifts to a sibling `scripts/` folder. -Everything resolves relative to that folder: - - - -- MyApp.AppHost - - AppHost.cs - - MyApp.AppHost.csproj - - Properties/ -- scripts working directory - - Worker.pl script path "Worker.pl" - - local WithLocalLib("local") resolves here - - lib/perl5 - - - -:::note -**Key insight:** The script path in `AddPerlScript` / `AddPerlApi` is relative to `appDirectory`, and so is everything else — `WithLocalLib`, cpanfile discovery, and the process working directory. -::: - -## WithLocalLib - -```csharp -.WithLocalLib("local") // relative path — resolved against appDirectory -.WithLocalLib("/opt/lib") // rooted Unix-style path — used as-is -.WithLocalLib("C:\\perl-lib") // rooted Windows path — used as-is -``` - -`WithLocalLib` configures [local::lib](https://metacpan.org/pod/local::lib)-style module isolation. -The `path` parameter is resolved **relative to the resource's working directory** (`appDirectory`), -not relative to the AppHost project, unless the path is already rooted. - -Implementation note: `WithLocalLib` path resolution uses `Path.IsPathRooted(configuredPath)`. -If `true`, the value is used directly. If `false`, it is combined with the resource working -directory and converted to an absolute path. - -### What it sets - -| Environment Variable | Value | -|---------------------|-------| -| `PERL5LIB` | `/lib/perl5` | -| `PERL_LOCAL_LIB_ROOT` | `` | -| `PERL_MM_OPT` | `INSTALL_BASE=` | -| `PERL_MB_OPT` | `--install_base ` | - -These ensure that: -- Perl finds modules in the local directory at runtime (`@INC`) -- Package managers install modules into the local directory -- No `sudo` or system-level permissions required - -### Resolution examples - -| `appDirectory` | `WithLocalLib(...)` | Resolved absolute path | -|----------------|---------------------|----------------------| -| `"."` | `"local"` | `/local` | -| `"../scripts"` | `"local"` | `/../scripts/local` | -| `"."` | `"/opt/perl-libs"` | `/opt/perl-libs` (Linux/macOS) | -| `"."` | `"C:\\perl-libs"` | `C:\\perl-libs` (Windows) | - -## Package management - -While I highly recommend you use cpanm or Carton, the integration aims to support three package managers and two installation strategies: - -| Package Manager | Individual Packages | Project Dependencies | -|----------------|-------------------|---------------------| -| **cpan** (default) | ✅ `.WithPackage("Module")` | ❌ Not supported (auto-switches to cpanm when calling `.WithProjectDependencies()`) | -| **cpanm** (App::cpanminus) | ✅ `.WithCpanMinus().WithPackage("Module")` | ✅ `.WithCpanMinus().WithProjectDependencies()` | -| **Carton** | ❌ Not supported | ✅ `.WithCarton().WithProjectDependencies()` | - -:::tip -The default package manager is `cpan`, but it is automatically switched to `cpanm` when -`WithProjectDependencies()` is called, since `cpan` does not support `--installdeps`. -`WithLocalLib()` will also currently swap to `cpanm` because it wasn't clear to me at time of release how to integrate it with cpan. -::: - -### WithCpanMinus + WithPackage - -Installs individual modules by name before the application starts. - -```csharp -builder.AddPerlScript("worker", "../scripts", "Worker.pl") - .WithCpanMinus() - .WithPackage("OpenTelemetry::SDK", skipTest: true) - .WithLocalLib("local"); -``` - -**What happens at startup:** - - - -1. A child installer resource runs `cpanm --notest --local-lib /local OpenTelemetry::SDK` -2. The module is installed into `scripts/local/lib/perl5/` -3. After installation, the main script starts with `PERL5LIB` pointing to the local directory - - - -**Resulting directory structure:** - - - -- my-example - - MyExample.AppHost/ - - AppHost.cs - - MyExample.AppHost.csproj - - scripts working directory (appDirectory = "../scripts") - - Worker.pl - - local - - lib - - perl5 - - OpenTelemetry/ - - SDK.pm - - - -**Options:** - -| Parameter | Effect | -|-----------|--------| -| `force: true` | Passes `--force` — reinstalls even if already present | -| `skipTest: true` | Passes `--notest` — skips running the module's test suite | - -### WithCpanMinus + WithProjectDependencies - -Installs all modules listed in a `cpanfile` in the working directory. - -```csharp -builder.AddPerlApi("api", ".", "../scripts/API.pl") - .WithCpanMinus() - .WithProjectDependencies() - .WithLocalLib("local"); -``` - -**What happens at startup:** - - - -1. The integration looks for `cpanfile` in the working directory -2. Runs `cpanm --installdeps --notest .` (with `--local-lib` if configured) -3. All dependencies from the cpanfile are installed - - - -**Expected cpanfile location:** `/cpanfile` - -### WithCarton + WithProjectDependencies - -[Carton](https://metacpan.org/pod/Carton) is a dependency manager for Perl that provides -reproducible builds via a lock file (`cpanfile.snapshot`). - -```csharp -builder.AddPerlApi("api", ".", "../scripts/API.pl") - .WithCarton() - .WithProjectDependencies(cartonDeployment: false) - .WithLocalLib("local"); -``` - -**What happens at startup:** - - - -1. The integration looks for `cpanfile` and optionally `cpanfile.snapshot` in the working directory -2. Runs `carton install` (or `carton install --deployment` if `cartonDeployment: true`) -3. Carton creates `local/` adjacent to the `cpanfile` - - - -**Deployment mode (`cartonDeployment: true`):** Installs exact versions from `cpanfile.snapshot`, -ensuring production builds match development. Fails if the snapshot is missing or out of date. - -**Resulting directory structure (appDirectory = "."):** - - - -- my-example - - MyApp.AppHost working directory (appDirectory = ".") - - AppHost.cs - - MyApp.AppHost.csproj - - cpanfile - - cpanfile.snapshot - - local - - lib - - perl5 - - Mojolicious - - scripts - - API.pl script path "../scripts/API.pl" - - - -:::important -Carton only supports project-level dependency installation. Calling `.WithPackage()` after `.WithCarton()` will throw an `InvalidOperationException`. If you need to install individual modules alongside Carton-managed dependencies, use `.WithCpanMinus()` on a separate resource. -::: - -## WithPerlbrewEnvironment - -[Perlbrew](https://perlbrew.pl/) manages multiple Perl installations. This method configures the -resource to use a specific perlbrew-managed Perl version. - -```csharp -builder.AddPerlScript("perlbrew-worker", "../scripts", "Worker.pl") - .WithPerlbrewEnvironment("perl-5.42.0"); -``` - -**What it configures:** -- Resolves the Perl binary from the perlbrew installation -- Sets `PERLBREW_ROOT`, `PERLBREW_PERL`, and `PERLBREW_HOME` -- Prepends the perlbrew `bin/` to `PATH` - -**Interaction with WithLocalLib:** If `.WithLocalLib("local")` is chained, modules are installed -into the local directory, not the perlbrew tree. This keeps the perlbrew installation clean and -allows per-project isolation. `WithLocalLib` is optional when using perlbrew. - -:::note -Perlbrew is Linux-only. On Windows, the integration will display a notification recommending [Berrybrew](https://github.com/stevieb9/berrybrew). Windows support for Berrybrew is on the roadmap. -::: - -## Common Pitfalls - -### WithLocalLib resolves relative to `appDirectory`, not the AppHost - -```csharp -// appDirectory = "../scripts", WithLocalLib("local") -// ✅ Resolves to: scripts/local/ -// ❌ Does NOT resolve to: MyApp.AppHost/local/ -``` - -If you expect the `local/` folder next to your `.csproj`, set `appDirectory` to `"."`. - -### Choosing to skip WithLocalLib modifies shared Perl installs - -It is valid to skip `WithLocalLib` if you intentionally want a shared/global module install. -That can be useful for common libraries on dev machines. - -The tradeoff is that installs target your platform Perl distribution instead of a project-local -folder. In practice this often means: - -- Linux (especially OS-managed Perl): writes to system or user Perl paths and may require elevated permissions -- Windows: writes into the active Strawberry Perl or ActiveState Perl environment - -This can be convenient, but it can also create drift across machines and affect unrelated projects. -Proceed with caution. - -### Mixing WithCarton and WithPackage - -Carton manages all dependencies through `cpanfile`. Calling `.WithPackage()` after `.WithCarton()` -will throw an `InvalidOperationException`: - -```csharp -// ❌ This throws — Carton does not support individual module installation -builder.AddPerlApi("api", ".", "api.pl") - .WithCarton() - .WithPackage("Some::Module"); - -// ✅ Instead, add the module to your cpanfile: -// requires 'Some::Module'; -``` - -### Script path is relative to `appDirectory` - -The `scriptName` parameter is resolved relative to `appDirectory`. Don't include the `appDirectory` -in the script path: - -```csharp -// ❌ Double-nests the path -builder.AddPerlScript("worker", "../scripts", "../scripts/Worker.pl"); - -// ✅ Correct — script path is relative to appDirectory -builder.AddPerlScript("worker", "../scripts", "Worker.pl"); -``` - -### cpanfile must be in the working directory - -`WithProjectDependencies` looks for `cpanfile` in the resource's working directory (`appDirectory`). -If your cpanfile is in a different location, adjust `appDirectory` accordingly. - -### cpanfile example - -Use a `cpanfile` to declare project dependencies for `WithProjectDependencies()`. - -```perl -requires 'Mojolicious', '>= 9.0'; -requires 'OpenTelemetry::SDK'; - -on 'test' => sub { - requires 'Test::More', '>= 1.302190'; -}; -``` - -Further reading: -- [CPAN::cpanfile reference](https://github.com/miyagawa/cpanfile/blob/master/README.md) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx new file mode 100644 index 000000000..89f51c232 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx @@ -0,0 +1,118 @@ +--- +title: Get started with the Perl hosting integration +description: Run Perl scripts, APIs, modules, and executables in Aspire with local dependencies, dashboard visibility, and container publishing. +--- + +import { + Badge, + LinkButton, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import perlIcon from '@assets/icons/perl-096-1500.svg'; + + + +Perl Camel + +The Aspire Community Toolkit Perl hosting integration runs Perl applications alongside the other resources in your AppHost. It models a Perl process as a first-class resource, manages its working directory and dependency installers, and supports local development and Dockerfile-based publishing. + +## How the integration fits together + +The hosting package belongs in the AppHost. It creates an executable resource for your Perl application, while your project retains its scripts, modules, and dependency files. + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group perl(logos:perl)[Perl project] + + service hosting(server)[Perl hosting integration] in apphost + service resource(logos:perl)[Perl app resource] in apphost + service runtime(logos:perl)[Perl runtime] in perl + service app(logos:perl)[Perl application] in perl + + hosting:R --> L:resource + resource:R --> L:runtime + runtime:R --> L:app +``` + +## Prerequisites + +- Install [Perl](https://www.perl.org/get.html) and ensure `perl` and `cpan` are on `PATH`. +- Install `cpanm` when you use `WithCpanMinus`, `WithLocalLib`, or project dependency installation. Install `carton` when you use Carton. +- Install the [Aspire CLI](/get-started/install-cli/) and create an AppHost. + +:::note +Perlbrew support is Linux-only. On Windows, use a supported Perl distribution; configuring perlbrew causes the resource to fail before it starts. +::: + +## Setup + +### Add the hosting package + +Add `CommunityToolkit.Aspire.Hosting.Perl` to your AppHost. The [Perl hosting reference](/integrations/frameworks/perl/perl-host/#installation) includes package installation options. + +### Add a Perl resource + +Add a script resource and use a project-local module directory: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddPerlScript("worker", "../perl-worker", "worker.pl") + .WithLocalLib("local"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const worker = await builder.addPerlScript( + 'worker', + '../perl-worker', + 'worker.pl' +); +await worker.withLocalLib({ path: 'local' }); + +await builder.build().run(); +``` + + + + +### Configure dependencies and endpoints + +The resource's application directory is its working directory. Put a `cpanfile` there when you want Aspire to install project dependencies, and add an HTTP endpoint for a web API that listens on a port. + + + Set up Perl in the AppHost + + +## See also + +- [Perl documentation](https://perldoc.perl.org/) +- [Perl hosting reference](/integrations/frameworks/perl/perl-host/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx new file mode 100644 index 000000000..b9a9554b1 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx @@ -0,0 +1,321 @@ +--- +title: Set up Perl apps in the Aspire AppHost +seoTitle: Perl application hosting integration for Aspire +description: Configure Perl application resources in Aspire, including entrypoints, package managers, local libraries, endpoints, environment, and publishing. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import LearnMore from '@components/LearnMore.astro'; +import perlIcon from '@assets/icons/perl-096-1500.svg'; + + + +Perl Camel + +This reference describes the Community Toolkit Perl hosting integration APIs for the Aspire [AppHost](/get-started/app-host/). If you're new to the integration, start with [Get started with the Perl integration](/integrations/frameworks/perl/perl-get-started/). + +## Installation + +Add [📦 CommunityToolkit.Aspire.Hosting.Perl](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Perl) to the AppHost: + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Perl +``` + +Or add the package manually: + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.Perl@* +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Perl +``` + +The command adds the package to `aspire.config.json`: + +```json title="aspire.config.json" +{ + "packages": { + "CommunityToolkit.Aspire.Hosting.Perl": "*" + } +} +``` + + + + + + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the + command reference. + + +## Add a Perl resource + +Each `AddPerl*` / `addPerl*` method accepts a resource name, an application directory, and an entrypoint. A relative application directory is resolved from the AppHost project directory and becomes the process working directory. Script paths are then resolved relative to that directory. + +| API | Local command and arguments | +| ----------------------------------------- | ---------------------------------------------- | +| `AddPerlScript` / `addPerlScript` | `perl -s ` | +| `AddPerlApi` / `addPerlApi` | `perl daemon` | +| `AddPerlModule` / `addPerlModule` | `perl -M -e "->run()"` | +| `AddPerlExecutable` / `addPerlExecutable` | Runs `` directly | + + + + +```csharp title="AppHost.cs" +var script = builder.AddPerlScript("worker", "../perl-worker", "worker.pl"); +var api = builder.AddPerlApi("api", "../perl-api", "app.pl"); +var module = builder.AddPerlModule("module-worker", "../perl-module", "MyApp::Worker"); +var executable = builder.AddPerlExecutable("packed-app", "../perl-bin", "my-app"); +``` + + + + +```typescript title="apphost.mts" +const script = await builder.addPerlScript( + 'worker', + '../perl-worker', + 'worker.pl' +); +const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); +const module = await builder.addPerlModule( + 'module-worker', + '../perl-module', + 'MyApp::Worker' +); +const executable = await builder.addPerlExecutable( + 'packed-app', + '../perl-bin', + 'my-app' +); +``` + + + + +All entrypoints require `perl` and `cpan` to be available. Aspire adds the standard executable-resource lifecycle actions and process logs; the integration doesn't add a Perl-specific dashboard command. `WithCpanMinus` and `WithCarton` add their own command requirement checks. + +## Configure endpoints, arguments, and environment + +Perl resources don't add an HTTP endpoint or health check automatically. For an API, configure the application to listen on a port and add the standard AppHost endpoint. Use normal resource APIs such as `WithArgs` / `withArgs`, `WithReference` / `withReference`, and `WaitFor` / `waitFor` to supply arguments and model dependencies. + + + + +```csharp title="AppHost.cs" +var api = builder.AddPerlApi("api", "../perl-api", "app.pl") + .WithHttpEndpoint(port: 3000, env: "PORT"); +``` + + + + +```typescript title="apphost.mts" +const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); +await api.withHttpEndpoint({ port: 3000, env: 'PORT' }); +``` + + + + +The application must honor the configured port itself. For example, configure your Mojolicious or Dancer application to read `PORT`; adding an endpoint doesn't change the framework's listener arguments. + +Every Perl resource configures OTLP export and sets `OTEL_TRACES_EXPORTER`, `OTEL_LOGS_EXPORTER`, `OTEL_METRICS_EXPORTER`, and their `OTEL_PERL_*` equivalents to `otlp`. It sets `OTEL_EXPORTER_OTLP_PROTOCOL` and `OTEL_PERL_EXPORTER_OTLP_PROTOCOL` to `http/protobuf`. + +### Configure a local::lib + +`WithLocalLib` / `withLocalLib` isolates modules in a local directory. Relative paths are resolved from `appDirectory`; rooted paths are used as supplied. The default path is `local`. + +It sets `PERL5LIB` to `/lib/perl5`, `PERL_LOCAL_LIB_ROOT` to ``, `PERL_MM_OPT` to `INSTALL_BASE=`, and `PERL_MB_OPT` to `--install_base `. If CPAN is active, the integration changes to cpanm because CPAN doesn't support the needed `--local-lib` option. + + + + +```csharp title="AppHost.cs" +var worker = builder.AddPerlScript("worker", "../perl-worker", "worker.pl") + .WithLocalLib("local"); +``` + + + + +```typescript title="apphost.mts" +const worker = await builder.addPerlScript( + 'worker', + '../perl-worker', + 'worker.pl' +); +await worker.withLocalLib({ path: 'local' }); +``` + + + + +### Trust development certificates + +`WithPerlCertificateTrust` / `withPerlCertificateTrust` is experimental. When Aspire provides a certificate bundle, it sets `SSL_CERT_FILE`, `PERL_LWP_SSL_CA_FILE`, and `MOJO_CA_FILE` on the app and its dependency installers. + + + + +```csharp title="AppHost.cs" +#pragma warning disable CTASPIREPERL001 +api.WithPerlCertificateTrust(); +#pragma warning restore CTASPIREPERL001 +``` + + + + +```typescript title="apphost.mts" +await api.withPerlCertificateTrust(); +``` + + + + +## Install dependencies + +The default package manager is CPAN. `WithPackage` / `withPackage` creates a child installer resource in run mode and makes the Perl app wait for it to complete. Use `force` to force an install and `skipTest` to skip package tests. + + + + +```csharp title="AppHost.cs" +var api = builder.AddPerlApi("api", "../perl-api", "app.pl") + .WithCpanMinus() + .WithPackage("Mojolicious", skipTest: true); +``` + + + + +```typescript title="apphost.mts" +const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); +await api.withCpanMinus(); +await api.withPackage('Mojolicious', { skipTest: true }); +``` + + + + +`WithCpanMinus` / `withCpanMinus` selects cpanm. With cpanm, per-package installers use `--force` and `--notest` for the corresponding options; with the default CPAN manager, they use `-f` and `-T`. + +### Install dependencies from a cpanfile + +`WithProjectDependencies` / `withProjectDependencies` creates one project installer in run mode. It expects `cpanfile` in the working directory: + +- CPAN is automatically changed to cpanm, which runs `cpanm --installdeps --notest .`. +- Carton runs `carton install`. Set `cartonDeployment` to add `--deployment`; this requires `cpanfile.snapshot`. +- A project installer runs before individual package installers, and the application waits for them all to complete. + +When the application directory contains `cpanfile`, `Makefile.PL`, or `Build.PL`, the integration automatically configures project dependency installation in run mode. + + + + +```csharp title="AppHost.cs" +var api = builder.AddPerlApi("api", "../perl-api", "app.pl") + .WithCpanMinus() + .WithProjectDependencies(); + +var worker = builder.AddPerlScript("worker", "../perl-worker", "worker.pl") + .WithCarton() + .WithProjectDependencies(cartonDeployment: true); +``` + + + + +```typescript title="apphost.mts" +const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); +await api.withCpanMinus(); +await api.withProjectDependencies(); + +const worker = await builder.addPerlScript( + 'worker', + '../perl-worker', + 'worker.pl' +); +await worker.withCarton(); +await worker.withProjectDependencies({ cartonDeployment: true }); +``` + + + + +`WithCarton` / `withCarton` and `WithPackage` / `withPackage` can't be combined. Carton manages dependencies through the `cpanfile`; add the module there instead. + +## Use perlbrew + +`WithPerlbrew` / `withPerlbrew` is an alias for `WithPerlbrewEnvironment` / `withPerlbrewEnvironment`. Both select a perlbrew version, accepting `5.40.0` or `perl-5.40.0`, and optionally accept the perlbrew root. The default root comes from `PERLBREW_ROOT` or `~/perl5/perlbrew`. + +The integration switches the command to the selected Perl executable, sets `PERLBREW_ROOT`, `PERLBREW_PERL`, and `PERLBREW_HOME`, and prepends the Perl bin directory to `PATH`. `WithLocalLib` remains useful to keep project modules separate from the perlbrew installation. + +:::caution +Perlbrew is Linux-only. On Windows, the resource displays a notification and fails before starting. Use a Windows Perl distribution instead. +::: + + + + +```csharp title="AppHost.cs" +var worker = builder.AddPerlScript("worker", "../perl-worker", "worker.pl") + .WithPerlbrew("5.40.0", perlbrewRoot: "/opt/perlbrew"); + +var api = builder.AddPerlApi("api", "../perl-api", "app.pl") + .WithPerlbrewEnvironment("perl-5.40.0", perlbrewRoot: "/opt/perlbrew"); +``` + + + + +```typescript title="apphost.mts" +const worker = await builder.addPerlScript( + 'worker', + '../perl-worker', + 'worker.pl' +); +await worker.withPerlbrew('5.40.0', { perlbrewRoot: '/opt/perlbrew' }); + +const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); +await api.withPerlbrewEnvironment('perl-5.40.0', { + perlbrewRoot: '/opt/perlbrew', +}); +``` + + + + +## Publish Perl apps + +In publish mode, Perl resources emit a generated Dockerfile. Dependency installer child resources exist only in run mode and are excluded from the manifest, so declare publish dependencies in `cpanfile`. + +- The default cpanm Dockerfile uses `perl:5-slim`, installs cpanm, runs `cpanm --installdeps --notest .`, and starts the configured entrypoint. +- Carton uses a `perl:5` build stage and a `perl:5-slim` runtime stage. Publish mode uses `carton install --deployment` by default, unless configured otherwise. +- `WithLocalLib` carries `PERL5LIB` and `PERL_LOCAL_LIB_ROOT` into the generated image. +- A script, API, module, or executable retains its corresponding entrypoint form in the generated image. + +## See also + +- [Get started with the Perl integration](/integrations/frameworks/perl/perl-get-started/) +- [Perl documentation](https://perldoc.perl.org/) +- [CPAN::cpanfile reference](https://github.com/miyagawa/cpanfile/blob/master/README.md) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell.mdx deleted file mode 100644 index eac07ec46..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell.mdx +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: PowerShell integration -seoTitle: "PowerShell integration for Aspire: hosting and client wiring" -description: Learn about the Aspire hosting integration for PowerShell scripts — orchestrate provisioning scripts, share parameters, and run PowerShell tasks alongside your apps. ---- - -import { Badge } from '@astrojs/starlight/components'; -import InstallPackage from "@components/InstallPackage.astro"; -import { Image } from 'astro:assets'; -import powershellIcon from '@assets/icons/powershell-icon.png'; - -PowerShell logo - -The Aspire PowerShell hosting integration enables you to run PowerShell Core (pwsh) scripts alongside your Aspire projects in the app host. This integration allows you to script your resources, reference connection strings, access live resources, and leverage the full power of PowerShell within your distributed application. - - - -:::note -This integration requires PowerShell Core (pwsh) 7.4 or later to be installed on your system and available in your `PATH`. For installation instructions, see [Install PowerShell](https://learn.microsoft.com/powershell/scripting/install/installing-powershell). -::: - -:::note -TypeScript AppHost support for this integration isn't yet available. -::: - -## Hosting integration - - - -### Add PowerShell resource - -In your AppHost, call `AddPowerShell` to register a PowerShell resource. Provide the resource name that appears in the Aspire dashboard: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var storage = builder.AddAzureStorage("storage").RunAsEmulator(); -var blob = storage.AddBlobs("myblob"); - -var ps = builder.AddPowerShell("ps") - .WithReference(blob) - .WaitFor(storage); - -builder.Build().Run(); -``` - -### Add scripts - -To execute PowerShell scripts within your resource, use the `AddScript` method: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var ps = builder.AddPowerShell("ps"); - -var script1 = ps.AddScript("script1", """ - param($name) - - Write-Information "Hello, $name" - Write-Information "`$myblob is $myblob" - - az storage container create --connection-string $myblob -n demo - az storage blob upload --connection-string $myblob -c demo --file ./scripts/script.ps1 - - Write-Information "Blob uploaded" -""").WithArgs("world"); - -var script2 = ps.AddScript("script2", """ - & ./scripts/script.ps1 @args -""") - .WithArgs(2, 3) - .WaitForCompletion(script1); - -builder.Build().Run(); -``` - -The `AddScript` method requires: -- **name**: The name of the script resource in the Aspire dashboard. -- **script**: The PowerShell script content to execute. - -### References and dependencies - -Use `WithReference` to pass connection strings and resource references to your PowerShell scripts. Referenced resources are available as variables in your script scope: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var storage = builder.AddAzureStorage("storage").RunAsEmulator(); -var blob = storage.AddBlobs("myblob"); - -var ps = builder.AddPowerShell("ps") - .WithReference(blob); // The $myblob variable is now available in scripts - -var script = ps.AddScript("demo", """ - Write-Information "Connection string: $myblob" -"""); - -builder.Build().Run(); -``` - -Use `WaitFor` to specify that a PowerShell resource should wait for other resources to be ready before executing: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var storage = builder.AddAzureStorage("storage").RunAsEmulator(); - -var ps = builder.AddPowerShell("ps") - .WaitFor(storage); - -builder.Build().Run(); -``` - -### Custom arguments - -Pass arguments to your PowerShell scripts using the `WithArgs` method: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var ps = builder.AddPowerShell("ps"); - -var script = ps.AddScript("process-data", """ - param($count, $name) - - Write-Information "Processing $count items for $name" -""").WithArgs(5, "demo"); - -builder.Build().Run(); -``` - -Scripts can define parameters using PowerShell's `param()` block and receive arguments passed via `WithArgs`. - -### Script execution order - -Control the execution order of scripts using `WaitForCompletion`. A script that calls `WaitForCompletion` will not run until the referenced script completes: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var ps = builder.AddPowerShell("ps"); - -var script1 = ps.AddScript("setup", """ - Write-Information "Setting up resources" - "setup-data.txt" | Set-Content "ready" -"""); - -var script2 = ps.AddScript("process", """ - Write-Information "Processing after setup" -""").WaitForCompletion(script1); - -builder.Build().Run(); -``` - -### Working directory - -Scripts execute in the context of your app host's working directory. You can access files relative to this directory within your scripts: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var ps = builder.AddPowerShell("ps"); - -var script = ps.AddScript("file-ops", """ - $pwd | Write-Information - Get-ChildItem ./scripts -"""); - -builder.Build().Run(); -``` - -## Debugging - -While your app host is running a script that contains a `Wait-Debugger` call, you can attach a PowerShell debugger to debug the script interactively. - -Open a terminal with PowerShell Core (pwsh) 7.4 or later and use the following commands: - -```powershell -Get-PSHostProcessInfo -Enter-PSHostProcess -Id -Get-Runspace -Debug-Runspace -Id -``` - -For more information about PowerShell debugging, see [Enter-PSHostProcess documentation](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/enter-pshostprocess?view=powershell-7.5). - -## See also - -- [PowerShell documentation](https://learn.microsoft.com/powershell/) -- [Enter-PSHostProcess documentation](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/enter-pshostprocess?view=powershell-7.5) -- [📦 CommunityToolkit.Aspire.Hosting.PowerShell NuGet package](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.PowerShell) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx new file mode 100644 index 000000000..19bbe2d89 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx @@ -0,0 +1,100 @@ +--- +title: Get started with the PowerShell integration +description: Use the Community Toolkit PowerShell integration to run managed scripts, model dependencies, and monitor their lifecycle in Aspire. +--- + +import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import powershellIcon from '@assets/icons/powershell-icon.png'; + +PowerShell logo + + + +The Community Toolkit PowerShell hosting integration runs PowerShell scripts in an in-process runspace pool that Aspire manages. Model setup, provisioning, and administrative scripts alongside your application resources, view their logs and states in the dashboard, and make later scripts wait for earlier ones to finish. + +## How the pieces fit together + +The integration is a hosting integration installed in your AppHost. A PowerShell runspace pool resource hosts one or more script resources. Aspire starts the pool, starts each script after its dependencies are ready, and reports the pool and script lifecycle in the dashboard. + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group scripts(server)[PowerShell resources] + + service hosting(server)[PowerShell hosting integration] in apphost + service pool(server)[Runspace pool] in scripts + service script(server)[Script resource] in scripts + + hosting:R --> L:pool + pool:R --> L:script +``` + +## Prerequisites + +- Create an [Aspire AppHost](/get-started/app-host/) in C# or TypeScript. +- Optionally install [PowerShell](https://learn.microsoft.com/powershell/scripting/install/installing-powershell) to develop and test scripts outside the AppHost. The integration runs scripts in-process through the PowerShell SDK, so it doesn't invoke `pwsh`. + + + +1. ### Install the hosting package + + Add `CommunityToolkit.Aspire.Hosting.PowerShell` to your AppHost. You can use `aspire add communitytoolkit-powershell` or install the NuGet package directly. + +2. ### Add a pool and a script + + Add a named PowerShell pool, then add a script to it. The following script appears as a resource in the dashboard. + + ```csharp title="AppHost.cs" + var builder = DistributedApplication.CreateBuilder(args); + + var scripts = builder.AddPowerShell("scripts"); + scripts.AddScript("setup", """ + Write-Information "Preparing the application" + """); + + builder.Build().Run(); + ``` + + ```typescript title="apphost.mts" + import { createBuilder } from './.aspire/modules/aspire.mjs'; + + const builder = await createBuilder(); + + const scripts = await builder.addPowerShell('scripts'); + await scripts.addScript( + 'setup', + 'Write-Information "Preparing the application"' + ); + + await builder.build().run(); + ``` + +3. ### Configure scripts in the AppHost + + Configure arguments, dependencies, connection-string variables, and lifecycle behavior in the [PowerShell AppHost reference](/integrations/frameworks/powershell/powershell-host/). + + + Configure PowerShell resources + + + + +## See also + +- [PowerShell documentation](https://learn.microsoft.com/powershell/) +- [PowerShell AppHost reference](/integrations/frameworks/powershell/powershell-host/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx new file mode 100644 index 000000000..b8ff0e606 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx @@ -0,0 +1,231 @@ +--- +title: Configure PowerShell scripts in the AppHost +description: Configure PowerShell runspace pools, scripts, arguments, dependencies, dashboard actions, and lifecycle behavior in Aspire. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import powershellIcon from '@assets/icons/powershell-icon.png'; + +PowerShell logo + + + +This reference describes the Community Toolkit PowerShell hosting integration. If you are new to it, begin with [Get started with the PowerShell integration](/integrations/frameworks/powershell/powershell-get-started/). + +:::note[Prerequisites] +Add the `CommunityToolkit.Aspire.Hosting.PowerShell` package to your AppHost. The integration hosts the PowerShell SDK in-process and doesn't require the `pwsh` executable. +::: + +## Install the package + + + + +```bash title="Terminal" +aspire add communitytoolkit-powershell +``` + +Or add [📦 CommunityToolkit.Aspire.Hosting.PowerShell](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.PowerShell) to the AppHost project. + + + + +```bash title="Terminal" +aspire add communitytoolkit-powershell +``` + +This adds the package to `aspire.config.json` and generates the TypeScript AppHost module. + + + + +## Add a runspace pool + +`AddPowerShell` / `addPowerShell` adds a runspace-pool resource. The resource name is shown in the dashboard. By default, the pool uses `ConstrainedLanguage` mode with one to five runspaces. + + + + +```csharp title="AppHost.cs" +using System.Management.Automation; + +var builder = DistributedApplication.CreateBuilder(args); + +var scripts = builder.AddPowerShell( + name: "scripts", + languageMode: PSLanguageMode.FullLanguage, + minRunspaces: 2, + maxRunspaces: 8); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const scripts = await builder.addPowerShell('scripts', { + languageMode: 'FullLanguage', + minRunspaces: 2, + maxRunspaces: 8, +}); + +await builder.build().run(); +``` + + + + +Use the least-permissive language mode appropriate for the scripts you run. The TypeScript API accepts the language-mode name as a string. Invalid names fail while Aspire constructs the AppHost. + +## Add scripts and arguments + +`AddScript` / `addScript` creates a child script resource. Aspire parses the script when the AppHost is built, starts it after the pool is running, and streams output, errors, warnings, information, verbose, and debug records to the resource logs. + +Use `WithArgs` / `withArgs` to bind values to a PowerShell `param()` block. C# accepts values of any type; the TypeScript export accepts strings. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var scripts = builder.AddPowerShell("scripts"); +scripts.AddScript("process-data", """ + param($count, $name) + Write-Information "Processing $count items for $name" + """) + .WithArgs(5, "demo"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const scripts = await builder.addPowerShell('scripts'); +await scripts + .addScript( + 'process-data', + 'param($count, $name) Write-Information "Processing $count items for $name"' + ) + .withArgs(['5', 'demo']); + +await builder.build().run(); +``` + + + + +Scripts execute in the AppHost process's current working directory. The integration has no `WithWorkingDirectory` API, so use absolute paths or set a location in the script when its file operations must be independent of the host's launch directory. + +The script resource implements the standard environment annotation interface, but the in-process runner doesn't project those annotations into the runspace. A script can read environment variables inherited by the AppHost process through PowerShell's `$env:` provider. + +## Pass connection strings to scripts + +In C#, `WithReference` on the runspace pool makes a connection string available as a read-only PowerShell variable. By default, the variable name is the referenced resource name. Pass `connectionName` to choose a different variable name. `optional: true` allows the connection string to be unavailable. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var cache = builder.AddRedis("cache"); +var scripts = builder.AddPowerShell("scripts") + .WithReference(cache, connectionName: "redisConnection"); + +scripts.AddScript("seed", """ + Write-Information "Redis connection: $redisConnection" + """); + +builder.Build().Run(); +``` + + + + +The PowerShell-specific pool `withReference` API is not exported to TypeScript. You can use standard AppHost resource relationships such as `waitFor`, but they do not create a PowerShell connection-string variable. + + + + +The pool resolves these variables before it opens. This is distinct from an environment variable: the connection string is added to the PowerShell session state rather than to a process environment. + +## Order scripts and resources + +Use `WaitFor` / `waitFor` for readiness dependencies. Each script automatically waits for its parent pool. Use `WaitForCompletion` / `waitForCompletion` when one script must finish before another script starts. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var scripts = builder.AddPowerShell("scripts"); +var setup = scripts.AddScript("setup", """ + Write-Information "Setting up" + """); + +scripts.AddScript("process", """ + Write-Information "Processing after setup" + """) + .WaitForCompletion(setup); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const scripts = await builder.addPowerShell('scripts'); +const setup = await scripts.addScript( + 'setup', + 'Write-Information "Setting up"' +); + +await scripts + .addScript('process', 'Write-Information "Processing after setup"') + .waitForCompletion(setup); + +await builder.build().run(); +``` + + + + +## Dashboard behavior, health, and publishing + +The dashboard reports the pool state and each script's invocation state. A completed script is a finite resource and reaches **Finished**; it is not an HTTP service. The integration does not add endpoints, HTTP health checks, or health probes for PowerShell resources. + +While a script is running, its dashboard resource has a **Stop script execution** action. The action stops the PowerShell pipeline; it is disabled when the script is not running. You can use `Wait-Debugger` in a script and attach a PowerShell debugger to the AppHost process when diagnosing a script. + +PowerShell pools and scripts are excluded from the deployment manifest. They run in the AppHost process during local orchestration and are not exported as container or deployment resources. + +## See also + +- [PowerShell documentation](https://learn.microsoft.com/powershell/) +- [Get started with the PowerShell integration](/integrations/frameworks/powershell/powershell-get-started/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust.mdx deleted file mode 100644 index 79ff45caf..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/rust.mdx +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Rust integration -seoTitle: Rust integration for Aspire AppHost (Community Toolkit) -description: Learn how to use the Aspire Community Toolkit hosting integration to run Rust applications alongside other resources in your AppHost project. ---- - -import { Badge } from '@astrojs/starlight/components'; -import InstallPackage from '@components/InstallPackage.astro'; -import { Image } from 'astro:assets'; -import rustIcon from '@assets/icons/rust-icon.png'; - -Rust logo - - - -The Aspire Rust hosting integration enables you to run Rust applications alongside other resources in your AppHost project, providing service discovery, health checks, and observability for your Rust services. - -## Prerequisites - -This integration requires `cargo` to be installed on your system and available in your `PATH`. For installation instructions, see [Install Rust](https://www.rust-lang.org/tools/install). - -:::note -TypeScript AppHost support for this integration isn't yet available. -::: - -## Hosting integration - - - -### Add Rust app - -In your AppHost, call `AddRustApp` to register a Rust application as a resource. Provide the resource name and the path to the directory containing your Rust project (where `Cargo.toml` lives): - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var rustApp = builder.AddRustApp("rust-api", workingDirectory: "../rust-app") - .WithHttpEndpoint(port: 8080, env: "PORT"); - -builder.AddProject("apiservice") - .WithReference(rustApp); - -builder.Build().Run(); -``` - -The Aspire app host runs `cargo run` in the specified `workingDirectory` to start your Rust application. The required parameters are: - -- **name** — the resource name shown in the Aspire dashboard. -- **workingDirectory** — path to the directory containing the Rust application. - -### Configure endpoints - -Rust applications typically read a `PORT` environment variable to determine which port to listen on. Use `WithHttpEndpoint` to expose an HTTP endpoint and inject the port value as an environment variable: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var rustApp = builder.AddRustApp("rust-api", "../rust-app") - .WithHttpEndpoint(port: 8080, env: "PORT"); - -builder.Build().Run(); -``` - -Your Rust application can read the injected environment variable as follows: - -```rust title="main.rs" -use std::env; -use actix_web::{web, App, HttpServer, Responder}; - -async fn greet() -> impl Responder { - "Hello from Rust!" -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string()); - let addr = format!("0.0.0.0:{}", port); - - println!("Server listening on {}", addr); - - HttpServer::new(|| { - App::new() - .route("/", web::get().to(greet)) - }) - .bind(addr)? - .run() - .await -} -``` - -### Custom arguments - -To pass custom arguments to `cargo run`, chain the `WithArgs` method: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var rustApp = builder.AddRustApp("rust-api", "../rust-app") - .WithArgs("--release") - .WithHttpEndpoint(port: 8080, env: "PORT"); - -builder.Build().Run(); -``` - -## See also - -- [Rust documentation](https://www.rust-lang.org/learn) -- [Cargo documentation](https://doc.rust-lang.org/cargo/) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [📦 CommunityToolkit.Aspire.Hosting.Rust NuGet package](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Rust) -- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx new file mode 100644 index 000000000..c9fb35ba1 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx @@ -0,0 +1,101 @@ +--- +title: Get started with the Rust integration +description: Use the Community Toolkit Rust integration to run Cargo or Bacon applications, configure endpoints, and monitor them with Aspire. +--- + +import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import rustIcon from '@assets/icons/rust-icon.png'; + +Rust logo + + + +The Community Toolkit Rust hosting integration runs Rust applications through Cargo or Bacon alongside the other resources in your Aspire AppHost. Rust app resources support endpoints, service discovery, health checks, environment configuration, and OpenTelemetry export. They are also configured for Dockerfile publishing. + +## How the pieces fit together + +The integration is installed in the AppHost. The AppHost starts Cargo or Bacon in the Rust application's working directory, applies standard Aspire resource configuration, and exposes the resulting resource in the dashboard. + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group rustapp(server)[Rust app] + + service hosting(server)[Rust hosting integration] in apphost + service resource(logos:rust)[Rust app resource] in apphost + service toolchain(logos:rust)[Cargo or Bacon] in rustapp + service app(logos:rust)[Rust process] in rustapp + + hosting:R --> L:resource + resource:R --> L:toolchain + toolchain:R --> L:app +``` + +## Prerequisites + +- Install Rust with [rustup](https://www.rust-lang.org/tools/install) and make `cargo` available on your `PATH`. +- Install [Bacon](https://dystroy.org/bacon/) when you use `AddBaconApp` / `addBaconApp`. +- Create an [Aspire AppHost](/get-started/app-host/) in C# or TypeScript. + + + +1. ### Install the hosting package + + Add `CommunityToolkit.Aspire.Hosting.Rust` to your AppHost. You can use `aspire add communitytoolkit-rust` or install the NuGet package directly. + +2. ### Add a Rust app + + Register the directory that contains your Rust project, then configure an endpoint for the port that the app reads from `PORT`. + + ```csharp title="AppHost.cs" + var builder = DistributedApplication.CreateBuilder(args); + + builder.AddRustApp("rust-api", "../rust-api") + .WithHttpEndpoint(port: 8080, env: "PORT") + .WithExternalHttpEndpoints(); + + builder.Build().Run(); + ``` + + ```typescript title="apphost.mts" + import { createBuilder } from './.aspire/modules/aspire.mjs'; + + const builder = await createBuilder(); + + const api = await builder.addRustApp('rust-api', '../rust-api'); + await api.withHttpEndpoint({ port: 8080, env: 'PORT' }); + await api.withExternalHttpEndpoints(); + + await builder.build().run(); + ``` + +3. ### Configure the app resource + + Choose Cargo or Bacon, pass command arguments, add health checks, and learn about publishing in the [Rust AppHost reference](/integrations/frameworks/rust/rust-host/). + + + Configure Rust apps in the AppHost + + + + +## See also + +- [Rust documentation](https://www.rust-lang.org/learn) +- [Cargo documentation](https://doc.rust-lang.org/cargo/) +- [Rust AppHost reference](/integrations/frameworks/rust/rust-host/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx new file mode 100644 index 000000000..a33f107bf --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx @@ -0,0 +1,206 @@ +--- +title: Configure Rust apps in the AppHost +description: Configure Cargo and Bacon applications, arguments, endpoints, health checks, telemetry, environment settings, and publishing in Aspire. +--- + +import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; +import rustIcon from '@assets/icons/rust-icon.png'; + +Rust logo + + + +This reference describes the Community Toolkit Rust hosting integration. If you are new to it, begin with [Get started with the Rust integration](/integrations/frameworks/rust/rust-get-started/). + +:::note[Prerequisites] +Install [Rust and Cargo](https://www.rust-lang.org/tools/install). Install [Bacon](https://dystroy.org/bacon/) too when you use the Bacon resource API. +::: + +## Install the package + + + + +```bash title="Terminal" +aspire add communitytoolkit-rust +``` + +Or add [📦 CommunityToolkit.Aspire.Hosting.Rust](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Rust) to the AppHost project. + + + + +```bash title="Terminal" +aspire add communitytoolkit-rust +``` + +This adds the package to `aspire.config.json` and generates the TypeScript AppHost module. + + + + +## Add a Cargo app + +`AddRustApp` / `addRustApp` starts `cargo run` in the supplied working directory. The path is resolved relative to the AppHost directory, so it normally contains the Rust project's `Cargo.toml`. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddRustApp("rust-api", "../rust-api"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder.addRustApp('rust-api', '../rust-api'); + +await builder.build().run(); +``` + + + + +## Pass Cargo arguments and choose a working directory + +The optional `args` are appended after `cargo run`. For example, `--release` produces `cargo run --release`; use `--` before arguments intended for your Rust application. The working directory is normalized to the current platform after Aspire combines it with the AppHost directory. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddRustApp( + name: "rust-api", + workingDirectory: "../rust-api", + args: ["--release", "--", "--environment", "development"]); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder.addRustApp('rust-api', '../rust-api', { + args: ['--release', '--', '--environment', 'development'], +}); + +await builder.build().run(); +``` + + + + +## Add a Bacon app + +`AddBaconApp` / `addBaconApp` runs the [Bacon](https://dystroy.org/bacon/) CLI from the working directory. Without arguments it runs `bacon run`; supply `args` to use another Bacon command. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var checks = builder.AddBaconApp( + name: "rust-checks", + workingDirectory: "../rust-api", + args: ["check"]); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const checks = await builder.addBaconApp('rust-checks', '../rust-api', { + args: ['check'], +}); + +await builder.build().run(); +``` + + + + +## Configure endpoints, environment, and health checks + +Rust app resources support standard executable-resource configuration. Use `WithHttpEndpoint` / `withHttpEndpoint` to allocate a port and put it in an environment variable that the application reads. Use `WithHttpHealthCheck` / `withHttpHealthCheck` when the application exposes an HTTP health endpoint. `WithExternalHttpEndpoints` / `withExternalHttpEndpoints` makes an HTTP endpoint externally accessible. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddRustApp("rust-api", "../rust-api") + .WithEnvironment("RUST_LOG", "info") + .WithHttpEndpoint(port: 8080, env: "PORT") + .WithExternalHttpEndpoints() + .WithHttpHealthCheck("/health"); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const api = await builder.addRustApp('rust-api', '../rust-api'); +await api.withEnvironment('RUST_LOG', 'info'); +await api.withHttpEndpoint({ port: 8080, env: 'PORT' }); +await api.withExternalHttpEndpoints(); +await api.withHttpHealthCheck({ path: '/health' }); + +await builder.build().run(); +``` + + + + +The integration configures the Rust app with the OpenTelemetry Protocol exporter. Add OpenTelemetry instrumentation to the Rust application to emit telemetry to Aspire. You can also use standard resource references to model dependencies and provide their configuration to the Rust process. + +The dashboard exposes the standard executable-resource lifecycle actions and process logs. The integration doesn't add Rust-specific dashboard commands. + +## Publish Rust apps + +Both Cargo and Bacon app resources are configured as Dockerfile-published resources when they are added. During `aspire publish`, Aspire converts the executable resource to a container resource and uses the Rust app's working directory as the Docker build context. Include a suitable `Dockerfile` there. The local Cargo or Bacon arguments are cleared for the containerized resource, so configure the Dockerfile with the command and arguments it needs. + +## See also + +- [Rust documentation](https://www.rust-lang.org/learn) +- [Cargo documentation](https://doc.rust-lang.org/cargo/) +- [Bacon documentation](https://dystroy.org/bacon/) +- [Get started with the Rust integration](/integrations/frameworks/rust/rust-get-started/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/data/integration-docs.json b/src/frontend/src/data/integration-docs.json index e7c67f277..2e8a6bfab 100644 --- a/src/frontend/src/data/integration-docs.json +++ b/src/frontend/src/data/integration-docs.json @@ -397,7 +397,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Deno", - "href": "/integrations/frameworks/deno-apps/" + "href": "/integrations/frameworks/deno/deno-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Flagd", @@ -409,7 +409,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Java", - "href": "/integrations/frameworks/java/" + "href": "/integrations/frameworks/java/java-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.JavaScript.Extensions", @@ -417,7 +417,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.k6", - "href": "/integrations/devtools/k6/" + "href": "/integrations/devtools/k6/k6-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Keycloak.Extensions", @@ -453,7 +453,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Perl", - "href": "/integrations/frameworks/perl/" + "href": "/integrations/frameworks/perl/perl-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions", @@ -461,7 +461,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.PowerShell", - "href": "/integrations/frameworks/powershell/" + "href": "/integrations/frameworks/powershell/powershell-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Python.Extensions", @@ -477,11 +477,11 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Rust", - "href": "/integrations/frameworks/rust/" + "href": "/integrations/frameworks/rust/rust-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects", - "href": "/integrations/devtools/sql-projects/" + "href": "/integrations/devtools/sql-projects/sql-projects-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Sqlite", @@ -545,7 +545,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.PowerShell", - "href": "/integrations/frameworks/powershell/" + "href": "/integrations/frameworks/powershell/powershell-get-started/" }, { "match": "CommunityToolkit.Aspire.SurrealDb", From ce1cfba96adfc4887c97cb6b3a67e714c86b97eb Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:57:57 -0500 Subject: [PATCH 2/5] Keep host-only integration logos visible Contain each hero image so non-square source artwork is preserved instead of cropped. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b620d5b1-e665-4478-974d-cb5d2b825c28 --- .../src/content/docs/integrations/devtools/k6/k6-get-started.mdx | 1 + .../src/content/docs/integrations/devtools/k6/k6-host.mdx | 1 + .../devtools/sql-projects/sql-projects-get-started.mdx | 1 + .../integrations/devtools/sql-projects/sql-projects-host.mdx | 1 + .../docs/integrations/frameworks/deno/deno-get-started.mdx | 1 + .../src/content/docs/integrations/frameworks/deno/deno-host.mdx | 1 + .../docs/integrations/frameworks/java/java-get-started.mdx | 1 + .../src/content/docs/integrations/frameworks/java/java-host.mdx | 1 + .../docs/integrations/frameworks/perl/perl-get-started.mdx | 1 + .../src/content/docs/integrations/frameworks/perl/perl-host.mdx | 1 + .../frameworks/powershell/powershell-get-started.mdx | 1 + .../docs/integrations/frameworks/powershell/powershell-host.mdx | 1 + .../docs/integrations/frameworks/rust/rust-get-started.mdx | 1 + .../src/content/docs/integrations/frameworks/rust/rust-host.mdx | 1 + 14 files changed, 14 insertions(+) diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx index 60c0e29ae..218d0576d 100644 --- a/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-get-started.mdx @@ -14,6 +14,7 @@ import k6Icon from '@assets/icons/k6-icon.svg'; alt="k6 logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx index f40bc1eb0..23c1f22cb 100644 --- a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx @@ -16,6 +16,7 @@ import k6Icon from '@assets/icons/k6-icon.svg'; alt="k6 logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx index e6ab39e57..506c4e181 100644 --- a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-get-started.mdx @@ -20,6 +20,7 @@ import sqlIcon from '@assets/icons/sql-database-projects-icon.png'; alt="SQL Database Projects icon" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx index 01e0f0de6..fcc3c74b4 100644 --- a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx @@ -18,6 +18,7 @@ import sqlIcon from '@assets/icons/sql-database-projects-icon.png'; alt="SQL Database Projects icon" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx index 46c2989b6..3f5350235 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx @@ -19,6 +19,7 @@ import denoIcon from '@assets/icons/deno-icon.png'; alt="Deno logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx index cfbccc671..1f55181de 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx @@ -16,6 +16,7 @@ import denoIcon from '@assets/icons/deno-icon.png'; alt="Deno logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx index d2baf00e3..f9caea242 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-get-started.mdx @@ -19,6 +19,7 @@ import javaIcon from '@assets/icons/java-icon.png'; alt="Java logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx index 8e8b5ad56..cc15669b5 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx @@ -16,6 +16,7 @@ import javaIcon from '@assets/icons/java-icon.png'; alt="Java logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx index 89f51c232..2db18b0c4 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx @@ -19,6 +19,7 @@ import perlIcon from '@assets/icons/perl-096-1500.svg'; alt="Perl Camel" width={75} height={75} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx index b9a9554b1..3f67db421 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx @@ -16,6 +16,7 @@ import perlIcon from '@assets/icons/perl-096-1500.svg'; alt="Perl Camel" width={75} height={75} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx index 19bbe2d89..b38873796 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx @@ -12,6 +12,7 @@ import powershellIcon from '@assets/icons/powershell-icon.png'; alt="PowerShell logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx index b8ff0e606..c5ebbeec2 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx @@ -12,6 +12,7 @@ import powershellIcon from '@assets/icons/powershell-icon.png'; alt="PowerShell logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx index c9fb35ba1..5ddbe054d 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx @@ -12,6 +12,7 @@ import rustIcon from '@assets/icons/rust-icon.png'; alt="Rust logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx index a33f107bf..4bad1d28f 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx @@ -12,6 +12,7 @@ import rustIcon from '@assets/icons/rust-icon.png'; alt="Rust logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> From a51f4cb20d954067611038e0e526f8b602120685 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:02:43 -0500 Subject: [PATCH 3/5] Use theme-aware Deno logos Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b620d5b1-e665-4478-974d-cb5d2b825c28 --- .../frameworks/deno/deno-get-started.mdx | 13 +++++++------ .../docs/integrations/frameworks/deno/deno-host.mdx | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx index 3f5350235..205d0a018 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx @@ -9,19 +9,20 @@ import { TabItem, Tabs, } from '@astrojs/starlight/components'; -import { Image } from 'astro:assets'; +import ThemeImage from '@components/ThemeImage.astro'; import denoIcon from '@assets/icons/deno-icon.png'; +import denoLightIcon from '@assets/icons/deno-light-icon.png'; -Deno logo The [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) Deno hosting integration adds Deno scripts and tasks to your [AppHost](/get-started/app-host/). Aspire starts the Deno process locally, shows it in the dashboard, and lets you connect it to the rest of your distributed application. diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx index 1f55181de..17bf97337 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx @@ -6,19 +6,20 @@ description: Configure Deno script and task resources, permissions, endpoints, h import { Badge, TabItem, Tabs } from '@astrojs/starlight/components'; import InstallPackage from '@components/InstallPackage.astro'; import LearnMore from '@components/LearnMore.astro'; -import { Image } from 'astro:assets'; +import ThemeImage from '@components/ThemeImage.astro'; import denoIcon from '@assets/icons/deno-icon.png'; +import denoLightIcon from '@assets/icons/deno-light-icon.png'; -Deno logo This reference covers the Deno AppHost API from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire). For an introduction, see [Get started with the Deno integration](/integrations/frameworks/deno/deno-get-started/). From c33bbc676ba751b0d67e56e8f104fd642f728b35 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:10:43 -0500 Subject: [PATCH 4/5] docs: synchronize host-only AppHost examples Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b0414d35-db01-4c94-9902-319b4420d708 --- .../docs/integrations/devtools/k6/k6-host.mdx | 6 +++++- .../devtools/sql-projects/sql-projects-host.mdx | 10 +++++++++- .../integrations/frameworks/deno/deno-host.mdx | 2 +- .../integrations/frameworks/java/java-host.mdx | 8 +++++++- .../powershell/powershell-get-started.mdx | 17 ++++++++++++++++- .../frameworks/powershell/powershell-host.mdx | 6 +++--- .../frameworks/rust/rust-get-started.mdx | 17 ++++++++++++++++- 7 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx index 23c1f22cb..ad76fa5f4 100644 --- a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx @@ -107,7 +107,7 @@ await builder.build().run(); - The resource is a container resource, so its logs, lifecycle actions, endpoint link, and health state appear in the dashboard. - The integration configures an OTLP exporter for the container. Use `WithK6OtlpEnvironment` / `withK6OtlpEnvironment` when k6 should consume the corresponding k6 environment variables. -Use `PrimaryEndpoint` / `primaryEndpoint()` when an AppHost API needs the k6 HTTP endpoint directly. +The examples read `PrimaryEndpoint` / `primaryEndpoint()` when an AppHost API needs the k6 HTTP endpoint directly. ### Use a fixed port or browser-enabled image @@ -121,6 +121,8 @@ var k6 = builder.AddK6( "browser-tests", enableBrowserExtensions: true, port: 6565); + +var endpoint = k6.Resource.PrimaryEndpoint; ``` @@ -131,6 +133,8 @@ const k6 = await builder.addK6('browser-tests', { enableBrowserExtensions: true, port: 6565, }); + +const endpoint = await k6.primaryEndpoint(); ``` diff --git a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx index fcc3c74b4..3b1a064e3 100644 --- a/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/sql-projects/sql-projects-host.mdx @@ -187,6 +187,10 @@ var databaseProject = builder.AddSqlProject("catalog-schema") .WithDacpac("../artifacts/catalog-schema.dacpac") .WithSkipWhenDeployed() .WithReference(database); + +var dacpacPath = databaseProject.Resource.DacpacPath; +var optionsPath = databaseProject.Resource.DacDeployOptionsPath; +var skipWhenDeployed = databaseProject.Resource.SkipWhenDeployed; ``` @@ -198,6 +202,10 @@ const databaseProject = await builder.addSqlProject('catalog-schema'); await databaseProject.withDacpac('../artifacts/catalog-schema.dacpac'); await databaseProject.withSkipWhenDeployed(); await databaseProject.withReference(database); + +const dacpacPath = await databaseProject.dacpacPath(); +const optionsPath = await databaseProject.dacDeployOptionsPath(); +const skipWhenDeployed = await databaseProject.skipWhenDeployed(); ``` @@ -240,7 +248,7 @@ The SQL Server database overload is `withReference` in TypeScript. The connectio When a referenced target becomes ready, the integration publishes the DACPAC and reports the deployment resource as `Running`, then `Finished` with exit code `0`; failures are reported in the resource logs and state. Use standard `WithExplicitStart` on a project or package resource to prevent that automatic deployment, then invoke its highlighted **Deploy** dashboard command. The command also deploys a schema again manually and is disabled while the resource is starting or running. -The `SqlProjectResource` is exported with properties for TypeScript AppHosts: +The preceding synchronized examples also show the `SqlProjectResource` properties exported to TypeScript AppHosts: - `dacpacPath()` returns the path configured by `withDacpac`, or `null`. - `dacDeployOptionsPath()` returns the publish-profile path configured by `withDacDeployOptions`, or `null`. diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx index 17bf97337..2c5db276b 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx @@ -151,7 +151,7 @@ await builder.build().run(); -In C#, an overload also accepts a callback that configures the installer resource. That callback overload is not exported to TypeScript AppHosts. +In C#, an overload also accepts a callback that configures the installer resource. It is marked `[AspireExportIgnore]` because `Action>` is not ATS-compatible; TypeScript uses the exported overload without `configureInstaller`. ## Configure endpoints, environment, and health checks diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx index cc15669b5..c30f2c5b5 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx @@ -94,6 +94,9 @@ var app = builder.AddJavaApp( jarPath: "target/java-api.jar", args: ["--spring.main.banner-mode=off"]); +var jarPath = app.Resource.JarPath; +app.Resource.JarPath = "target/java-api-optimized.jar"; + builder.Build().Run(); ``` @@ -112,13 +115,16 @@ const app = await builder.addJavaAppWithJar( { args: ['--spring.main.banner-mode=off'] } ); +const jarPath = await app.jarPath(); +await app.setJarPath('target/java-api-optimized.jar'); + await builder.build().run(); ``` -The TypeScript export is named `addJavaAppWithJar`. The Java executable resource also exposes its `JarPath` / `jarPath` property when you need to update the configured JAR path programmatically. +The TypeScript export is named `addJavaAppWithJar`. The Java executable resource exposes `JarPath` in C# and the synchronized `jarPath()` getter and `setJarPath(value)` operation in TypeScript. ## Build before running diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx index b38873796..5e0fd8290 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-get-started.mdx @@ -3,7 +3,13 @@ title: Get started with the PowerShell integration description: Use the Community Toolkit PowerShell integration to run managed scripts, model dependencies, and monitor their lifecycle in Aspire. --- -import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import { + Badge, + LinkButton, + Steps, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; import { Image } from 'astro:assets'; import powershellIcon from '@assets/icons/powershell-icon.png'; @@ -54,6 +60,9 @@ architecture-beta Add a named PowerShell pool, then add a script to it. The following script appears as a resource in the dashboard. + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -65,6 +74,9 @@ architecture-beta builder.Build().Run(); ``` + + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -79,6 +91,9 @@ architecture-beta await builder.build().run(); ``` + + + 3. ### Configure scripts in the AppHost Configure arguments, dependencies, connection-string variables, and lifecycle behavior in the [PowerShell AppHost reference](/integrations/frameworks/powershell/powershell-host/). diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx index c5ebbeec2..4e943d861 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx @@ -89,13 +89,13 @@ await builder.build().run(); -Use the least-permissive language mode appropriate for the scripts you run. The TypeScript API accepts the language-mode name as a string. Invalid names fail while Aspire constructs the AppHost. +Use the least-permissive language mode appropriate for the scripts you run. The C# overload that accepts `PSLanguageMode` is marked `[AspireExportIgnore]` because the enum isn't ATS-compatible. The exported TypeScript bridge accepts the language-mode name as a string; invalid names fail while Aspire constructs the AppHost. ## Add scripts and arguments `AddScript` / `addScript` creates a child script resource. Aspire parses the script when the AppHost is built, starts it after the pool is running, and streams output, errors, warnings, information, verbose, and debug records to the resource logs. -Use `WithArgs` / `withArgs` to bind values to a PowerShell `param()` block. C# accepts values of any type; the TypeScript export accepts strings. +Use `WithArgs` / `withArgs` to bind values to a PowerShell `param()` block. The C# `object[]` overload accepts values of any type but is marked `[AspireExportIgnore]` because `object[]` isn't ATS-compatible. The exported TypeScript bridge accepts strings. @@ -163,7 +163,7 @@ builder.Build().Run(); -The PowerShell-specific pool `withReference` API is not exported to TypeScript. You can use standard AppHost resource relationships such as `waitFor`, but they do not create a PowerShell connection-string variable. +The PowerShell-specific pool `WithReference` API is marked `[AspireExportIgnore]` because `IResourceBuilder` is not currently validated for ATS export in this integration. You can use standard TypeScript AppHost relationships such as `waitFor`, but they do not create a PowerShell connection-string variable. diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx index 5ddbe054d..4e4a0aae1 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-get-started.mdx @@ -3,7 +3,13 @@ title: Get started with the Rust integration description: Use the Community Toolkit Rust integration to run Cargo or Bacon applications, configure endpoints, and monitor them with Aspire. --- -import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import { + Badge, + LinkButton, + Steps, + TabItem, + Tabs, +} from '@astrojs/starlight/components'; import { Image } from 'astro:assets'; import rustIcon from '@assets/icons/rust-icon.png'; @@ -57,6 +63,9 @@ architecture-beta Register the directory that contains your Rust project, then configure an endpoint for the port that the app reads from `PORT`. + + + ```csharp title="AppHost.cs" var builder = DistributedApplication.CreateBuilder(args); @@ -67,6 +76,9 @@ architecture-beta builder.Build().Run(); ``` + + + ```typescript title="apphost.mts" import { createBuilder } from './.aspire/modules/aspire.mjs'; @@ -79,6 +91,9 @@ architecture-beta await builder.build().run(); ``` + + + 3. ### Configure the app resource Choose Cargo or Bacon, pass command arguments, add health checks, and learn about publishing in the [Rust AppHost reference](/integrations/frameworks/rust/rust-host/). From 7b1dd34b382077f0d7d565008441035520067f35 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:02:58 -0500 Subject: [PATCH 5/5] docs: correct host-only TypeScript signatures Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b0414d35-db01-4c94-9902-319b4420d708 --- src/frontend/config/redirects.mjs | 3 +++ .../docs/integrations/devtools/k6/k6-host.mdx | 10 ++------ .../frameworks/deno/deno-get-started.mdx | 5 +--- .../frameworks/deno/deno-host.mdx | 25 +++++++++---------- .../frameworks/java/java-host.mdx | 8 +++--- .../frameworks/perl/perl-get-started.mdx | 4 +-- .../frameworks/perl/perl-host.mdx | 12 ++++----- .../frameworks/powershell/powershell-host.mdx | 6 +---- .../frameworks/rust/rust-host.mdx | 15 ++++++----- .../tests/unit/redirects.vitest.test.ts | 18 +++++++++++++ 10 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/frontend/config/redirects.mjs b/src/frontend/config/redirects.mjs index da01fc764..7d886efe8 100644 --- a/src/frontend/config/redirects.mjs +++ b/src/frontend/config/redirects.mjs @@ -187,6 +187,9 @@ export const redirects = { '/integrations/frameworks/rust/': '/integrations/frameworks/rust/rust-get-started/', '/integrations/devtools/k6/': '/integrations/devtools/k6/k6-get-started/', '/integrations/devtools/sql-projects/': '/integrations/devtools/sql-projects/sql-projects-get-started/', + '/ja/integrations/frameworks/java/': '/integrations/frameworks/java/java-get-started/', + '/ja/integrations/frameworks/powershell/': '/integrations/frameworks/powershell/powershell-get-started/', + '/ja/integrations/frameworks/rust/': '/integrations/frameworks/rust/rust-get-started/', '/ja/integrations/frameworks/go-apps/': '/integrations/frameworks/go/go-get-started/', '/integrations/frameworks/csharp-file-based-apps/': '/integrations/dotnet/csharp-file-based-apps/', '/integrations/frameworks/maui/': '/integrations/dotnet/maui/', diff --git a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx index ad76fa5f4..2e5d64912 100644 --- a/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/k6/k6-host.mdx @@ -129,10 +129,7 @@ var endpoint = k6.Resource.PrimaryEndpoint; ```typescript title="apphost.mts" -const k6 = await builder.addK6('browser-tests', { - enableBrowserExtensions: true, - port: 6565, -}); +const k6 = await builder.addK6('browser-tests', true, 6565); const endpoint = await k6.primaryEndpoint(); ``` @@ -163,10 +160,7 @@ var k6 = builder.AddK6("load-test") ```typescript title="apphost.mts" const k6 = await builder.addK6('load-test'); await k6.withBindMount('./scripts', '/scripts', { isReadOnly: true }); -await k6.withScript('/scripts/main.js', { - virtualUsers: 25, - duration: '45s', -}); +await k6.withScript('/scripts/main.js', 25, '45s'); ``` diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx index 205d0a018..6b3a9ba2a 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-get-started.mdx @@ -68,10 +68,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); const app = await builder - .addDenoTask('web', { - workingDirectory: '../web', - taskName: 'dev', - }) + .addDenoTask('web', '../web', 'dev') .withHttpEndpoint({ env: 'PORT' }) .withHttpHealthCheck({ path: '/' }); diff --git a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx index 2c5db276b..f95a8687e 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/deno/deno-host.mdx @@ -60,11 +60,13 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const api = await builder.addDenoApp('deno-api', 'main.ts', { - workingDirectory: '../deno-api', - permissionFlags: ['--allow-env', '--allow-net'], - args: ['--verbose'], -}); +const api = await builder.addDenoApp( + 'deno-api', + 'main.ts', + '../deno-api', + ['--allow-env', '--allow-net'], + ['--verbose'] +); await builder.build().run(); ``` @@ -103,11 +105,10 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const web = await builder.addDenoTask('web', { - workingDirectory: '../web', - taskName: 'dev', - args: ['--host', '0.0.0.0'], -}); +const web = await builder.addDenoTask('web', '../web', 'dev', [ + '--host', + '0.0.0.0', +]); await builder.build().run(); ``` @@ -183,9 +184,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); const api = await builder - .addDenoApp('deno-api', 'main.ts', { - permissionFlags: ['--allow-env', '--allow-net'], - }) + .addDenoApp('deno-api', 'main.ts', undefined, ['--allow-env', '--allow-net']) .withHttpEndpoint({ port: 8000, env: 'PORT' }) .withEnvironment('LOG_LEVEL', 'debug') .withHttpHealthCheck({ path: '/health' }); diff --git a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx index c30f2c5b5..825e3abc1 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/java/java-host.mdx @@ -112,7 +112,7 @@ const app = await builder.addJavaAppWithJar( 'java-api', '../java-api', 'target/java-api.jar', - { args: ['--spring.main.banner-mode=off'] } + ['--spring.main.banner-mode=off'] ); const jarPath = await app.jarPath(); @@ -231,7 +231,7 @@ const app = await builder .addJavaApp('java-api', '../java-api') .withMavenGoal('spring-boot:run', []) .withJvmArgs(['-Xms256m', '-Xmx512m']) - .withOtelAgent({ agentPath: '../agents/opentelemetry-javaagent.jar' }); + .withOtelAgent('../agents/opentelemetry-javaagent.jar'); await builder.build().run(); ``` @@ -270,9 +270,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); const app = await builder - .addJavaContainerApp('java-api', 'ghcr.io/contoso/java-api', { - imageTag: '1.0', - }) + .addJavaContainerApp('java-api', 'ghcr.io/contoso/java-api', '1.0') .withJvmArgs(['-Djava.awt.headless=true']) .withHttpEndpoint({ targetPort: 8080, env: 'SERVER_PORT' }); diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx index 2db18b0c4..f8a0e1e7c 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-get-started.mdx @@ -49,7 +49,7 @@ architecture-beta ## Prerequisites - Install [Perl](https://www.perl.org/get.html) and ensure `perl` and `cpan` are on `PATH`. -- Install `cpanm` when you use `WithCpanMinus`, `WithLocalLib`, or project dependency installation. Install `carton` when you use Carton. +- Install `cpanm` when you use `WithCpanMinus`, `WithLocalLib`, or project dependency installation without Carton. Install `carton` when you use Carton. - Install the [Aspire CLI](/get-started/install-cli/) and create an AppHost. :::note @@ -91,7 +91,7 @@ const worker = await builder.addPerlScript( '../perl-worker', 'worker.pl' ); -await worker.withLocalLib({ path: 'local' }); +await worker.withLocalLib('local'); await builder.build().run(); ``` diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx index 3f67db421..427e9d6cd 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl/perl-host.mdx @@ -163,7 +163,7 @@ const worker = await builder.addPerlScript( '../perl-worker', 'worker.pl' ); -await worker.withLocalLib({ path: 'local' }); +await worker.withLocalLib('local'); ``` @@ -211,7 +211,7 @@ var api = builder.AddPerlApi("api", "../perl-api", "app.pl") ```typescript title="apphost.mts" const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); await api.withCpanMinus(); -await api.withPackage('Mojolicious', { skipTest: true }); +await api.withPackage('Mojolicious', false, true); ``` @@ -256,7 +256,7 @@ const worker = await builder.addPerlScript( 'worker.pl' ); await worker.withCarton(); -await worker.withProjectDependencies({ cartonDeployment: true }); +await worker.withProjectDependencies(true); ``` @@ -294,12 +294,10 @@ const worker = await builder.addPerlScript( '../perl-worker', 'worker.pl' ); -await worker.withPerlbrew('5.40.0', { perlbrewRoot: '/opt/perlbrew' }); +await worker.withPerlbrew('5.40.0', '/opt/perlbrew'); const api = await builder.addPerlApi('api', '../perl-api', 'app.pl'); -await api.withPerlbrewEnvironment('perl-5.40.0', { - perlbrewRoot: '/opt/perlbrew', -}); +await api.withPerlbrewEnvironment('perl-5.40.0', '/opt/perlbrew'); ``` diff --git a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx index 4e943d861..502b618a7 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/powershell/powershell-host.mdx @@ -77,11 +77,7 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const scripts = await builder.addPowerShell('scripts', { - languageMode: 'FullLanguage', - minRunspaces: 2, - maxRunspaces: 8, -}); +const scripts = await builder.addPowerShell('scripts', 'FullLanguage', 2, 8); await builder.build().run(); ``` diff --git a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx index 4bad1d28f..2273507c7 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/rust/rust-host.mdx @@ -105,9 +105,12 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const api = await builder.addRustApp('rust-api', '../rust-api', { - args: ['--release', '--', '--environment', 'development'], -}); +const api = await builder.addRustApp('rust-api', '../rust-api', [ + '--release', + '--', + '--environment', + 'development', +]); await builder.build().run(); ``` @@ -141,9 +144,9 @@ import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); -const checks = await builder.addBaconApp('rust-checks', '../rust-api', { - args: ['check'], -}); +const checks = await builder.addBaconApp('rust-checks', '../rust-api', [ + 'check', +]); await builder.build().run(); ``` diff --git a/src/frontend/tests/unit/redirects.vitest.test.ts b/src/frontend/tests/unit/redirects.vitest.test.ts index af377df1c..828eea990 100644 --- a/src/frontend/tests/unit/redirects.vitest.test.ts +++ b/src/frontend/tests/unit/redirects.vitest.test.ts @@ -70,3 +70,21 @@ test('/whats-new/ redirect destination resolves to a real .mdx file on disk', () expect(existsSync(filePath), `Expected ${filePath} to exist`).toBe(true); }); + +test('host-only integration routes redirect to their get-started pages', () => { + expect(redirects).toMatchObject({ + '/integrations/frameworks/deno-apps/': '/integrations/frameworks/deno/deno-get-started/', + '/integrations/frameworks/java/': '/integrations/frameworks/java/java-get-started/', + '/integrations/frameworks/perl/': '/integrations/frameworks/perl/perl-get-started/', + '/integrations/frameworks/powershell/': + '/integrations/frameworks/powershell/powershell-get-started/', + '/integrations/frameworks/rust/': '/integrations/frameworks/rust/rust-get-started/', + '/integrations/devtools/k6/': '/integrations/devtools/k6/k6-get-started/', + '/integrations/devtools/sql-projects/': + '/integrations/devtools/sql-projects/sql-projects-get-started/', + '/ja/integrations/frameworks/java/': '/integrations/frameworks/java/java-get-started/', + '/ja/integrations/frameworks/powershell/': + '/integrations/frameworks/powershell/powershell-get-started/', + '/ja/integrations/frameworks/rust/': '/integrations/frameworks/rust/rust-get-started/', + }); +});