.env is sorted alphabetically, leading to environment placeholders breaking
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
Not sure if this is already resolved by #12656. 13.0 sorts the .env file alphabetically which destroys cross references made using `AsEnvironmentPlaceholder` in `PublishAsDockerComposeService`. With 9.5, the order is preserved and existing .env variables on top were kept. This is related to #12009 which now broke.
I use it to ensure the docker compose create the image in the form of `image: "${ABC_DOCKER_REPOSITORY}:${ABC_IMAGE_TAG:-2.12.44}"`.
```cs
var interfaceDockerRepositoryParam = builder.AddParameter("interface-docker-repository", "${DOCKER_REGISTRY_HOSTNAME}/myPrefix/", true)
...
// Workaround since resource.AddEnvironmentVariable is not accessible...
static ParameterResource GetUntrackedParameter(string name, string value)
{
return new ParameterResource(name, _ => value)
{
// This is necessary, as https://github.com/dotnet/aspire/blob/88da0b94e248d131a8b333bebd4c98031ef35f7f/src/Aspire.Hosting.Docker/DockerComposePublishingContext.cs#L184
// checks for Default to be set, which makes no sense...
// Default is only meant to allow the value to be added to the manifest. The GetValueAsync would work either way...
Default = new GenerateParameterDefault()
};
}
...
var repositoryName = $"{interfaceDockerRepositoryParam.AsEnvironmentPlaceholder(resource)}{resource.Name}";
var resourceDockerRepoParam = GetUntrackedParameter(resource.Name + "-docker-repository", repositoryName);
var resourceImageTagParam = GetUntrackedParameter(resource.Name + "-image-tag", string.Empty);
// Get environment names:
var resourceDockerRepoEnvName = resourceDockerRepoParam.AsEnvironmentPlaceholder(resource)[2..^1];
var resourceImageTagEnvName = resourceImageTagParam.AsEnvironmentPlaceholder(resource)[2..^1];
service.Image = $"${{{resourceDockerRepoEnvName}}}:${{{resourceImageTagEnvName}:-{fallbackVersion}}}";
```
If the `resource.Name` is alphabetically after `INTERFACE_DOCKER_REPOSITORY`, the reference will work. If not, the reference can't be resolved on startup...
In the past, this was created as
```
INTERFACE_DOCKER_REPOSITORY=${DOCKER_REGISTRY_HOSTNAME}/myPrefix/
ABC_DOCKER_REPOSITORY=${INTERFACE_DOCKER_REPOSITORY}/abc
ABC_IMAGE_TAG=
```
now it is created as
```
ABC_DOCKER_REPOSITORY=${INTERFACE_DOCKER_REPOSITORY}/abc
ABC_IMAGE_TAG=
INTERFACE_DOCKER_REPOSITORY=${DOCKER_REGISTRY_HOSTNAME}/myPrefix/
```
with INTERFACE_DOCKER_REPOSITORY failing to resolve.
### Expected Behavior
The .env file is created as until 9.5 with existing user variables being kept and order working in regards to the placeholders.
### Steps To Reproduce
1. Create a prameter as described above
2. Use it in PublishAsDockerComposeService as placeholder
3. Run `aspire do prepare-compose`
4. Start the docker-compose
### Exceptions (if any)
WARN[0000] The "INTERFACE_DOCKER_REPOSITORY" variable is not set. Defaulting to a blank string.
### .NET Version info
.NET SDK:
Version: 10.0.100
Commit: b0f34d51fc
Workload version: 10.0.100.1
MSBuild version: 18.0.2+b0f34d51f
Runtime Environment:
OS Name: Mac OS X
OS Version: 26.1
OS Platform: Darwin
RID: osx-arm64
Base Path: /usr/local/share/dotnet/sdk/10.0.100/
.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
Host:
Version: 10.0.0
Architecture: arm64
Commit: b0f34d51fc
.NET SDKs installed:
9.0.307 [/usr/local/share/dotnet/sdk]
9.0.308 [/usr/local/share/dotnet/sdk]
10.0.100 [/usr/local/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.11 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.11 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
DOTNET_INSTALL_DIR [/usr/local/share/dotnet/]
global.json file:
/Users//GitRepos//global.json
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
### Anything else?
ASP.NET Core: 10.0.100
.NET Aspire: 10.0.0
IDE: Rider
Contributor guide
Assessment
This issue has not been assessed yet.