Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 8 additions & 3 deletions src/Aspire.Hosting.NodeJs/NodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,14 @@ public static IResourceBuilder<ViteAppResource> AddViteApp(this IDistributedAppl
});

// since Vite apps are typically served via a separate web server, we don't have an entrypoint
var dockerFileAnnotation = resource.Annotations.OfType<DockerfileBuildAnnotation>().LastOrDefault()
?? throw new InvalidOperationException("DockerfileBuildAnnotation should exist after calling PublishAsDockerFile.");
dockerFileAnnotation.HasEntrypoint = false;
if (resource.TryGetLastAnnotation<DockerfileBuildAnnotation>(out var dockerFileAnnotation))
{
dockerFileAnnotation.HasEntrypoint = false;
}
else
{
throw new InvalidOperationException("DockerfileBuildAnnotation should exist after calling PublishAsDockerFile.");
}
})
.WithAnnotation(new ContainerFilesSourceAnnotation() { SourcePath = "/app/dist" });
}
Expand Down
12 changes: 5 additions & 7 deletions src/Aspire.Hosting.Python/PythonAppResourceBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -601,18 +601,16 @@ private static DockerfileStage AddStaticFiles(this DockerfileStage stage, IResou
throw new InvalidOperationException("Cannot add container files: Source resource does not have a container image name.");
}

// get the source path
if (!containerFileDestination.Source.TryGetLastAnnotation<ContainerFilesSourceAnnotation>(out var containerFilesSource))
{
throw new InvalidOperationException("Cannot add container files: Source resource does not have a ContainerFilesSourceAnnotation.");
}

var destinationPath = containerFileDestination.DestinationPath;
if (!destinationPath.StartsWith('/'))
{
destinationPath = $"{rootDestinationPath}/{destinationPath}";
}
stage.CopyFrom(imageName, containerFilesSource.SourcePath, destinationPath);

foreach (var containerFilesSource in containerFileDestination.Source.Annotations.OfType<ContainerFilesSourceAnnotation>())
{
stage.CopyFrom(imageName, containerFilesSource.SourcePath, destinationPath);
}
}

stage.EmptyLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public static IEnumerable<IResource> GetComputeResources(this DistributedApplica
continue;
}

if (r.IsBuildOnlyContainer())
{
continue;
}
Comment on lines +31 to +34
Copy link
Member

Choose a reason for hiding this comment

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

This feels like it's in the wrong place or this method has the wrong name.

Copy link
Member Author

Choose a reason for hiding this comment

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

In my opinion it isn't. A "build only container" (i.e. one that doesn't have an entrypoint) isn't a "Compute Resource". It can't stand alone. It doesn't have an entrypoint.


yield return r;
}
}
Expand Down
39 changes: 39 additions & 0 deletions tests/Aspire.Hosting.Azure.Tests/AzureContainerAppsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma warning disable ASPIREACADOMAINS001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable ASPIRECOMPUTE001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable ASPIREAZURE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable ASPIREDOCKERFILEBUILDER001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

using System.Text.Json.Nodes;
using Aspire.Hosting.ApplicationModel;
Expand Down Expand Up @@ -1954,6 +1955,44 @@ await Verify(containerBicep, "bicep")
.AppendContentAsFile(projectBicep, "bicep");
}

[Fact]
public async Task BuildOnlyContainerResource_DoesNotGetDeployed()
{
var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);

builder.AddAzureContainerAppEnvironment("env");

// Add a normal container resource
builder.AddContainer("api", "myimage");

// Add a build-only container resource
builder.AddExecutable("build-only", "exe", ".")
.PublishAsDockerFile(c =>
{
c.WithDockerfileBuilder(".", dockerfileContext =>
{
var dockerBuilder = dockerfileContext.Builder
.From("scratch");
});

var dockerFileAnnotation = c.Resource.Annotations.OfType<DockerfileBuildAnnotation>().Single();
dockerFileAnnotation.HasEntrypoint = false;
});

using var app = builder.Build();

await ExecuteBeforeStartHooksAsync(app, default);

var model = app.Services.GetRequiredService<DistributedApplicationModel>();

var container = model.Resources.Single(r => r.Name == "api");
var containerProvisioningResource = container.GetDeploymentTargetAnnotation()?.DeploymentTarget as AzureProvisioningResource;
Assert.NotNull(containerProvisioningResource);

var buildOnly = model.Resources.Single(r => r.Name == "build-only");
Assert.Null(buildOnly.GetDeploymentTargetAnnotation());
}

[Fact]
public async Task BindMountNamesWithHyphensAreNormalized()
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public async Task DeployAsync_WithBuildOnlyContainers()

var containerAppEnv = builder.AddAzureContainerAppEnvironment("env");

// Add a compute resource with its own build step
// Add a build-only container resource
builder.AddExecutable("exe", "exe", ".")
.PublishAsDockerFile(c =>
{
Expand Down