From 619ba8a9af9691711041d00424b60c172d9b3427 Mon Sep 17 00:00:00 2001 From: Omnideth Date: Wed, 25 Mar 2026 21:36:33 -0500 Subject: [PATCH 1/7] Beginning perl changes. --- src/frontend/src/assets/icons/perl-096-1500.svg | 4 ++++ .../docs/integrations/frameworks/perl.mdx | 17 +++++++++++++++++ .../src/data/aspire-integration-names.json | 1 + src/frontend/src/data/thanks-license-titles.ts | 2 ++ 4 files changed, 24 insertions(+) create mode 100644 src/frontend/src/assets/icons/perl-096-1500.svg create mode 100644 src/frontend/src/content/docs/integrations/frameworks/perl.mdx diff --git a/src/frontend/src/assets/icons/perl-096-1500.svg b/src/frontend/src/assets/icons/perl-096-1500.svg new file mode 100644 index 000000000..35b3f2eba --- /dev/null +++ b/src/frontend/src/assets/icons/perl-096-1500.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx new file mode 100644 index 000000000..1dd0871d7 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx @@ -0,0 +1,17 @@ +--- +Title: Perl Integration +--- + +import { Badge } from '@astrojs/starlight/components'; +import perlIcon from '@assets/icons/perl-096-1500.svg'; + + + +Perl Camel \ No newline at end of file diff --git a/src/frontend/src/data/aspire-integration-names.json b/src/frontend/src/data/aspire-integration-names.json index 098d801bf..23b70f67e 100644 --- a/src/frontend/src/data/aspire-integration-names.json +++ b/src/frontend/src/data/aspire-integration-names.json @@ -117,6 +117,7 @@ "CommunityToolkit.Aspire.Hosting.Ollama", "CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector", "CommunityToolkit.Aspire.Hosting.PapercutSmtp", + "CommunityToolkit.Aspire.Hosting.Perl", "CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions", "CommunityToolkit.Aspire.Hosting.PowerShell", "CommunityToolkit.Aspire.Hosting.Python.Extensions", diff --git a/src/frontend/src/data/thanks-license-titles.ts b/src/frontend/src/data/thanks-license-titles.ts index 57f292c8a..9ca2719ac 100644 --- a/src/frontend/src/data/thanks-license-titles.ts +++ b/src/frontend/src/data/thanks-license-titles.ts @@ -49,4 +49,6 @@ export const licenseTitles = { dapr: 'Apache-2.0: https://github.com/dapr/dapr/blob/master/LICENSE', hex1b: 'MIT: https://hex1b.dev', asciinema: 'GPL-3.0: https://github.com/asciinema/asciinema/blob/develop/LICENSE', + perl-assets: 'CC-BY-4.0: https://github.com/metacpan/perl-assets?tab=CC-BY-4.0-1-ov-file#readme', + perl: 'Artistic License: https://dev.perl.org/licenses/artistic.html', } as const; \ No newline at end of file From 45167ac93d6fec9962ccf1325189f9f0f2b47ec0 Mon Sep 17 00:00:00 2001 From: Omnideth Date: Tue, 31 Mar 2026 20:54:07 -0500 Subject: [PATCH 2/7] Wiring up display via topics. --- src/frontend/config/sidebar/integrations.topics.ts | 9 +++++++++ .../src/content/docs/integrations/frameworks/perl.mdx | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/frontend/config/sidebar/integrations.topics.ts b/src/frontend/config/sidebar/integrations.topics.ts index d9d594d46..21289d34c 100644 --- a/src/frontend/config/sidebar/integrations.topics.ts +++ b/src/frontend/config/sidebar/integrations.topics.ts @@ -1343,6 +1343,15 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { { label: 'Dapr', slug: 'integrations/frameworks/dapr' }, { label: 'Go', slug: 'integrations/frameworks/go-apps' }, { label: 'Java', slug: 'integrations/frameworks/java' }, + { label: 'Bun', slug: 'integrations/frameworks/bun-apps' }, + { label: 'Dapr', slug: 'integrations/frameworks/dapr' }, + { label: 'Deno', slug: 'integrations/frameworks/deno-apps' }, + { label: 'Go', slug: 'integrations/frameworks/go-apps' }, + { label: 'Java', slug: 'integrations/frameworks/java' }, + { label: 'JavaScript', slug: 'integrations/frameworks/javascript' }, + { label: 'Node.js extensions', slug: 'integrations/frameworks/nodejs-extensions' }, + { label: 'Orleans', slug: 'integrations/frameworks/orleans' }, + { label: 'Perl', slug: 'integrations/frameworks/perl' }, { label: 'PowerShell', slug: 'integrations/frameworks/powershell' }, { label: 'Python', slug: 'integrations/frameworks/python' }, { label: 'Rust', slug: 'integrations/frameworks/rust' }, diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx index 1dd0871d7..99ff60d75 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx @@ -1,8 +1,9 @@ --- -Title: Perl Integration +title: Perl Integration --- import { Badge } from '@astrojs/starlight/components'; +import { Image } from 'astro:assets'; import perlIcon from '@assets/icons/perl-096-1500.svg'; From 9b81dc58deebffb4da7adba542baeb3df2b17baa Mon Sep 17 00:00:00 2001 From: Omnideth Date: Tue, 31 Mar 2026 22:10:05 -0500 Subject: [PATCH 3/7] Now just need to push in the docs. --- src/frontend/src/content/docs/integrations/frameworks/perl.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx index 99ff60d75..95adc7330 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx @@ -15,4 +15,5 @@ import perlIcon from '@assets/icons/perl-096-1500.svg'; height={20} class:list={'float-inline-left icon'} data-zoom-off -/> \ No newline at end of file +/> + From 446a1f491bbbf66f830b33a960ee88024fa52c5e Mon Sep 17 00:00:00 2001 From: Matthew Austew Date: Thu, 2 Apr 2026 16:53:50 -0500 Subject: [PATCH 4/7] Accidentally forgot the final documentation addition, just sent up the harness first. Also changed some of the feedback from the PR. --- .../docs/integrations/frameworks/perl.mdx | 377 +++++++++++++++++- 1 file changed, 374 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx index 95adc7330..aec50a572 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx @@ -1,5 +1,5 @@ --- -title: Perl Integration +title: Perl integration --- import { Badge } from '@astrojs/starlight/components'; @@ -11,9 +11,380 @@ import perlIcon from '@assets/icons/perl-096-1500.svg'; Perl Camel +## Using the Perl Hosting Integration + +A guide for developers using `CommunityToolkit.Aspire.Hosting.Perl` for the first time, or as a +reference when revisiting the API. This document explains how key hosting API calls map to on-disk +directory layout, environment variable configuration, and runtime behavior. + +--- + +## Table of Contents + +1. [Quick Start](#quick-start) +2. [Core Concepts](#core-concepts) +3. [The `appDirectory` Parameter](#the-appdirectory-parameter) +4. [WithLocalLib](#withlocallib) +5. [Package Management](#package-management) + - [WithCpanMinus + WithPackage](#withcpanminus--withpackage) + - [WithCpanMinus + WithProjectDependencies](#withcpanminus--withprojectdependencies) + - [WithCarton + WithProjectDependencies](#withcarton--withprojectdependencies) +6. [WithPerlbrewEnvironment](#withperlbrewenvironment) +7. [Common Pitfalls](#common-pitfalls) +8. [Reporting an Issue](#reporting-issues) + +--- + +## Quick Start + +Install the package in your AppHost project: + +```dotnetcli +dotnet add package CommunityToolkit.Aspire.Hosting.Perl +``` + +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/... +``` + +> **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()` | + +> 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) + +## Reporting Issues + +If you notice an issue with these docs while using the integration, please file an issue at [microsoft/aspire.dev](https://github.com/microsoft/aspire.dev) \ No newline at end of file From 98479348235fd59fd41dbf196fc648b8ae2ee1f0 Mon Sep 17 00:00:00 2001 From: Matthew Austew Date: Fri, 3 Apr 2026 09:27:51 -0500 Subject: [PATCH 5/7] Updated to add contributor guide steps for an integration, then also fixing the thanks-license-titles.ts --- .../docs/community/contributor-guide.mdx | 42 +++++++++++++++++++ .../src/data/thanks-license-titles.ts | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/content/docs/community/contributor-guide.mdx b/src/frontend/src/content/docs/community/contributor-guide.mdx index 2cf1a660a..6772ea3cd 100644 --- a/src/frontend/src/content/docs/community/contributor-guide.mdx +++ b/src/frontend/src/content/docs/community/contributor-guide.mdx @@ -174,6 +174,48 @@ Without the blank lines between steps, the inner content won't render correctly. +## 🧩 Adding a new framework integration + +If you've built a new Community Toolkit hosting integration (e.g. `CommunityToolkit.Aspire.Hosting.`) and want to document it on `aspire.dev`, you'll need to touch several files. Here's a summary of the steps, using the Perl integration as an example: + + + +1. **Create the documentation page** + + Add a new MDX file at `src/frontend/src/content/docs/integrations/frameworks/.mdx`. Use an existing framework page (such as `python.mdx` or `java.mdx`) as a template. Include frontmatter with a `title`, any required component imports, and a `Badge` indicating it's a Community Toolkit integration. + +1. **Add an icon asset** + + Place an SVG icon for the framework in `src/frontend/src/assets/icons/`. Reference it in your MDX page with an `Image` component import. + +1. **Register the sidebar entry** + + In `src/frontend/config/sidebar/integrations.topics.ts`, add a new entry for your framework in the frameworks list (keep alphabetical order): + + ```ts + { label: '', slug: 'integrations/frameworks/' }, + ``` + +1. **Add the NuGet package name** + + In `src/frontend/src/data/aspire-integration-names.json`, add the full NuGet package name for your integration (keep alphabetical order): + + ```json + "CommunityToolkit.Aspire.Hosting.", + ``` + +1. **Add license attribution** + + If your integration uses assets or technologies with specific licenses, add entries in `src/frontend/src/data/thanks-license-titles.ts`: + + ```ts + '': ': ', + ``` + + + +After making these changes, run `pnpm dev` (or `aspire start`) locally to verify the page renders correctly, the sidebar navigation works, and the icon displays as expected. + ## ✍️ Writing style guide diff --git a/src/frontend/src/data/thanks-license-titles.ts b/src/frontend/src/data/thanks-license-titles.ts index 9ca2719ac..372618bc8 100644 --- a/src/frontend/src/data/thanks-license-titles.ts +++ b/src/frontend/src/data/thanks-license-titles.ts @@ -49,6 +49,6 @@ export const licenseTitles = { dapr: 'Apache-2.0: https://github.com/dapr/dapr/blob/master/LICENSE', hex1b: 'MIT: https://hex1b.dev', asciinema: 'GPL-3.0: https://github.com/asciinema/asciinema/blob/develop/LICENSE', - perl-assets: 'CC-BY-4.0: https://github.com/metacpan/perl-assets?tab=CC-BY-4.0-1-ov-file#readme', + perlAssets: 'CC-BY-4.0: https://github.com/metacpan/perl-assets?tab=CC-BY-4.0-1-ov-file#readme', perl: 'Artistic License: https://dev.perl.org/licenses/artistic.html', } as const; \ No newline at end of file From 9f17067b5dc19663d12c336cc2ae95c9661f9298 Mon Sep 17 00:00:00 2001 From: Omnideth Date: Sun, 12 Apr 2026 08:50:44 -0500 Subject: [PATCH 6/7] Cleanup of the integrations.topics file from a bad merge? --- src/frontend/config/sidebar/integrations.topics.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/frontend/config/sidebar/integrations.topics.ts b/src/frontend/config/sidebar/integrations.topics.ts index 21289d34c..6360d73bb 100644 --- a/src/frontend/config/sidebar/integrations.topics.ts +++ b/src/frontend/config/sidebar/integrations.topics.ts @@ -1343,13 +1343,6 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { { label: 'Dapr', slug: 'integrations/frameworks/dapr' }, { label: 'Go', slug: 'integrations/frameworks/go-apps' }, { label: 'Java', slug: 'integrations/frameworks/java' }, - { label: 'Bun', slug: 'integrations/frameworks/bun-apps' }, - { label: 'Dapr', slug: 'integrations/frameworks/dapr' }, - { label: 'Deno', slug: 'integrations/frameworks/deno-apps' }, - { label: 'Go', slug: 'integrations/frameworks/go-apps' }, - { label: 'Java', slug: 'integrations/frameworks/java' }, - { label: 'JavaScript', slug: 'integrations/frameworks/javascript' }, - { label: 'Node.js extensions', slug: 'integrations/frameworks/nodejs-extensions' }, { label: 'Orleans', slug: 'integrations/frameworks/orleans' }, { label: 'Perl', slug: 'integrations/frameworks/perl' }, { label: 'PowerShell', slug: 'integrations/frameworks/powershell' }, From 1c8db499b09889ccf41a4a746072e663186ac96b Mon Sep 17 00:00:00 2001 From: Omnideth Date: Sun, 12 Apr 2026 10:30:35 -0500 Subject: [PATCH 7/7] Updated to address all feedback. --- .../docs/integrations/frameworks/perl.mdx | 58 +++++-------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx index aec50a572..28d4cf708 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/perl.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/perl.mdx @@ -2,7 +2,7 @@ title: Perl integration --- -import { Badge } from '@astrojs/starlight/components'; +import { Aside, Badge, Steps } from '@astrojs/starlight/components'; import { Image } from 'astro:assets'; import perlIcon from '@assets/icons/perl-096-1500.svg'; @@ -23,25 +23,7 @@ A guide for developers using `CommunityToolkit.Aspire.Hosting.Perl` for the firs reference when revisiting the API. This document explains how key hosting API calls map to on-disk directory layout, environment variable configuration, and runtime behavior. ---- - -## Table of Contents - -1. [Quick Start](#quick-start) -2. [Core Concepts](#core-concepts) -3. [The `appDirectory` Parameter](#the-appdirectory-parameter) -4. [WithLocalLib](#withlocallib) -5. [Package Management](#package-management) - - [WithCpanMinus + WithPackage](#withcpanminus--withpackage) - - [WithCpanMinus + WithProjectDependencies](#withcpanminus--withprojectdependencies) - - [WithCarton + WithProjectDependencies](#withcarton--withprojectdependencies) -6. [WithPerlbrewEnvironment](#withperlbrewenvironment) -7. [Common Pitfalls](#common-pitfalls) -8. [Reporting an Issue](#reporting-issues) - ---- - -## Quick Start +## Quick start Install the package in your AppHost project: @@ -62,9 +44,7 @@ builder.AddPerlScript("my-worker", "scripts", "Worker.pl") builder.Build().Run(); ``` ---- - -## Core Concepts +## Core concepts The integration provides two entry points for adding Perl resources: @@ -76,9 +56,7 @@ The integration provides two entry points for adding Perl resources: 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 +## The `appDirectory` parameter `appDirectory` is the **anchor for all relative path resolution** in the integration. It determines: @@ -127,15 +105,15 @@ scripts/ ← working directory > **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` accepts a single `path` argument: + +| Argument Example | Type | Behavior | +|------------------|------|----------| +| `"local"` | Relative path | Resolved against `appDirectory` | +| `"/opt/lib"` | Rooted Unix-style path | Used as-is | +| `"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`), @@ -168,8 +146,6 @@ These ensure that: | `"."` | `"/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: @@ -180,6 +156,7 @@ While I highly recommend you use cpanm or Carton, the integration aims to suppor | **cpanm** (App::cpanminus) | ✅ `.WithCpanMinus().WithPackage("Module")` | ✅ `.WithCpanMinus().WithProjectDependencies()` | | **Carton** | ❌ Not supported | ✅ `.WithCarton().WithProjectDependencies()` | +> [!NOTE] > 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. @@ -235,10 +212,11 @@ builder.AddPerlApi("api", ".", "../scripts/API.pl") ``` **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 @@ -283,8 +261,6 @@ my-example/ > 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 @@ -308,9 +284,7 @@ allows per-project isolation. `WithLocalLib` is optional when using perlbrew. > recommending [Berrybrew](https://github.com/stevieb9/berrybrew). Windows support for Berrybrew > is on the roadmap. ---- - -## Common Pitfalls +## Common pitfalls ### WithLocalLib resolves relative to `appDirectory`, not the AppHost @@ -385,6 +359,6 @@ on 'test' => sub { Further reading: - [CPAN::cpanfile reference](https://github.com/miyagawa/cpanfile/blob/master/README.md) -## Reporting Issues +## Reporting issues If you notice an issue with these docs while using the integration, please file an issue at [microsoft/aspire.dev](https://github.com/microsoft/aspire.dev) \ No newline at end of file