Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .github/workflows/polyglot-validation/Dockerfile.golang
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@
#
# Note: Expects self-extracting binary and NuGet artifacts to be pre-downloaded to /workspace/artifacts/
#
FROM mcr.microsoft.com/devcontainers/go:1.26-trixie
FROM golang:1.26-trixie

# Ensure Yarn APT repository signing key is available (base image includes Yarn repo)
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /etc/apt/keyrings/yarn-archive-keyring.gpg > /dev/null

# Install system dependencies (wget, docker CLI, jq for JSON manipulation)
# Install system dependencies (wget, Docker CLI, jq for JSON manipulation, ICU for the Aspire CLI)
RUN apt-get update && apt-get install -y \
wget \
docker.io \
jq \
libicu76 \
&& rm -rf /var/lib/apt/lists/*

# Pre-configure Aspire CLI path
Expand Down
51 changes: 51 additions & 0 deletions src/Aspire.Hosting/Ats/BuilderExports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Eventing;
using Aspire.Hosting.Publishing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

Expand Down Expand Up @@ -30,6 +31,8 @@ namespace Aspire.Hosting.Ats;
/// <list type="bullet">
/// <item><description><c>subscribeBeforeStart</c> - Called before the application starts</description></item>
/// <item><description><c>subscribeAfterResourcesCreated</c> - Called after resources are created</description></item>
/// <item><description><c>subscribeBeforePublish</c> - Called before the application is published</description></item>
/// <item><description><c>subscribeAfterPublish</c> - Called after the application is published</description></item>
/// </list>
/// </para>
/// </remarks>
Expand Down Expand Up @@ -209,6 +212,54 @@ public static DistributedApplicationEventSubscription SubscribeBeforeStart(
});
}

/// <summary>
/// Subscribes to the BeforePublish event, which fires before the application is published.
/// </summary>
/// <remarks>
/// This event provides access to the service provider and distributed application model,
/// allowing you to perform final configuration or validation before publish pipeline steps run.
/// </remarks>
/// <param name="builder">The builder handle.</param>
/// <param name="callback">A callback that receives the exported event when the event fires.</param>
/// <returns>A subscription handle that can be used to unsubscribe.</returns>
[AspireExport(Description = "Subscribes to the BeforePublish event")]
public static DistributedApplicationEventSubscription SubscribeBeforePublish(
this IDistributedApplicationBuilder builder,
Func<BeforePublishEvent, Task> callback)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(callback);

return builder.Eventing.Subscribe<BeforePublishEvent>(async (@event, ct) =>
{
await callback(@event).ConfigureAwait(false);
});
}

/// <summary>
/// Subscribes to the AfterPublish event, which fires after the application is published.
/// </summary>
/// <remarks>
/// This event provides access to the service provider and distributed application model,
/// allowing you to inspect the model after publish pipeline steps complete.
/// </remarks>
/// <param name="builder">The builder handle.</param>
/// <param name="callback">A callback that receives the exported event when the event fires.</param>
/// <returns>A subscription handle that can be used to unsubscribe.</returns>
[AspireExport(Description = "Subscribes to the AfterPublish event")]
public static DistributedApplicationEventSubscription SubscribeAfterPublish(
this IDistributedApplicationBuilder builder,
Func<AfterPublishEvent, Task> callback)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(callback);

return builder.Eventing.Subscribe<AfterPublishEvent>(async (@event, ct) =>
{
await callback(@event).ConfigureAwait(false);
});
}

/// <summary>
/// Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
/// </summary>
Expand Down
31 changes: 31 additions & 0 deletions src/Aspire.Hosting/Ats/ServiceCollectionExports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Eventing;
using Aspire.Hosting.Lifecycle;
using Aspire.Hosting.Publishing;
using Microsoft.Extensions.DependencyInjection;

namespace Aspire.Hosting.Ats;
Expand Down Expand Up @@ -76,6 +77,36 @@ public static DistributedApplicationEventSubscription OnBeforeStart(this Eventin
return context.Eventing.Subscribe<BeforeStartEvent>((@event, _) => callback(@event));
}

/// <summary>
/// Subscribes to the BeforePublish event from an eventing subscriber registration context.
/// </summary>
/// <param name="context">The eventing subscriber registration context.</param>
/// <param name="callback">The callback to invoke when the event fires.</param>
/// <returns>The event subscription.</returns>
[AspireExport("eventingSubscriberOnBeforePublish", MethodName = "onBeforePublish", Description = "Subscribes an eventing subscriber to the BeforePublish event")]
public static DistributedApplicationEventSubscription OnBeforePublish(this EventingSubscriberRegistrationContext context, Func<BeforePublishEvent, Task> callback)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(callback);

return context.Eventing.Subscribe<BeforePublishEvent>((@event, _) => callback(@event));
}

/// <summary>
/// Subscribes to the AfterPublish event from an eventing subscriber registration context.
/// </summary>
/// <param name="context">The eventing subscriber registration context.</param>
/// <param name="callback">The callback to invoke when the event fires.</param>
/// <returns>The event subscription.</returns>
[AspireExport("eventingSubscriberOnAfterPublish", MethodName = "onAfterPublish", Description = "Subscribes an eventing subscriber to the AfterPublish event")]
public static DistributedApplicationEventSubscription OnAfterPublish(this EventingSubscriberRegistrationContext context, Func<AfterPublishEvent, Task> callback)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(callback);

return context.Eventing.Subscribe<AfterPublishEvent>((@event, _) => callback(@event));
}

/// <summary>
/// Subscribes to the AfterResourcesCreated event from an eventing subscriber registration context.
/// </summary>
Expand Down
3 changes: 2 additions & 1 deletion src/Aspire.Hosting/Publishing/AfterPublishEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Aspire.Hosting.Publishing;
/// </summary>
/// <param name="services">The <see cref="IServiceProvider"/> for the app host.</param>
/// <param name="model">The <see cref="DistributedApplicationModel"/>.</param>
[AspireExport(ExposeProperties = true)]
public sealed class AfterPublishEvent(IServiceProvider services, DistributedApplicationModel model) : IDistributedApplicationEvent
{
/// <summary>
Expand All @@ -22,4 +23,4 @@ public sealed class AfterPublishEvent(IServiceProvider services, DistributedAppl
/// The <see cref="DistributedApplicationModel"/> instance.
/// </summary>
public DistributedApplicationModel Model { get; } = model;
}
}
3 changes: 2 additions & 1 deletion src/Aspire.Hosting/Publishing/BeforePublishEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Aspire.Hosting.Publishing;
/// </summary>
/// <param name="services">The <see cref="IServiceProvider"/> for the app host.</param>
/// <param name="model">The <see cref="DistributedApplicationModel"/>.</param>
[AspireExport(ExposeProperties = true)]
public sealed class BeforePublishEvent(IServiceProvider services, DistributedApplicationModel model) : IDistributedApplicationEvent
{
/// <summary>
Expand All @@ -22,4 +23,4 @@ public sealed class BeforePublishEvent(IServiceProvider services, DistributedApp
/// The <see cref="DistributedApplicationModel"/> instance.
/// </summary>
public DistributedApplicationModel Model { get; } = model;
}
}
8 changes: 8 additions & 0 deletions src/Aspire.Hosting/api/Aspire.Hosting.Capabilities.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepContext [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepFactoryContext [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineSummary [ExposeMethods]
Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent [ExposeProperties]
Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfiguration [interface]
Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfigurationSection [interface, ExposeProperties]
Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.IHostEnvironment [interface, ExposeProperties]
Expand Down Expand Up @@ -232,6 +234,10 @@ Aspire.Hosting.Pipelines/PipelineStepFactoryContext.setPipelineContext(context:
Aspire.Hosting.Pipelines/PipelineStepFactoryContext.setResource(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepFactoryContext, value: Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource) -> Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepFactoryContext
Aspire.Hosting.Pipelines/PipelineSummary.add(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineSummary, key: string, value: string) -> void
Aspire.Hosting.Pipelines/requiredBy(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep, stepName: string) -> void
Aspire.Hosting.Publishing/AfterPublishEvent.model(context: Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.DistributedApplicationModel
Aspire.Hosting.Publishing/AfterPublishEvent.services(context: Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent) -> System.ComponentModel/System.IServiceProvider
Aspire.Hosting.Publishing/BeforePublishEvent.model(context: Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.DistributedApplicationModel
Aspire.Hosting.Publishing/BeforePublishEvent.services(context: Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent) -> System.ComponentModel/System.IServiceProvider
Aspire.Hosting/addConnectionString(name: string, environmentVariableName?: string) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithConnectionString
Aspire.Hosting/addConnectionStringBuilder(name: string, connectionStringBuilder: callback) -> Aspire.Hosting/Aspire.Hosting.ConnectionStringResource
Aspire.Hosting/addConnectionStringExpression(name: string, connectionStringExpression: Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression) -> Aspire.Hosting/Aspire.Hosting.ConnectionStringResource
Expand Down Expand Up @@ -350,7 +356,9 @@ Aspire.Hosting/publishResourceUpdate(resource: Aspire.Hosting/Aspire.Hosting.App
Aspire.Hosting/publishWithContainerFiles(source: Aspire.Hosting/Aspire.Hosting.IResourceWithContainerFiles, destinationPath: string) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.IContainerFilesDestinationResource
Aspire.Hosting/run(context: Aspire.Hosting/Aspire.Hosting.DistributedApplication, cancellationToken?: cancellationToken) -> void
Aspire.Hosting/saveStateJson(json: string, cancellationToken?: cancellationToken) -> void
Aspire.Hosting/subscribeAfterPublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeAfterResourcesCreated(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeBeforePublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeBeforeStart(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/tryGetResourceState(resourceName: string) -> Aspire.Hosting/Aspire.Hosting.Ats.ResourceEventDto
Aspire.Hosting/updateTask(statusText: string, cancellationToken?: cancellationToken) -> void
Expand Down
10 changes: 10 additions & 0 deletions src/Aspire.Hosting/api/Aspire.Hosting.ats.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepContext [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepFactoryContext [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineSummary [ExposeMethods]
Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent [ExposeProperties]
Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent [ExposeProperties]
Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfiguration [interface]
Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfigurationSection [interface, ExposeProperties]
Microsoft.Extensions.Hosting.Abstractions/Microsoft.Extensions.Hosting.IHostEnvironment [interface, ExposeProperties]
Expand Down Expand Up @@ -400,6 +402,10 @@ Aspire.Hosting.Pipelines/PipelineSummary.add(context: Aspire.Hosting/Aspire.Host
Aspire.Hosting.Pipelines/requiredBy(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep, stepName: string) -> void
Aspire.Hosting.Pipelines/steps(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineEditor) -> Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep[]
Aspire.Hosting.Pipelines/stepsByTag(context: Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineEditor, tag: string) -> Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep[]
Aspire.Hosting.Publishing/AfterPublishEvent.model(context: Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.DistributedApplicationModel
Aspire.Hosting.Publishing/AfterPublishEvent.services(context: Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent) -> System.ComponentModel/System.IServiceProvider
Aspire.Hosting.Publishing/BeforePublishEvent.model(context: Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.DistributedApplicationModel
Aspire.Hosting.Publishing/BeforePublishEvent.services(context: Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent) -> System.ComponentModel/System.IServiceProvider
Aspire.Hosting/addConnectionString(name: string, environmentVariableNameOrExpression?: string|Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResourceWithConnectionString
Aspire.Hosting/addContainer(name: string, image: string|Aspire.Hosting/Aspire.Hosting.Ats.AddContainerOptions) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerResource
Aspire.Hosting/addContainerRegistry(name: string, endpoint: string|Aspire.Hosting/Aspire.Hosting.ApplicationModel.ParameterResource, repository?: string|Aspire.Hosting/Aspire.Hosting.ApplicationModel.ParameterResource) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerRegistryResource
Expand Down Expand Up @@ -462,7 +468,9 @@ Aspire.Hosting/dockerfileStageRun(command: string) -> Aspire.Hosting/Aspire.Host
Aspire.Hosting/emptyLine() -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.Docker.DockerfileStage
Aspire.Hosting/entrypoint(command: string[]) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.Docker.DockerfileStage
Aspire.Hosting/env(name: string, value: string) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.Docker.DockerfileStage
Aspire.Hosting/eventingSubscriberOnAfterPublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/eventingSubscriberOnAfterResourcesCreated(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/eventingSubscriberOnBeforePublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/eventingSubscriberOnBeforeStart(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/excludeFromManifest() -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource
Aspire.Hosting/excludeFromMcp() -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource
Expand Down Expand Up @@ -544,7 +552,9 @@ Aspire.Hosting/publishWithContainerFilesFromResource(source: Aspire.Hosting/Aspi
Aspire.Hosting/run(context: Aspire.Hosting/Aspire.Hosting.DistributedApplication, cancellationToken?: cancellationToken) -> void
Aspire.Hosting/runWithMounts(command: string, mounts: string[]) -> Aspire.Hosting/Aspire.Hosting.ApplicationModel.Docker.DockerfileStage
Aspire.Hosting/saveStateJson(json: string, cancellationToken?: cancellationToken) -> void
Aspire.Hosting/subscribeAfterPublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeAfterResourcesCreated(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeBeforePublish(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/subscribeBeforeStart(callback: callback) -> Aspire.Hosting/Aspire.Hosting.Eventing.DistributedApplicationEventSubscription
Aspire.Hosting/tryAddEventingSubscriber(subscribe: callback) -> void
Aspire.Hosting/tryGetResourceState(resourceName: string) -> Aspire.Hosting/Aspire.Hosting.Ats.ResourceEventDto
Expand Down
Loading
Loading