Skip to content

Add polyglot exports for ActiveMQ#1176

Merged
aaronpowell merged 9 commits intomainfrom
dapine/polyglot-export-activemq
Mar 27, 2026
Merged

Add polyglot exports for ActiveMQ#1176
aaronpowell merged 9 commits intomainfrom
dapine/polyglot-export-activemq

Conversation

@IEvangelist
Copy link
Contributor

Summary

  • add AspireExport coverage for the ActiveMQ hosting integration
  • expose ActiveMQ resource properties for polyglot app hosts
  • add a TypeScript ValidationAppHost under playground/polyglot for export verification

Validation

  • dotnet pack src/CommunityToolkit.Aspire.Hosting.ActiveMQ/CommunityToolkit.Aspire.Hosting.ActiveMQ.csproj -c Debug -p:PackageVersion=13.2.1-polyglot.local
  • aspire restore + local package pinning in the ValidationAppHost
  • npx tsc --noEmit
  • detached apphost startup succeeded from a short temp mirror; classic2 and artemis2 containers started, while fixed-port classic and artemis remained in Starting during the smoke window

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 18, 2026 15:04
@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.sh | bash -s -- 1176

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/CommunityToolkit/Aspire/main/eng/scripts/dogfood-pr.ps1) } 1176"

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Aspire ATS/Polyglot export support to the ActiveMQ hosting integration and introduces a TypeScript ValidationAppHost to validate the exported surface from a polyglot app host.

Changes:

  • Export ActiveMQ resources and builder extension methods via AspireExport, and hide ATS-incompatible settings via AspireExportIgnore.
  • Add a TypeScript ValidationAppHost (tsconfig + npm project + sample apphost.ts) for ActiveMQ export validation.
  • Update .gitignore to ignore common playground build/output artifacts.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQServerResourceBase.cs Exports resource properties for polyglot hosts; ignores ATS-incompatible ActiveMqSettings.
src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQBuilderExtensions.cs Exports ActiveMQ/Artemis adders and volume/bind-mount fluent APIs for polyglot hosts.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/tsconfig.json TypeScript compiler configuration for the validation host.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/package.json NPM project metadata and scripts for building/running the validation host.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/package-lock.json Lockfile capturing the resolved dependency graph for the validation host.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/apphost.ts Validation app host script exercising exported APIs and property exposure.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/apphost.run.json Local run profile configuration for the validation host.
playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/.aspire/settings.json Aspire polyglot host settings referencing the ActiveMQ package.
.gitignore Ignores additional playground outputs (e.g., dist/, generated files).
Files not reviewed (1)
  • playground/polyglot/TypeScript/CommunityToolkit.Aspire.Hosting.ActiveMQ/ValidationAppHost/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQBuilderExtensions.cs:80

  • AddActiveMQArtemis doesn’t validate the builder argument, unlike AddActiveMQ. Passing a null builder will currently lead to a NullReferenceException later instead of an ArgumentNullException. Add ArgumentNullException.ThrowIfNull(builder, nameof(builder)); at the start for consistency and clearer failure behavior.
    [AspireExport("addActiveMQArtemis", Description = "Adds an ActiveMQ Artemis container resource")]
    public static IResourceBuilder<ActiveMQArtemisServerResource> AddActiveMQArtemis(this IDistributedApplicationBuilder builder,
        [ResourceName] string name,
        IResourceBuilder<ParameterResource>? userName = null,
        IResourceBuilder<ParameterResource>? password = null,
        int? port = null,
        string scheme = "tcp",
        int? webPort = null)
    {
        ArgumentNullException.ThrowIfNull(name, nameof(name));
        ArgumentNullException.ThrowIfNull(scheme, nameof(scheme));


You can also share your feedback on Copilot code review. Take the survey.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Diagnostics.CodeAnalysis;
using System.Text;
Comment on lines +11 to +12
#pragma warning disable ASPIREATS001 // AspireExport is experimental

Comment on lines +5 to +6
#pragma warning disable ASPIREATS001 // AspireExport is experimental

Copy link
Member

@aaronpowell aaronpowell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some thoughts on this design:

  • I'd prefer we don't create a new playground top level folder but instead work out how to continue using the examples folder. Maybe the existing app hosts should be turned to file-based and we have ts and cs side-by-side.
  • I want some way we can run a test or validation against the TypeScript app host. Right now, there's nothing in CI that validates that it is going to continue to work.
  • What do you think about making the TypeScript app host implement the same logic as the C# one so that we could (in theory) load it into a test runner and run automated tests?

@IEvangelist
Copy link
Contributor Author

Maybe the existing app hosts should be turned to file-based and we have ts and cs side-by-side.

The problem with this approach is the aspire.config.json points to a single apphost (and not all apphosts are created equally). There are nuances with the project-based vs file-based C# apphosts.

I want some way we can run a test or validation against the TypeScript app host. Right now, there's nothing in CI that validates that it is going to continue to work.

That's a good callout, and I do agree. The dotnet/aspire repo has a suite of e2e tests for various scenarios, it's a lot of code though to port/maintain/etc. What existing e2e testing infra does this repo have in place?

What do you think about making the TypeScript app host implement the same logic as the C# one so that we could (in theory) load it into a test runner and run automated tests?

That's a good idea! The playground approach is to ensure that the APIs we explicitly exported are in fact, generated as TypeScript compatible APIs. I'd argue that you'd really want to leave playground bits as they are, since they serve two different purposes (even though they slightly overlap).

@aaronpowell
Copy link
Member

Maybe the existing app hosts should be turned to file-based and we have ts and cs side-by-side.

The problem with this approach is the aspire.config.json points to a single apphost (and not all apphosts are created equally). There are nuances with the project-based vs file-based C# apphosts.

Oh, that's a bit of a pain. Maybe we'll have to have a <Integraton>.AppHost.TypeScript folder in the examples folder too.

What existing e2e testing infra does this repo have in place

Our test projects for the integration have a test class which uses the testing framework to start the app host, but this works by having a project reference. Have a look at AppHostTests in the ActiveMQ test project. It boils down to using DistributedApplicationFactory in a fixture for the tests, which takes an IProjectMetadata that has the path to the project to start the app host. I'm not familiar with how the bootstrap process of the polyglot app hosts works to know if you could just create your own implementation of that pointing to the TypeScript file - my gut says "probably not", but that could be a starting point.

That's a good idea! The playground approach is to ensure that the APIs we explicitly exported are in fact, generated as TypeScript compatible APIs. I'd argue that you'd really want to leave playground bits as they are, since they serve two different purposes (even though they slightly overlap).

If the intent of the playground is to validate that the API surface is properly covered, then we need something place to confirm that assumption. Right now, it would appear that there is a file in the repo that says "at some point in time this API was valid" but without any process to run the app host, test the app host, or something, we can't have confidence that it will continue to work.

@IEvangelist
Copy link
Contributor Author

Sorry @aaronpowell - been buried, not ignoring you...

IEvangelist and others added 3 commits March 25, 2026 00:16
- move the TypeScript apphost into examples
- add reusable TypeScript apphost validation coverage
- fix the ActiveMQ export review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Member

@aaronpowell aaronpowell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to add the Aspire CLI to the GitHub Actions, we don't do that now and that'd be why the TypeScript AppHost test failed.

Comment on lines +9 to +26
public async Task TypeScriptAppHostCompilesAndStarts()
{
string repoRoot = Path.GetFullPath(Path.Combine("..", "..", "..", "..", ".."));
string scriptPath = Path.Combine(repoRoot, "eng", "testing", "validate-typescript-apphost.ps1");
string appHostPath = Path.Combine(repoRoot, "examples", "activemq", "CommunityToolkit.Aspire.Hosting.ActiveMQ.AppHost.TypeScript", "apphost.ts");
string packageProjectPath = Path.Combine(repoRoot, "src", "CommunityToolkit.Aspire.Hosting.ActiveMQ", "CommunityToolkit.Aspire.Hosting.ActiveMQ.csproj");
string shell = OperatingSystem.IsWindows() ? "pwsh.exe" : "pwsh";

await ProcessTestUtilities.RunProcessAsync(shell, [
"-NoLogo",
"-NoProfile",
"-File", scriptPath,
"-AppHostPath", appHostPath,
"-PackageProjectPath", packageProjectPath,
"-PackageName", "CommunityToolkit.Aspire.Hosting.ActiveMQ",
"-WaitForResources", "classic,classic2,artemis,artemis2"
], repoRoot, TestContext.Current.CancellationToken);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reckon we can bundle this up a lot cleaner so that the test is doing a bit less lifting, and we rely more on conventions.

    public async Task TypeScriptAppHostCompilesAndStarts()
    {
        await TypeScriptAppHostTest.Run(
            appHostProject: "CommunityToolkit.Aspire.Hosting.ActiveMQ.AppHost.TypeScript",
            packageProject: "CommunityToolkit.Aspire.Hosting.ActiveMQ",
            exampleName: "activemq"
        );
    }

And then in the CommunityToolkit.Aspire.Testsings project we'd have:

public static class TypeScriptAppHostTest
{
    public static async Task Run(string appHostProject, string packageName, string exampleName)
    {
        string repoRoot = Path.GetFullPath(Path.Combine("..", "..", "..", "..", ".."));
        string scriptPath = Path.Combine(repoRoot, "eng", "testing", "validate-typescript-apphost.ps1");
        string appHostPath = Path.Combine(repoRoot, "examples", exampleName, appHostProject, "apphost.ts");
        string packageProjectPath = Path.Combine(repoRoot, "src", packageName, $"{packageName}.csproj");
        string shell = OperatingSystem.IsWindows() ? "pwsh.exe" : "pwsh";

        await ProcessTestUtilities.RunProcessAsync(shell, [
            "-NoLogo",
            "-NoProfile",
            "-File", scriptPath,
            "-AppHostPath", appHostPath,
            "-PackageProjectPath", packageProjectPath,
            "-PackageName", packageName,
            "-WaitForResources", "classic,classic2,artemis,artemis2"
        ], repoRoot, TestContext.Current.CancellationToken);
    }
}

IEvangelist and others added 2 commits March 26, 2026 15:30
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@aaronpowell aaronpowell merged commit e1489df into main Mar 27, 2026
240 of 244 checks passed
@aaronpowell aaronpowell deleted the dapine/polyglot-export-activemq branch March 27, 2026 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants