diff --git a/.github/workflows/polyglot-validation/Dockerfile.golang b/.github/workflows/polyglot-validation/Dockerfile.golang
index 154c87af2a2..42075d6de69 100644
--- a/.github/workflows/polyglot-validation/Dockerfile.golang
+++ b/.github/workflows/polyglot-validation/Dockerfile.golang
@@ -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
diff --git a/src/Aspire.Hosting/Ats/BuilderExports.cs b/src/Aspire.Hosting/Ats/BuilderExports.cs
index 8bfca79182b..95954787770 100644
--- a/src/Aspire.Hosting/Ats/BuilderExports.cs
+++ b/src/Aspire.Hosting/Ats/BuilderExports.cs
@@ -3,6 +3,7 @@
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Eventing;
+using Aspire.Hosting.Publishing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
@@ -30,6 +31,8 @@ namespace Aspire.Hosting.Ats;
///
/// - subscribeBeforeStart - Called before the application starts
/// - subscribeAfterResourcesCreated - Called after resources are created
+/// - subscribeBeforePublish - Called before the application is published
+/// - subscribeAfterPublish - Called after the application is published
///
///
///
@@ -209,6 +212,54 @@ public static DistributedApplicationEventSubscription SubscribeBeforeStart(
});
}
+ ///
+ /// Subscribes to the BeforePublish event, which fires before the application is published.
+ ///
+ ///
+ /// 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.
+ ///
+ /// The builder handle.
+ /// A callback that receives the exported event when the event fires.
+ /// A subscription handle that can be used to unsubscribe.
+ [AspireExport(Description = "Subscribes to the BeforePublish event")]
+ public static DistributedApplicationEventSubscription SubscribeBeforePublish(
+ this IDistributedApplicationBuilder builder,
+ Func callback)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(callback);
+
+ return builder.Eventing.Subscribe(async (@event, ct) =>
+ {
+ await callback(@event).ConfigureAwait(false);
+ });
+ }
+
+ ///
+ /// Subscribes to the AfterPublish event, which fires after the application is published.
+ ///
+ ///
+ /// This event provides access to the service provider and distributed application model,
+ /// allowing you to inspect the model after publish pipeline steps complete.
+ ///
+ /// The builder handle.
+ /// A callback that receives the exported event when the event fires.
+ /// A subscription handle that can be used to unsubscribe.
+ [AspireExport(Description = "Subscribes to the AfterPublish event")]
+ public static DistributedApplicationEventSubscription SubscribeAfterPublish(
+ this IDistributedApplicationBuilder builder,
+ Func callback)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(callback);
+
+ return builder.Eventing.Subscribe(async (@event, ct) =>
+ {
+ await callback(@event).ConfigureAwait(false);
+ });
+ }
+
///
/// Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
///
diff --git a/src/Aspire.Hosting/Ats/ServiceCollectionExports.cs b/src/Aspire.Hosting/Ats/ServiceCollectionExports.cs
index 084c22bcba7..a7198497743 100644
--- a/src/Aspire.Hosting/Ats/ServiceCollectionExports.cs
+++ b/src/Aspire.Hosting/Ats/ServiceCollectionExports.cs
@@ -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;
@@ -76,6 +77,36 @@ public static DistributedApplicationEventSubscription OnBeforeStart(this Eventin
return context.Eventing.Subscribe((@event, _) => callback(@event));
}
+ ///
+ /// Subscribes to the BeforePublish event from an eventing subscriber registration context.
+ ///
+ /// The eventing subscriber registration context.
+ /// The callback to invoke when the event fires.
+ /// The event subscription.
+ [AspireExport("eventingSubscriberOnBeforePublish", MethodName = "onBeforePublish", Description = "Subscribes an eventing subscriber to the BeforePublish event")]
+ public static DistributedApplicationEventSubscription OnBeforePublish(this EventingSubscriberRegistrationContext context, Func callback)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+ ArgumentNullException.ThrowIfNull(callback);
+
+ return context.Eventing.Subscribe((@event, _) => callback(@event));
+ }
+
+ ///
+ /// Subscribes to the AfterPublish event from an eventing subscriber registration context.
+ ///
+ /// The eventing subscriber registration context.
+ /// The callback to invoke when the event fires.
+ /// The event subscription.
+ [AspireExport("eventingSubscriberOnAfterPublish", MethodName = "onAfterPublish", Description = "Subscribes an eventing subscriber to the AfterPublish event")]
+ public static DistributedApplicationEventSubscription OnAfterPublish(this EventingSubscriberRegistrationContext context, Func callback)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+ ArgumentNullException.ThrowIfNull(callback);
+
+ return context.Eventing.Subscribe((@event, _) => callback(@event));
+ }
+
///
/// Subscribes to the AfterResourcesCreated event from an eventing subscriber registration context.
///
diff --git a/src/Aspire.Hosting/Publishing/AfterPublishEvent.cs b/src/Aspire.Hosting/Publishing/AfterPublishEvent.cs
index 1ab45f4e543..69adce6db69 100644
--- a/src/Aspire.Hosting/Publishing/AfterPublishEvent.cs
+++ b/src/Aspire.Hosting/Publishing/AfterPublishEvent.cs
@@ -11,6 +11,7 @@ namespace Aspire.Hosting.Publishing;
///
/// The for the app host.
/// The .
+[AspireExport(ExposeProperties = true)]
public sealed class AfterPublishEvent(IServiceProvider services, DistributedApplicationModel model) : IDistributedApplicationEvent
{
///
@@ -22,4 +23,4 @@ public sealed class AfterPublishEvent(IServiceProvider services, DistributedAppl
/// The instance.
///
public DistributedApplicationModel Model { get; } = model;
-}
\ No newline at end of file
+}
diff --git a/src/Aspire.Hosting/Publishing/BeforePublishEvent.cs b/src/Aspire.Hosting/Publishing/BeforePublishEvent.cs
index dc6e26947da..b8d7b0100a6 100644
--- a/src/Aspire.Hosting/Publishing/BeforePublishEvent.cs
+++ b/src/Aspire.Hosting/Publishing/BeforePublishEvent.cs
@@ -11,6 +11,7 @@ namespace Aspire.Hosting.Publishing;
///
/// The for the app host.
/// The .
+[AspireExport(ExposeProperties = true)]
public sealed class BeforePublishEvent(IServiceProvider services, DistributedApplicationModel model) : IDistributedApplicationEvent
{
///
@@ -22,4 +23,4 @@ public sealed class BeforePublishEvent(IServiceProvider services, DistributedApp
/// The instance.
///
public DistributedApplicationModel Model { get; } = model;
-}
\ No newline at end of file
+}
diff --git a/src/Aspire.Hosting/api/Aspire.Hosting.Capabilities.txt b/src/Aspire.Hosting/api/Aspire.Hosting.Capabilities.txt
index eb49d9ba830..77a9db017e7 100644
--- a/src/Aspire.Hosting/api/Aspire.Hosting.Capabilities.txt
+++ b/src/Aspire.Hosting/api/Aspire.Hosting.Capabilities.txt
@@ -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]
@@ -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
@@ -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
diff --git a/src/Aspire.Hosting/api/Aspire.Hosting.ats.txt b/src/Aspire.Hosting/api/Aspire.Hosting.ats.txt
index c34f82e7916..8c93261e782 100644
--- a/src/Aspire.Hosting/api/Aspire.Hosting.ats.txt
+++ b/src/Aspire.Hosting/api/Aspire.Hosting.ats.txt
@@ -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]
@@ -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
@@ -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
@@ -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
diff --git a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go
index 31b8c31b4e8..6fa0d090064 100644
--- a/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go
+++ b/tests/Aspire.Hosting.CodeGeneration.Go.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.go
@@ -1,4 +1,4 @@
-// aspire.go - Capability-based Aspire SDK
+// aspire.go - Capability-based Aspire SDK
// This SDK uses the ATS (Aspire Type System) capability API.
// Capabilities are endpoints like 'Aspire.Hosting/createBuilder'.
//
@@ -835,6 +835,62 @@ type TestVaultResource interface {
// Handle wrappers
// ============================================================================
+// AfterPublishEvent is the public interface for handle type AfterPublishEvent.
+type AfterPublishEvent interface {
+ handleReference
+ Model() DistributedApplicationModel
+ Services() ServiceProvider
+ Err() error
+}
+
+// afterPublishEvent is the unexported impl of AfterPublishEvent.
+type afterPublishEvent struct {
+ *resourceBuilderBase
+}
+
+// newAfterPublishEventFromHandle wraps an existing handle as AfterPublishEvent.
+func newAfterPublishEventFromHandle(h *handle, c *client) AfterPublishEvent {
+ return &afterPublishEvent{resourceBuilderBase: newResourceBuilderBase(h, c)}
+}
+
+// Model gets the Model property
+func (s *afterPublishEvent) Model() DistributedApplicationModel {
+ if s.err != nil { return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting.Publishing/AfterPublishEvent.model", reqArgs)
+ if err != nil {
+ return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting.Publishing/AfterPublishEvent.model returned unexpected type %T", result)
+ return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationModel{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
+// Services gets the Services property
+func (s *afterPublishEvent) Services() ServiceProvider {
+ if s.err != nil { return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting.Publishing/AfterPublishEvent.services", reqArgs)
+ if err != nil {
+ return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting.Publishing/AfterPublishEvent.services returned unexpected type %T", result)
+ return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &serviceProvider{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// AfterResourcesCreatedEvent is the public interface for handle type AfterResourcesCreatedEvent.
type AfterResourcesCreatedEvent interface {
handleReference
@@ -2712,6 +2768,62 @@ func (s *aspire_Hosting_CodeGeneration_Go_TestsTestVaultResource) WithoutHttpsCe
return s
}
+// BeforePublishEvent is the public interface for handle type BeforePublishEvent.
+type BeforePublishEvent interface {
+ handleReference
+ Model() DistributedApplicationModel
+ Services() ServiceProvider
+ Err() error
+}
+
+// beforePublishEvent is the unexported impl of BeforePublishEvent.
+type beforePublishEvent struct {
+ *resourceBuilderBase
+}
+
+// newBeforePublishEventFromHandle wraps an existing handle as BeforePublishEvent.
+func newBeforePublishEventFromHandle(h *handle, c *client) BeforePublishEvent {
+ return &beforePublishEvent{resourceBuilderBase: newResourceBuilderBase(h, c)}
+}
+
+// Model gets the Model property
+func (s *beforePublishEvent) Model() DistributedApplicationModel {
+ if s.err != nil { return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting.Publishing/BeforePublishEvent.model", reqArgs)
+ if err != nil {
+ return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting.Publishing/BeforePublishEvent.model returned unexpected type %T", result)
+ return &distributedApplicationModel{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationModel{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
+// Services gets the Services property
+func (s *beforePublishEvent) Services() ServiceProvider {
+ if s.err != nil { return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting.Publishing/BeforePublishEvent.services", reqArgs)
+ if err != nil {
+ return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting.Publishing/BeforePublishEvent.services returned unexpected type %T", result)
+ return &serviceProvider{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &serviceProvider{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// BeforeResourceStartedEvent is the public interface for handle type BeforeResourceStartedEvent.
type BeforeResourceStartedEvent interface {
handleReference
@@ -7504,7 +7616,9 @@ type DistributedApplicationBuilder interface {
ExecutionContext() DistributedApplicationExecutionContext
GetConfiguration() Configuration
Pipeline() DistributedApplicationPipeline
+ SubscribeAfterPublish(callback func(arg AfterPublishEvent)) DistributedApplicationEventSubscription
SubscribeAfterResourcesCreated(callback func(arg AfterResourcesCreatedEvent)) DistributedApplicationEventSubscription
+ SubscribeBeforePublish(callback func(arg BeforePublishEvent)) DistributedApplicationEventSubscription
SubscribeBeforeStart(callback func(arg BeforeStartEvent)) DistributedApplicationEventSubscription
TryAddEventingSubscriber(subscribe func(arg EventingSubscriberRegistrationContext)) error
UserSecretsManager() UserSecretsManager
@@ -8061,6 +8175,33 @@ func (s *distributedApplicationBuilder) Pipeline() DistributedApplicationPipelin
return &distributedApplicationPipeline{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
}
+// SubscribeAfterPublish subscribes to the AfterPublish event
+func (s *distributedApplicationBuilder) SubscribeAfterPublish(callback func(arg AfterPublishEvent)) DistributedApplicationEventSubscription {
+ if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "builder": s.handle.ToJSON(),
+ }
+ if callback != nil {
+ cb := callback
+ shim := func(args ...any) any {
+ cb(callbackArg[AfterPublishEvent](args, 0))
+ return nil
+ }
+ reqArgs["callback"] = s.client.registerCallback(shim)
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting/subscribeAfterPublish", reqArgs)
+ if err != nil {
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting/subscribeAfterPublish returned unexpected type %T", result)
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// SubscribeAfterResourcesCreated subscribes to the AfterResourcesCreated event
func (s *distributedApplicationBuilder) SubscribeAfterResourcesCreated(callback func(arg AfterResourcesCreatedEvent)) DistributedApplicationEventSubscription {
if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
@@ -8088,6 +8229,33 @@ func (s *distributedApplicationBuilder) SubscribeAfterResourcesCreated(callback
return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
}
+// SubscribeBeforePublish subscribes to the BeforePublish event
+func (s *distributedApplicationBuilder) SubscribeBeforePublish(callback func(arg BeforePublishEvent)) DistributedApplicationEventSubscription {
+ if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "builder": s.handle.ToJSON(),
+ }
+ if callback != nil {
+ cb := callback
+ shim := func(args ...any) any {
+ cb(callbackArg[BeforePublishEvent](args, 0))
+ return nil
+ }
+ reqArgs["callback"] = s.client.registerCallback(shim)
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting/subscribeBeforePublish", reqArgs)
+ if err != nil {
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting/subscribeBeforePublish returned unexpected type %T", result)
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// SubscribeBeforeStart subscribes to the BeforeStart event
func (s *distributedApplicationBuilder) SubscribeBeforeStart(callback func(arg BeforeStartEvent)) DistributedApplicationEventSubscription {
if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
@@ -11311,7 +11479,9 @@ type EventingSubscriberRegistrationContext interface {
handleReference
CancellationToken() (*CancellationToken, error)
ExecutionContext() DistributedApplicationExecutionContext
+ OnAfterPublish(callback func(arg AfterPublishEvent)) DistributedApplicationEventSubscription
OnAfterResourcesCreated(callback func(arg AfterResourcesCreatedEvent)) DistributedApplicationEventSubscription
+ OnBeforePublish(callback func(arg BeforePublishEvent)) DistributedApplicationEventSubscription
OnBeforeStart(callback func(arg BeforeStartEvent)) DistributedApplicationEventSubscription
Err() error
}
@@ -11360,6 +11530,33 @@ func (s *eventingSubscriberRegistrationContext) ExecutionContext() DistributedAp
return &distributedApplicationExecutionContext{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
}
+// OnAfterPublish subscribes an eventing subscriber to the AfterPublish event
+func (s *eventingSubscriberRegistrationContext) OnAfterPublish(callback func(arg AfterPublishEvent)) DistributedApplicationEventSubscription {
+ if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ if callback != nil {
+ cb := callback
+ shim := func(args ...any) any {
+ cb(callbackArg[AfterPublishEvent](args, 0))
+ return nil
+ }
+ reqArgs["callback"] = s.client.registerCallback(shim)
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting/eventingSubscriberOnAfterPublish", reqArgs)
+ if err != nil {
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting/eventingSubscriberOnAfterPublish returned unexpected type %T", result)
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// OnAfterResourcesCreated subscribes an eventing subscriber to the AfterResourcesCreated event
func (s *eventingSubscriberRegistrationContext) OnAfterResourcesCreated(callback func(arg AfterResourcesCreatedEvent)) DistributedApplicationEventSubscription {
if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
@@ -11387,6 +11584,33 @@ func (s *eventingSubscriberRegistrationContext) OnAfterResourcesCreated(callback
return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
}
+// OnBeforePublish subscribes an eventing subscriber to the BeforePublish event
+func (s *eventingSubscriberRegistrationContext) OnBeforePublish(callback func(arg BeforePublishEvent)) DistributedApplicationEventSubscription {
+ if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
+ ctx := context.Background()
+ reqArgs := map[string]any{
+ "context": s.handle.ToJSON(),
+ }
+ if callback != nil {
+ cb := callback
+ shim := func(args ...any) any {
+ cb(callbackArg[BeforePublishEvent](args, 0))
+ return nil
+ }
+ reqArgs["callback"] = s.client.registerCallback(shim)
+ }
+ result, err := s.client.invokeCapability(ctx, "Aspire.Hosting/eventingSubscriberOnBeforePublish", reqArgs)
+ if err != nil {
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ href, ok := result.(handleReference)
+ if !ok {
+ err := fmt.Errorf("aspire: Aspire.Hosting/eventingSubscriberOnBeforePublish returned unexpected type %T", result)
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}
+ }
+ return &distributedApplicationEventSubscription{resourceBuilderBase: newResourceBuilderBase(href.getHandle(), s.client)}
+}
+
// OnBeforeStart subscribes an eventing subscriber to the BeforeStart event
func (s *eventingSubscriberRegistrationContext) OnBeforeStart(callback func(arg BeforeStartEvent)) DistributedApplicationEventSubscription {
if s.err != nil { return &distributedApplicationEventSubscription{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)} }
@@ -24234,6 +24458,9 @@ func registerWrappers(c *client) {
c.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression", func(h *handle, c *client) any {
return newHandleBackedReferenceExpression(h, c)
})
+ c.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent", func(h *handle, c *client) any {
+ return newAfterPublishEventFromHandle(h, c)
+ })
c.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.AfterResourcesCreatedEvent", func(h *handle, c *client) any {
return newAfterResourcesCreatedEventFromHandle(h, c)
})
@@ -24243,6 +24470,9 @@ func registerWrappers(c *client) {
c.registerHandleWrapper("Aspire.Hosting.CodeGeneration.Go.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.TestTypes.TestVaultResource", func(h *handle, c *client) any {
return newAspire_Hosting_CodeGeneration_Go_TestsTestVaultResourceFromHandle(h, c)
})
+ c.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent", func(h *handle, c *client) any {
+ return newBeforePublishEventFromHandle(h, c)
+ })
c.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeResourceStartedEvent", func(h *handle, c *client) any {
return newBeforeResourceStartedEventFromHandle(h, c)
})
diff --git a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java
index c56156fe1d2..fed0bc36264 100644
--- a/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java
+++ b/tests/Aspire.Hosting.CodeGeneration.Java.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.java
@@ -1,4 +1,4 @@
-// ===== AddContainerOptions.java =====
+// ===== AddContainerOptions.java =====
// AddContainerOptions.java - GENERATED CODE - DO NOT EDIT
package aspire;
@@ -139,6 +139,36 @@ public AddStepOptions requiredBy(String[] value) {
}
+// ===== AfterPublishEvent.java =====
+// AfterPublishEvent.java - GENERATED CODE - DO NOT EDIT
+
+package aspire;
+
+import java.util.*;
+import java.util.function.*;
+
+/** Wrapper for Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent. */
+public class AfterPublishEvent extends HandleWrapperBase {
+ AfterPublishEvent(Handle handle, AspireClient client) {
+ super(handle, client);
+ }
+
+ /** Gets the Services property */
+ public IServiceProvider services() {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ return (IServiceProvider) getClient().invokeCapability("Aspire.Hosting.Publishing/AfterPublishEvent.services", reqArgs);
+ }
+
+ /** Gets the Model property */
+ public DistributedApplicationModel model() {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ return (DistributedApplicationModel) getClient().invokeCapability("Aspire.Hosting.Publishing/AfterPublishEvent.model", reqArgs);
+ }
+
+}
+
// ===== AfterResourcesCreatedEvent.java =====
// AfterResourcesCreatedEvent.java - GENERATED CODE - DO NOT EDIT
@@ -1269,6 +1299,8 @@ public class AspireRegistrations {
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.InputsDialogValidationContext", (h, c) -> new InputsDialogValidationContext(h, c));
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions", (h, c) -> new ProjectResourceOptions(h, c));
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.IUserSecretsManager", (h, c) -> new IUserSecretsManager(h, c));
+ AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent", (h, c) -> new AfterPublishEvent(h, c));
+ AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent", (h, c) -> new BeforePublishEvent(h, c));
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineConfigurationContext", (h, c) -> new PipelineConfigurationContext(h, c));
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineContext", (h, c) -> new PipelineContext(h, c));
AspireClient.registerHandleWrapper("Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineEditor", (h, c) -> new PipelineEditor(h, c));
@@ -1407,6 +1439,36 @@ static void ensureRegistered() {
}
}
+// ===== BeforePublishEvent.java =====
+// BeforePublishEvent.java - GENERATED CODE - DO NOT EDIT
+
+package aspire;
+
+import java.util.*;
+import java.util.function.*;
+
+/** Wrapper for Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent. */
+public class BeforePublishEvent extends HandleWrapperBase {
+ BeforePublishEvent(Handle handle, AspireClient client) {
+ super(handle, client);
+ }
+
+ /** Gets the Services property */
+ public IServiceProvider services() {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ return (IServiceProvider) getClient().invokeCapability("Aspire.Hosting.Publishing/BeforePublishEvent.services", reqArgs);
+ }
+
+ /** Gets the Model property */
+ public DistributedApplicationModel model() {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ return (DistributedApplicationModel) getClient().invokeCapability("Aspire.Hosting.Publishing/BeforePublishEvent.model", reqArgs);
+ }
+
+}
+
// ===== BeforeResourceStartedEvent.java =====
// BeforeResourceStartedEvent.java - GENERATED CODE - DO NOT EDIT
@@ -8659,6 +8721,36 @@ public DistributedApplicationEventSubscription onBeforeStart(AspireAction1 callback) {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ var callbackId = getClient().registerCallback(args -> {
+ var arg = (BeforePublishEvent) args[0];
+ callback.invoke(arg);
+ return null;
+ });
+ if (callbackId != null) {
+ reqArgs.put("callback", callbackId);
+ }
+ return (DistributedApplicationEventSubscription) getClient().invokeCapability("Aspire.Hosting/eventingSubscriberOnBeforePublish", reqArgs);
+ }
+
+ /** Subscribes an eventing subscriber to the AfterPublish event */
+ public DistributedApplicationEventSubscription onAfterPublish(AspireAction1 callback) {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("context", AspireClient.serializeValue(getHandle()));
+ var callbackId = getClient().registerCallback(args -> {
+ var arg = (AfterPublishEvent) args[0];
+ callback.invoke(arg);
+ return null;
+ });
+ if (callbackId != null) {
+ reqArgs.put("callback", callbackId);
+ }
+ return (DistributedApplicationEventSubscription) getClient().invokeCapability("Aspire.Hosting/eventingSubscriberOnAfterPublish", reqArgs);
+ }
+
/** Subscribes an eventing subscriber to the AfterResourcesCreated event */
public DistributedApplicationEventSubscription onAfterResourcesCreated(AspireAction1 callback) {
Map reqArgs = new HashMap<>();
@@ -11776,6 +11868,36 @@ public DistributedApplicationEventSubscription subscribeBeforeStart(AspireAction
return (DistributedApplicationEventSubscription) getClient().invokeCapability("Aspire.Hosting/subscribeBeforeStart", reqArgs);
}
+ /** Subscribes to the BeforePublish event */
+ public DistributedApplicationEventSubscription subscribeBeforePublish(AspireAction1 callback) {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("builder", AspireClient.serializeValue(getHandle()));
+ var callbackId = getClient().registerCallback(args -> {
+ var arg = (BeforePublishEvent) args[0];
+ callback.invoke(arg);
+ return null;
+ });
+ if (callbackId != null) {
+ reqArgs.put("callback", callbackId);
+ }
+ return (DistributedApplicationEventSubscription) getClient().invokeCapability("Aspire.Hosting/subscribeBeforePublish", reqArgs);
+ }
+
+ /** Subscribes to the AfterPublish event */
+ public DistributedApplicationEventSubscription subscribeAfterPublish(AspireAction1 callback) {
+ Map reqArgs = new HashMap<>();
+ reqArgs.put("builder", AspireClient.serializeValue(getHandle()));
+ var callbackId = getClient().registerCallback(args -> {
+ var arg = (AfterPublishEvent) args[0];
+ callback.invoke(arg);
+ return null;
+ });
+ if (callbackId != null) {
+ reqArgs.put("callback", callbackId);
+ }
+ return (DistributedApplicationEventSubscription) getClient().invokeCapability("Aspire.Hosting/subscribeAfterPublish", reqArgs);
+ }
+
/** Subscribes to the AfterResourcesCreated event */
public DistributedApplicationEventSubscription subscribeAfterResourcesCreated(AspireAction1 callback) {
Map reqArgs = new HashMap<>();
@@ -23254,6 +23376,7 @@ public WithVolumeOptions isReadOnly(Boolean value) {
.modules/AddParameterOptions.java
.modules/AddParameterWithGeneratedValueOptions.java
.modules/AddStepOptions.java
+.modules/AfterPublishEvent.java
.modules/AfterResourcesCreatedEvent.java
.modules/Aspire.java
.modules/AspireAction0.java
@@ -23272,6 +23395,7 @@ public WithVolumeOptions isReadOnly(Boolean value) {
.modules/AspireRegistrations.java
.modules/AspireUnion.java
.modules/BaseRegistrations.java
+.modules/BeforePublishEvent.java
.modules/BeforeResourceStartedEvent.java
.modules/BeforeStartEvent.java
.modules/BuildOptions.java
diff --git a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py
index ff6649ed3c9..05031727da4 100644
--- a/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py
+++ b/tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py
@@ -1,4 +1,4 @@
-# -------------------------------------------------------------
+# -------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE in project root for information.
#
@@ -2329,6 +2329,26 @@ def subscribe_before_start(self, callback: typing.Callable[[BeforeStartEvent], N
)
return typing.cast(DistributedApplicationEventSubscription, result)
+ def subscribe_before_publish(self, callback: typing.Callable[[BeforePublishEvent], None]) -> DistributedApplicationEventSubscription:
+ """Subscribes to the BeforePublish event"""
+ rpc_args: dict[str, typing.Any] = {'builder': self._handle}
+ rpc_args['callback'] = self._client.register_callback(callback)
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting/subscribeBeforePublish',
+ rpc_args,
+ )
+ return typing.cast(DistributedApplicationEventSubscription, result)
+
+ def subscribe_after_publish(self, callback: typing.Callable[[AfterPublishEvent], None]) -> DistributedApplicationEventSubscription:
+ """Subscribes to the AfterPublish event"""
+ rpc_args: dict[str, typing.Any] = {'builder': self._handle}
+ rpc_args['callback'] = self._client.register_callback(callback)
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting/subscribeAfterPublish',
+ rpc_args,
+ )
+ return typing.cast(DistributedApplicationEventSubscription, result)
+
def subscribe_after_resources_created(self, callback: typing.Callable[[AfterResourcesCreatedEvent], None]) -> DistributedApplicationEventSubscription:
"""Subscribes to the AfterResourcesCreated event"""
rpc_args: dict[str, typing.Any] = {'builder': self._handle}
@@ -3035,6 +3055,40 @@ def get_or_set_secret(self, resource_builder: AbstractResource, name: str, value
)
+class AfterPublishEvent:
+ """Type class for AfterPublishEvent."""
+
+ def __init__(self, handle: Handle, client: AspireClient) -> None:
+ self._handle = handle
+ self._client = client
+
+ def __repr__(self) -> str:
+ return f"AfterPublishEvent(handle={self._handle.handle_id})"
+
+ @_uncached_property
+ def handle(self) -> Handle:
+ """The underlying object reference handle."""
+ return self._handle
+
+ @_cached_property
+ def services(self) -> AbstractServiceProvider:
+ """Gets the Services property"""
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting.Publishing/AfterPublishEvent.services',
+ {'context': self._handle}
+ )
+ return typing.cast(AbstractServiceProvider, result)
+
+ @_cached_property
+ def model(self) -> DistributedApplicationModel:
+ """Gets the Model property"""
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting.Publishing/AfterPublishEvent.model',
+ {'context': self._handle}
+ )
+ return typing.cast(DistributedApplicationModel, result)
+
+
class AfterResourcesCreatedEvent:
"""Type class for AfterResourcesCreatedEvent."""
@@ -3069,6 +3123,40 @@ def model(self) -> DistributedApplicationModel:
return typing.cast(DistributedApplicationModel, result)
+class BeforePublishEvent:
+ """Type class for BeforePublishEvent."""
+
+ def __init__(self, handle: Handle, client: AspireClient) -> None:
+ self._handle = handle
+ self._client = client
+
+ def __repr__(self) -> str:
+ return f"BeforePublishEvent(handle={self._handle.handle_id})"
+
+ @_uncached_property
+ def handle(self) -> Handle:
+ """The underlying object reference handle."""
+ return self._handle
+
+ @_cached_property
+ def services(self) -> AbstractServiceProvider:
+ """Gets the Services property"""
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting.Publishing/BeforePublishEvent.services',
+ {'context': self._handle}
+ )
+ return typing.cast(AbstractServiceProvider, result)
+
+ @_cached_property
+ def model(self) -> DistributedApplicationModel:
+ """Gets the Model property"""
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting.Publishing/BeforePublishEvent.model',
+ {'context': self._handle}
+ )
+ return typing.cast(DistributedApplicationModel, result)
+
+
class BeforeResourceStartedEvent:
"""Type class for BeforeResourceStartedEvent."""
@@ -4299,6 +4387,26 @@ def on_before_start(self, callback: typing.Callable[[BeforeStartEvent], None]) -
)
return typing.cast(DistributedApplicationEventSubscription, result)
+ def on_before_publish(self, callback: typing.Callable[[BeforePublishEvent], None]) -> DistributedApplicationEventSubscription:
+ """Subscribes an eventing subscriber to the BeforePublish event"""
+ rpc_args: dict[str, typing.Any] = {'context': self._handle}
+ rpc_args['callback'] = self._client.register_callback(callback)
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting/eventingSubscriberOnBeforePublish',
+ rpc_args,
+ )
+ return typing.cast(DistributedApplicationEventSubscription, result)
+
+ def on_after_publish(self, callback: typing.Callable[[AfterPublishEvent], None]) -> DistributedApplicationEventSubscription:
+ """Subscribes an eventing subscriber to the AfterPublish event"""
+ rpc_args: dict[str, typing.Any] = {'context': self._handle}
+ rpc_args['callback'] = self._client.register_callback(callback)
+ result = self._client.invoke_capability(
+ 'Aspire.Hosting/eventingSubscriberOnAfterPublish',
+ rpc_args,
+ )
+ return typing.cast(DistributedApplicationEventSubscription, result)
+
def on_after_resources_created(self, callback: typing.Callable[[AfterResourcesCreatedEvent], None]) -> DistributedApplicationEventSubscription:
"""Subscribes an eventing subscriber to the AfterResourcesCreated event"""
rpc_args: dict[str, typing.Any] = {'context': self._handle}
@@ -10691,7 +10799,9 @@ def create_builder(
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.Pipelines.IReportingTask", AbstractReportingTask)
_register_handle_wrapper("System.ComponentModel/System.IServiceProvider", AbstractServiceProvider)
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.IUserSecretsManager", AbstractUserSecretsManager)
+_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent", AfterPublishEvent)
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.AfterResourcesCreatedEvent", AfterResourcesCreatedEvent)
+_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent", BeforePublishEvent)
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeResourceStartedEvent", BeforeResourceStartedEvent)
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeStartEvent", BeforeStartEvent)
_register_handle_wrapper("Aspire.Hosting/Aspire.Hosting.ApplicationModel.CommandLineArgsCallbackContext", CommandLineArgsCallbackContext)
diff --git a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs
index 16c540685f0..1d84f5d5009 100644
--- a/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs
+++ b/tests/Aspire.Hosting.CodeGeneration.Rust.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.rs
@@ -1,4 +1,4 @@
-//! aspire.rs - Capability-based Aspire SDK
+//! aspire.rs - Capability-based Aspire SDK
//! GENERATED CODE - DO NOT EDIT
use std::collections::HashMap;
@@ -1305,6 +1305,50 @@ pub mod well_known_pipeline_tags {
// Handle Wrappers
// ============================================================================
+/// Wrapper for Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent
+pub struct AfterPublishEvent {
+ handle: Handle,
+ client: Arc,
+}
+
+impl HasHandle for AfterPublishEvent {
+ fn handle(&self) -> &Handle {
+ &self.handle
+ }
+}
+
+impl AfterPublishEvent {
+ pub fn new(handle: Handle, client: Arc) -> Self {
+ Self { handle, client }
+ }
+
+ pub fn handle(&self) -> &Handle {
+ &self.handle
+ }
+
+ pub fn client(&self) -> &Arc {
+ &self.client
+ }
+
+ /// Gets the Services property
+ pub fn services(&self) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let result = self.client.invoke_capability("Aspire.Hosting.Publishing/AfterPublishEvent.services", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(IServiceProvider::new(handle, self.client.clone()))
+ }
+
+ /// Gets the Model property
+ pub fn model(&self) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let result = self.client.invoke_capability("Aspire.Hosting.Publishing/AfterPublishEvent.model", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationModel::new(handle, self.client.clone()))
+ }
+}
+
/// Wrapper for Aspire.Hosting/Aspire.Hosting.ApplicationModel.AfterResourcesCreatedEvent
pub struct AfterResourcesCreatedEvent {
handle: Handle,
@@ -1349,6 +1393,50 @@ impl AfterResourcesCreatedEvent {
}
}
+/// Wrapper for Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent
+pub struct BeforePublishEvent {
+ handle: Handle,
+ client: Arc,
+}
+
+impl HasHandle for BeforePublishEvent {
+ fn handle(&self) -> &Handle {
+ &self.handle
+ }
+}
+
+impl BeforePublishEvent {
+ pub fn new(handle: Handle, client: Arc) -> Self {
+ Self { handle, client }
+ }
+
+ pub fn handle(&self) -> &Handle {
+ &self.handle
+ }
+
+ pub fn client(&self) -> &Arc {
+ &self.client
+ }
+
+ /// Gets the Services property
+ pub fn services(&self) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let result = self.client.invoke_capability("Aspire.Hosting.Publishing/BeforePublishEvent.services", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(IServiceProvider::new(handle, self.client.clone()))
+ }
+
+ /// Gets the Model property
+ pub fn model(&self) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let result = self.client.invoke_capability("Aspire.Hosting.Publishing/BeforePublishEvent.model", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationModel::new(handle, self.client.clone()))
+ }
+}
+
/// Wrapper for Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeResourceStartedEvent
pub struct BeforeResourceStartedEvent {
handle: Handle,
@@ -6939,6 +7027,28 @@ impl EventingSubscriberRegistrationContext {
Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
}
+ /// Subscribes an eventing subscriber to the BeforePublish event
+ pub fn on_before_publish(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let callback_id = register_callback(callback);
+ args.insert("callback".to_string(), Value::String(callback_id));
+ let result = self.client.invoke_capability("Aspire.Hosting/eventingSubscriberOnBeforePublish", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
+ }
+
+ /// Subscribes an eventing subscriber to the AfterPublish event
+ pub fn on_after_publish(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("context".to_string(), self.handle.to_json());
+ let callback_id = register_callback(callback);
+ args.insert("callback".to_string(), Value::String(callback_id));
+ let result = self.client.invoke_capability("Aspire.Hosting/eventingSubscriberOnAfterPublish", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
+ }
+
/// Subscribes an eventing subscriber to the AfterResourcesCreated event
pub fn on_after_resources_created(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
let mut args: HashMap = HashMap::new();
@@ -9174,6 +9284,28 @@ impl IDistributedApplicationBuilder {
Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
}
+ /// Subscribes to the BeforePublish event
+ pub fn subscribe_before_publish(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("builder".to_string(), self.handle.to_json());
+ let callback_id = register_callback(callback);
+ args.insert("callback".to_string(), Value::String(callback_id));
+ let result = self.client.invoke_capability("Aspire.Hosting/subscribeBeforePublish", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
+ }
+
+ /// Subscribes to the AfterPublish event
+ pub fn subscribe_after_publish(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
+ let mut args: HashMap = HashMap::new();
+ args.insert("builder".to_string(), self.handle.to_json());
+ let callback_id = register_callback(callback);
+ args.insert("callback".to_string(), Value::String(callback_id));
+ let result = self.client.invoke_capability("Aspire.Hosting/subscribeAfterPublish", args)?;
+ let handle: Handle = serde_json::from_value(result)?;
+ Ok(DistributedApplicationEventSubscription::new(handle, self.client.clone()))
+ }
+
/// Subscribes to the AfterResourcesCreated event
pub fn subscribe_after_resources_created(&self, callback: impl Fn(Vec) -> Value + Send + Sync + 'static) -> Result> {
let mut args: HashMap = HashMap::new();
diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs
index 70489a2ee54..438d964e373 100644
--- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs
+++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs
@@ -1188,6 +1188,10 @@ public void Generate_HostingAssembly_IncludesCoreFrameworkPolyglotHelpers()
Assert.Contains("getDistributedApplicationModel", aspireTs);
Assert.Contains("subscribeBeforeStart", aspireTs);
Assert.Contains("subscribeAfterResourcesCreated", aspireTs);
+ Assert.Contains("subscribeBeforePublish", aspireTs);
+ Assert.Contains("subscribeAfterPublish", aspireTs);
+ Assert.Contains("onBeforePublish", aspireTs);
+ Assert.Contains("onAfterPublish", aspireTs);
Assert.Contains("onBeforeResourceStarted", aspireTs);
Assert.Contains("onResourceStopped", aspireTs);
Assert.Contains("onConnectionStringAvailable", aspireTs);
diff --git a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts
index a05d67221a1..247ea229216 100644
--- a/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts
+++ b/tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts
@@ -428,6 +428,12 @@ type PipelineSummaryHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.Pip
/** Various properties to modify the behavior of the project resource. */
type ProjectResourceOptionsHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions'>;
+/** This event is published after the distributed application is published. */
+type AfterPublishEventHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent'>;
+
+/** This event is published before the distributed application is published. */
+type BeforePublishEventHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent'>;
+
/** Handle to IConfiguration */
type IConfigurationHandle = Handle<'Microsoft.Extensions.Configuration.Abstractions/Microsoft.Extensions.Configuration.IConfiguration'>;
@@ -1499,6 +1505,54 @@ export interface WithVolumeOptions {
isReadOnly?: boolean;
}
+// ============================================================================
+// AfterPublishEvent
+// ============================================================================
+
+/** This event is published after the distributed application is published. */
+export interface AfterPublishEvent {
+ toJSON(): MarshalledHandle;
+ /** The `IServiceProvider` for the app host. */
+ services(): ServiceProviderPromise;
+ /** The `DistributedApplicationModel` instance. */
+ model(): DistributedApplicationModelPromise;
+}
+
+// ============================================================================
+// AfterPublishEventImpl
+// ============================================================================
+
+/** This event is published after the distributed application is published. */
+class AfterPublishEventImpl implements AfterPublishEvent {
+ constructor(private _handle: AfterPublishEventHandle, private _client: AspireClientRpc) {}
+
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+
+ services(): ServiceProviderPromise {
+ const promise = (async () => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.Publishing/AfterPublishEvent.services',
+ { context: this._handle }
+ );
+ return new ServiceProviderImpl(handle, this._client);
+ })();
+ return new ServiceProviderPromiseImpl(promise, this._client, false);
+ }
+
+ model(): DistributedApplicationModelPromise {
+ const promise = (async () => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.Publishing/AfterPublishEvent.model',
+ { context: this._handle }
+ );
+ return new DistributedApplicationModelImpl(handle, this._client);
+ })();
+ return new DistributedApplicationModelPromiseImpl(promise, this._client, false);
+ }
+
+}
+
// ============================================================================
// AfterResourcesCreatedEvent
// ============================================================================
@@ -1561,6 +1615,54 @@ class AfterResourcesCreatedEventImpl implements AfterResourcesCreatedEvent {
}
+// ============================================================================
+// BeforePublishEvent
+// ============================================================================
+
+/** This event is published before the distributed application is published. */
+export interface BeforePublishEvent {
+ toJSON(): MarshalledHandle;
+ /** The `IServiceProvider` for the app host. */
+ services(): ServiceProviderPromise;
+ /** The `DistributedApplicationModel` instance. */
+ model(): DistributedApplicationModelPromise;
+}
+
+// ============================================================================
+// BeforePublishEventImpl
+// ============================================================================
+
+/** This event is published before the distributed application is published. */
+class BeforePublishEventImpl implements BeforePublishEvent {
+ constructor(private _handle: BeforePublishEventHandle, private _client: AspireClientRpc) {}
+
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+
+ services(): ServiceProviderPromise {
+ const promise = (async () => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.Publishing/BeforePublishEvent.services',
+ { context: this._handle }
+ );
+ return new ServiceProviderImpl(handle, this._client);
+ })();
+ return new ServiceProviderPromiseImpl(promise, this._client, false);
+ }
+
+ model(): DistributedApplicationModelPromise {
+ const promise = (async () => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.Publishing/BeforePublishEvent.model',
+ { context: this._handle }
+ );
+ return new DistributedApplicationModelImpl(handle, this._client);
+ })();
+ return new DistributedApplicationModelPromiseImpl(promise, this._client, false);
+ }
+
+}
+
// ============================================================================
// BeforeResourceStartedEvent
// ============================================================================
@@ -3835,6 +3937,18 @@ export interface EventingSubscriberRegistrationContext {
* @returns The event subscription.
*/
onBeforeStart(callback: (arg: BeforeStartEvent) => Promise): Promise;
+ /**
+ * Subscribes to the BeforePublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ onBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise;
+ /**
+ * Subscribes to the AfterPublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ onAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise;
/**
* Subscribes to the AfterResourcesCreated event from an eventing subscriber registration context.
* @param callback The callback to invoke when the event fires.
@@ -3854,6 +3968,18 @@ export interface EventingSubscriberRegistrationContextPromise extends PromiseLik
* @returns The event subscription.
*/
onBeforeStart(callback: (arg: BeforeStartEvent) => Promise): Promise;
+ /**
+ * Subscribes to the BeforePublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ onBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise;
+ /**
+ * Subscribes to the AfterPublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ onAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise;
/**
* Subscribes to the AfterResourcesCreated event from an eventing subscriber registration context.
* @param callback The callback to invoke when the event fires.
@@ -3907,6 +4033,42 @@ class EventingSubscriberRegistrationContextImpl implements EventingSubscriberReg
);
}
+ /**
+ * Subscribes to the BeforePublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ async onBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise {
+ const callbackId = registerCallback(async (argData: unknown) => {
+ const argHandle = wrapIfHandle(argData) as BeforePublishEventHandle;
+ const arg = new BeforePublishEventImpl(argHandle, this._client);
+ await callback(arg);
+ });
+ const rpcArgs: Record = { context: this._handle, callback: callbackId };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/eventingSubscriberOnBeforePublish',
+ rpcArgs
+ );
+ }
+
+ /**
+ * Subscribes to the AfterPublish event from an eventing subscriber registration context.
+ * @param callback The callback to invoke when the event fires.
+ * @returns The event subscription.
+ */
+ async onAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise {
+ const callbackId = registerCallback(async (argData: unknown) => {
+ const argHandle = wrapIfHandle(argData) as AfterPublishEventHandle;
+ const arg = new AfterPublishEventImpl(argHandle, this._client);
+ await callback(arg);
+ });
+ const rpcArgs: Record = { context: this._handle, callback: callbackId };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/eventingSubscriberOnAfterPublish',
+ rpcArgs
+ );
+ }
+
/**
* Subscribes to the AfterResourcesCreated event from an eventing subscriber registration context.
* @param callback The callback to invoke when the event fires.
@@ -3954,6 +4116,14 @@ class EventingSubscriberRegistrationContextPromiseImpl implements EventingSubscr
return this._promise.then(obj => obj.onBeforeStart(callback));
}
+ onBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise {
+ return this._promise.then(obj => obj.onBeforePublish(callback));
+ }
+
+ onAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise {
+ return this._promise.then(obj => obj.onAfterPublish(callback));
+ }
+
onAfterResourcesCreated(callback: (arg: AfterResourcesCreatedEvent) => Promise): Promise {
return this._promise.then(obj => obj.onAfterResourcesCreated(callback));
}
@@ -7154,6 +7324,24 @@ export interface DistributedApplicationBuilder {
* @returns A subscription handle that can be used to unsubscribe.
*/
subscribeBeforeStart(callback: (arg: BeforeStartEvent) => Promise): Promise;
+ /**
+ * Subscribes to the BeforePublish event, which fires before the application is published.
+ *
+ * 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.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ subscribeBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise;
+ /**
+ * Subscribes to the AfterPublish event, which fires after the application is published.
+ *
+ * This event provides access to the service provider and distributed application model,
+ * allowing you to inspect the model after publish pipeline steps complete.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ subscribeAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise;
/**
* Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
*
@@ -7373,6 +7561,24 @@ export interface DistributedApplicationBuilderPromise extends PromiseLike Promise): Promise;
+ /**
+ * Subscribes to the BeforePublish event, which fires before the application is published.
+ *
+ * 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.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ subscribeBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise;
+ /**
+ * Subscribes to the AfterPublish event, which fires after the application is published.
+ *
+ * This event provides access to the service provider and distributed application model,
+ * allowing you to inspect the model after publish pipeline steps complete.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ subscribeAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise;
/**
* Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
*
@@ -7882,6 +8088,48 @@ class DistributedApplicationBuilderImpl implements DistributedApplicationBuilder
);
}
+ /**
+ * Subscribes to the BeforePublish event, which fires before the application is published.
+ *
+ * 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.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ async subscribeBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise {
+ const callbackId = registerCallback(async (argData: unknown) => {
+ const argHandle = wrapIfHandle(argData) as BeforePublishEventHandle;
+ const arg = new BeforePublishEventImpl(argHandle, this._client);
+ await callback(arg);
+ });
+ const rpcArgs: Record = { builder: this._handle, callback: callbackId };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/subscribeBeforePublish',
+ rpcArgs
+ );
+ }
+
+ /**
+ * Subscribes to the AfterPublish event, which fires after the application is published.
+ *
+ * This event provides access to the service provider and distributed application model,
+ * allowing you to inspect the model after publish pipeline steps complete.
+ * @param callback A callback that receives the exported event when the event fires.
+ * @returns A subscription handle that can be used to unsubscribe.
+ */
+ async subscribeAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise {
+ const callbackId = registerCallback(async (argData: unknown) => {
+ const argHandle = wrapIfHandle(argData) as AfterPublishEventHandle;
+ const arg = new AfterPublishEventImpl(argHandle, this._client);
+ await callback(arg);
+ });
+ const rpcArgs: Record = { builder: this._handle, callback: callbackId };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/subscribeAfterPublish',
+ rpcArgs
+ );
+ }
+
/**
* Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
*
@@ -8091,6 +8339,14 @@ class DistributedApplicationBuilderPromiseImpl implements DistributedApplication
return this._promise.then(obj => obj.subscribeBeforeStart(callback));
}
+ subscribeBeforePublish(callback: (arg: BeforePublishEvent) => Promise): Promise {
+ return this._promise.then(obj => obj.subscribeBeforePublish(callback));
+ }
+
+ subscribeAfterPublish(callback: (arg: AfterPublishEvent) => Promise): Promise {
+ return this._promise.then(obj => obj.subscribeAfterPublish(callback));
+ }
+
subscribeAfterResourcesCreated(callback: (arg: AfterResourcesCreatedEvent) => Promise): Promise {
return this._promise.then(obj => obj.subscribeAfterResourcesCreated(callback));
}
@@ -53569,7 +53825,9 @@ process.on('uncaughtException', (error: Error) => {
// ============================================================================
// Register wrapper factories for typed handle wrapping in callbacks
+registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Publishing.AfterPublishEvent', (handle, client) => new AfterPublishEventImpl(handle as AfterPublishEventHandle, client));
registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.AfterResourcesCreatedEvent', (handle, client) => new AfterResourcesCreatedEventImpl(handle as AfterResourcesCreatedEventHandle, client));
+registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.Publishing.BeforePublishEvent', (handle, client) => new BeforePublishEventImpl(handle as BeforePublishEventHandle, client));
registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeResourceStartedEvent', (handle, client) => new BeforeResourceStartedEventImpl(handle as BeforeResourceStartedEventHandle, client));
registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.BeforeStartEvent', (handle, client) => new BeforeStartEventImpl(handle as BeforeStartEventHandle, client));
registerHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.CommandLineArgsCallbackContext', (handle, client) => new CommandLineArgsCallbackContextImpl(handle as CommandLineArgsCallbackContextHandle, client));
diff --git a/tests/PolyglotAppHosts/Aspire.Hosting/Go/apphost.go b/tests/PolyglotAppHosts/Aspire.Hosting/Go/apphost.go
index 2856ddfb70a..f2ab6901f28 100644
--- a/tests/PolyglotAppHosts/Aspire.Hosting/Go/apphost.go
+++ b/tests/PolyglotAppHosts/Aspire.Hosting/Go/apphost.go
@@ -377,6 +377,26 @@ func main() {
_ = beforeStartServices.GetDistributedApplicationModel()
})
+ beforePublishSub := builder.SubscribeBeforePublish(func(e aspire.BeforePublishEvent) {
+ beforePublishModel := e.Model()
+ _, _ = beforePublishModel.GetResources()
+ _ = beforePublishModel.FindResourceByName("mycontainer")
+ beforePublishServices := e.Services()
+ beforePublishLoggerFactory := beforePublishServices.GetLoggerFactory()
+ beforePublishLogger := beforePublishLoggerFactory.CreateLogger("ValidationAppHost.BeforePublish")
+ _ = beforePublishLogger.LogInformation("BeforePublish")
+ })
+
+ afterPublishSub := builder.SubscribeAfterPublish(func(e aspire.AfterPublishEvent) {
+ afterPublishModel := e.Model()
+ _, _ = afterPublishModel.GetResources()
+ _ = afterPublishModel.FindResourceByName("mycontainer")
+ afterPublishServices := e.Services()
+ afterPublishLoggerFactory := afterPublishServices.GetLoggerFactory()
+ afterPublishLogger := afterPublishLoggerFactory.CreateLogger("ValidationAppHost.AfterPublish")
+ _ = afterPublishLogger.LogInformation("AfterPublish")
+ })
+
afterResourcesSub := builder.SubscribeAfterResourcesCreated(func(e aspire.AfterResourcesCreatedEvent) {
afterResourcesModel := e.Model()
_, _ = afterResourcesModel.GetResources()
@@ -390,6 +410,8 @@ func main() {
builderEventing := builder.Eventing()
_ = builderEventing.Unsubscribe(beforeStartSub)
_ = builderEventing.Unsubscribe(afterResourcesSub)
+ _ = builderEventing.Unsubscribe(beforePublishSub)
+ _ = builderEventing.Unsubscribe(afterPublishSub)
// Resource events — typed callbacks
_ = container.OnBeforeResourceStarted(func(e aspire.BeforeResourceStartedEvent) {
diff --git a/tests/PolyglotAppHosts/Aspire.Hosting/Java/AppHost.java b/tests/PolyglotAppHosts/Aspire.Hosting/Java/AppHost.java
index b43dee03246..7f2c639fc8d 100644
--- a/tests/PolyglotAppHosts/Aspire.Hosting/Java/AppHost.java
+++ b/tests/PolyglotAppHosts/Aspire.Hosting/Java/AppHost.java
@@ -129,6 +129,18 @@ void main() throws Exception {
var aspireStore = subscriberServices.getAspireStore();
var _contentBackedFilename = aspireStore.getFileNameWithContent("validation-apphost.java", "AppHost.java");
});
+ registrationContext.onBeforePublish((beforePublishEvent) -> {
+ var beforePublishServices = beforePublishEvent.services();
+ var beforePublishModel = beforePublishEvent.model();
+ var _beforePublishEventing = beforePublishServices.getEventing();
+ var _beforePublishResources = beforePublishModel.getResources();
+ });
+ registrationContext.onAfterPublish((afterPublishEvent) -> {
+ var afterPublishServices = afterPublishEvent.services();
+ var afterPublishModel = afterPublishEvent.model();
+ var _afterPublishEventing = afterPublishServices.getEventing();
+ var _afterPublishResources = afterPublishModel.getResources();
+ });
registrationContext.onAfterResourcesCreated((afterResourcesCreatedEvent) -> {
var afterResourcesCreatedServices = afterResourcesCreatedEvent.services();
var afterResourcesCreatedModel = afterResourcesCreatedEvent.model();
@@ -164,9 +176,13 @@ void main() throws Exception {
var _httpsCertificateData = executionConfiguration.getHttpsCertificateData();
var beforeStartSubscription = builder.subscribeBeforeStart((beforeStartEvent) -> { var beforeStartServices = beforeStartEvent.services(); var beforeStartModel = beforeStartEvent.model(); var _beforeStartResources = beforeStartModel.getResources(); var _beforeStartContainer = beforeStartModel.findResourceByName("mycontainer"); var _beforeStartEventing = beforeStartServices.getEventing(); var beforeStartLoggerFactory = beforeStartServices.getLoggerFactory(); var beforeStartLogger = beforeStartLoggerFactory.createLogger("ValidationAppHost.BeforeStart"); beforeStartLogger.logInformation("BeforeStart information"); beforeStartLogger.logWarning("BeforeStart warning"); beforeStartLogger.logError("BeforeStart error"); beforeStartLogger.logDebug("BeforeStart debug"); beforeStartLogger.log("critical", "BeforeStart critical"); var beforeStartResourceLoggerService = beforeStartServices.getResourceLoggerService(); beforeStartResourceLoggerService.completeLog(container); beforeStartResourceLoggerService.completeLogByName("mycontainer"); var beforeStartNotificationService = beforeStartServices.getResourceNotificationService(); beforeStartNotificationService.waitForResourceState("mycontainer", "Running"); var _matchedResourceState = beforeStartNotificationService.waitForResourceStates("mycontainer", new String[] { "Running", "FailedToStart" }); var _healthyResourceEvent = beforeStartNotificationService.waitForResourceHealthy("mycontainer"); beforeStartNotificationService.waitForDependencies(container); var _currentResourceState = beforeStartNotificationService.tryGetResourceState("mycontainer"); beforeStartNotificationService.publishResourceUpdate(container, new PublishResourceUpdateOptions().state("Validated").stateStyle("info")); var userSecretsManager = beforeStartServices.getUserSecretsManager(); var _userSecretsAvailable = userSecretsManager.isAvailable(); var _userSecretsFilePath = userSecretsManager.filePath(); var _secretSet = userSecretsManager.trySetSecret("Validation:Key", "value"); userSecretsManager.getOrSetSecret(container, "Validation:GeneratedKey", "generated-value"); var _generatedSecretValue = builderConfiguration.getConfigValue("Validation:GeneratedKey"); userSecretsManager.saveStateJson("{\"Validation\":\"Value\"}"); var _modelFromServices = beforeStartServices.getDistributedApplicationModel(); });
var afterResourcesCreatedSubscription = builder.subscribeAfterResourcesCreated((afterResourcesCreatedEvent) -> { var afterResourcesCreatedServices = afterResourcesCreatedEvent.services(); var afterResourcesCreatedModel = afterResourcesCreatedEvent.model(); var _afterResources = afterResourcesCreatedModel.getResources(); var _afterResourcesContainer = afterResourcesCreatedModel.findResourceByName("mycontainer"); var afterResourcesCreatedLoggerFactory = afterResourcesCreatedServices.getLoggerFactory(); var afterResourcesCreatedLogger = afterResourcesCreatedLoggerFactory.createLogger("ValidationAppHost.AfterResourcesCreated"); afterResourcesCreatedLogger.logInformation("AfterResourcesCreated"); });
+ var beforePublishSubscription = builder.subscribeBeforePublish((beforePublishEvent) -> { var beforePublishServices = beforePublishEvent.services(); var beforePublishModel = beforePublishEvent.model(); var _beforePublishResources = beforePublishModel.getResources(); var _beforePublishContainer = beforePublishModel.findResourceByName("mycontainer"); var beforePublishLoggerFactory = beforePublishServices.getLoggerFactory(); var beforePublishLogger = beforePublishLoggerFactory.createLogger("ValidationAppHost.BeforePublish"); beforePublishLogger.logInformation("BeforePublish"); });
+ var afterPublishSubscription = builder.subscribeAfterPublish((afterPublishEvent) -> { var afterPublishServices = afterPublishEvent.services(); var afterPublishModel = afterPublishEvent.model(); var _afterPublishResources = afterPublishModel.getResources(); var _afterPublishContainer = afterPublishModel.findResourceByName("mycontainer"); var afterPublishLoggerFactory = afterPublishServices.getLoggerFactory(); var afterPublishLogger = afterPublishLoggerFactory.createLogger("ValidationAppHost.AfterPublish"); afterPublishLogger.logInformation("AfterPublish"); });
var builderEventing = builder.eventing();
builderEventing.unsubscribe(beforeStartSubscription);
builderEventing.unsubscribe(afterResourcesCreatedSubscription);
+ builderEventing.unsubscribe(beforePublishSubscription);
+ builderEventing.unsubscribe(afterPublishSubscription);
container.onBeforeResourceStarted((beforeResourceStartedEvent) -> { var _resource = beforeResourceStartedEvent.resource(); var services = beforeResourceStartedEvent.services(); var loggerFactory = services.getLoggerFactory(); var logger = loggerFactory.createLogger("ValidationAppHost.BeforeResourceStarted"); logger.logInformation("BeforeResourceStarted"); });
container.onResourceStopped((resourceStoppedEvent) -> { var _resource = resourceStoppedEvent.resource(); var services = resourceStoppedEvent.services(); var loggerFactory = services.getLoggerFactory(); var logger = loggerFactory.createLogger("ValidationAppHost.ResourceStopped"); logger.logWarning("ResourceStopped"); });
cache.onConnectionStringAvailable((connectionStringAvailableEvent) -> { var _resource = connectionStringAvailableEvent.resource(); var services = connectionStringAvailableEvent.services(); var notifications = services.getResourceNotificationService(); var _connectionState = notifications.tryGetResourceState("cache"); });
diff --git a/tests/PolyglotAppHosts/Aspire.Hosting/Python/apphost.py b/tests/PolyglotAppHosts/Aspire.Hosting/Python/apphost.py
index 099cdec51d8..a25a5aec3e2 100644
--- a/tests/PolyglotAppHosts/Aspire.Hosting/Python/apphost.py
+++ b/tests/PolyglotAppHosts/Aspire.Hosting/Python/apphost.py
@@ -276,6 +276,18 @@ def on_eventing_before_start(before_start_event):
aspire_store = subscriber_services.get_aspire_store()
_content_backed_filename = aspire_store.get_file_name_with_content("validation-apphost.py", "apphost.py")
+ def on_eventing_before_publish(before_publish_event):
+ before_publish_services = before_publish_event.services
+ before_publish_model = before_publish_event.model
+ _before_publish_eventing = before_publish_services.get_eventing()
+ _before_publish_resources = before_publish_model.get_resources()
+
+ def on_eventing_after_publish(after_publish_event):
+ after_publish_services = after_publish_event.services
+ after_publish_model = after_publish_event.model
+ _after_publish_eventing = after_publish_services.get_eventing()
+ _after_publish_resources = after_publish_model.get_resources()
+
def on_eventing_after_resources_created(after_resources_created_event):
after_resources_created_services = after_resources_created_event.services
after_resources_created_model = after_resources_created_event.model
@@ -283,6 +295,8 @@ def on_eventing_after_resources_created(after_resources_created_event):
_after_resources_created_resources = after_resources_created_model.get_resources()
registration_context.on_before_start(on_eventing_before_start)
+ registration_context.on_before_publish(on_eventing_before_publish)
+ registration_context.on_after_publish(on_eventing_after_publish)
registration_context.on_after_resources_created(on_eventing_after_resources_created)
builder.add_eventing_subscriber(configure_eventing_subscriber)
@@ -318,9 +332,13 @@ def configure_https_certificate(certificate_info):
_https_certificate_data = execution_config.get_https_certificate_data()
before_start_subscription = builder.subscribe_before_start(lambda *_args, **_kwargs: None)
after_resources_created_subscription = builder.subscribe_after_resources_created(lambda *_args, **_kwargs: None)
+ before_publish_subscription = builder.subscribe_before_publish(lambda *_args, **_kwargs: None)
+ after_publish_subscription = builder.subscribe_after_publish(lambda *_args, **_kwargs: None)
builder_eventing = builder.eventing
- builder_eventing.unsubscribe(None)
- builder_eventing.unsubscribe(None)
+ builder_eventing.unsubscribe(before_start_subscription)
+ builder_eventing.unsubscribe(after_resources_created_subscription)
+ builder_eventing.unsubscribe(before_publish_subscription)
+ builder_eventing.unsubscribe(after_publish_subscription)
container.on_before_resource_started(lambda *_args, **_kwargs: None)
container.on_resource_stopped(lambda *_args, **_kwargs: None)
built_connection_string.on_connection_string_available(lambda *_args, **_kwargs: None)
diff --git a/tests/PolyglotAppHosts/Aspire.Hosting/TypeScript/apphost.ts b/tests/PolyglotAppHosts/Aspire.Hosting/TypeScript/apphost.ts
index c8b6e255fd1..2d372764a46 100644
--- a/tests/PolyglotAppHosts/Aspire.Hosting/TypeScript/apphost.ts
+++ b/tests/PolyglotAppHosts/Aspire.Hosting/TypeScript/apphost.ts
@@ -423,6 +423,20 @@ await builder.addEventingSubscriber(async (registrationContext) => {
const _contentBackedFilename = await aspireStore.getFileNameWithContent("validation-apphost.ts", "apphost.ts");
});
+ await registrationContext.onBeforePublish(async (beforePublishEvent) => {
+ const beforePublishServices = await beforePublishEvent.services();
+ const beforePublishModel = await beforePublishEvent.model();
+ const _beforePublishEventing = await beforePublishServices.getEventing();
+ const _beforePublishResources = await beforePublishModel.getResources();
+ });
+
+ await registrationContext.onAfterPublish(async (afterPublishEvent) => {
+ const afterPublishServices = await afterPublishEvent.services();
+ const afterPublishModel = await afterPublishEvent.model();
+ const _afterPublishEventing = await afterPublishServices.getEventing();
+ const _afterPublishResources = await afterPublishModel.getResources();
+ });
+
await registrationContext.onAfterResourcesCreated(async (afterResourcesCreatedEvent) => {
const afterResourcesCreatedServices = await afterResourcesCreatedEvent.services();
const afterResourcesCreatedModel = await afterResourcesCreatedEvent.model();
@@ -512,9 +526,31 @@ const afterResourcesCreatedSubscription = await builder.subscribeAfterResourcesC
await afterResourcesCreatedLogger.logInformation("AfterResourcesCreated");
});
+const beforePublishSubscription = await builder.subscribeBeforePublish(async (beforePublishEvent) => {
+ const beforePublishServices = await beforePublishEvent.services();
+ const beforePublishModel = await beforePublishEvent.model();
+ const _beforePublishResources = await beforePublishModel.getResources();
+ const _beforePublishContainer = await beforePublishModel.findResourceByName("mycontainer");
+ const beforePublishLoggerFactory = await beforePublishServices.getLoggerFactory();
+ const beforePublishLogger = await beforePublishLoggerFactory.createLogger("ValidationAppHost.BeforePublish");
+ await beforePublishLogger.logInformation("BeforePublish");
+});
+
+const afterPublishSubscription = await builder.subscribeAfterPublish(async (afterPublishEvent) => {
+ const afterPublishServices = await afterPublishEvent.services();
+ const afterPublishModel = await afterPublishEvent.model();
+ const _afterPublishResources = await afterPublishModel.getResources();
+ const _afterPublishContainer = await afterPublishModel.findResourceByName("mycontainer");
+ const afterPublishLoggerFactory = await afterPublishServices.getLoggerFactory();
+ const afterPublishLogger = await afterPublishLoggerFactory.createLogger("ValidationAppHost.AfterPublish");
+ await afterPublishLogger.logInformation("AfterPublish");
+});
+
const builderEventing = await builder.eventing();
await builderEventing.unsubscribe(beforeStartSubscription);
await builderEventing.unsubscribe(afterResourcesCreatedSubscription);
+await builderEventing.unsubscribe(beforePublishSubscription);
+await builderEventing.unsubscribe(afterPublishSubscription);
await container.onBeforeResourceStarted(async (beforeResourceStartedEvent) => {
const _resource = await beforeResourceStartedEvent.resource();
diff --git a/tests/Shared/Hex1bAutomatorTestHelpers.cs b/tests/Shared/Hex1bAutomatorTestHelpers.cs
index 4c7c69b77ef..0a94ffeeaf4 100644
--- a/tests/Shared/Hex1bAutomatorTestHelpers.cs
+++ b/tests/Shared/Hex1bAutomatorTestHelpers.cs
@@ -618,10 +618,12 @@ await auto.WaitUntilAsync(
description: "output path prompt");
await auto.EnterAsync();
- // Step 5: URLs prompt (all templates have this)
+ // Step 5: URLs prompt (all templates have this). The CLI may spend time
+ // resolving template versions after the output path is entered, so reuse
+ // the template-selection timeout for this first post-resolution prompt.
await auto.WaitUntilAsync(
s => new CellPatternSearcher().Find("Use *.dev.localhost URLs").Search(s).Count > 0,
- timeout: TimeSpan.FromSeconds(10),
+ timeout: templateTimeout,
description: "URLs prompt");
await auto.EnterAsync(); // Accept default "No"