Output from azd version
azd version 1.25.0 (commit 208a5186a1c601e89ae8e37f9ef7b4e7037e4fc3) (stable)
Describe the bug
In azd 1.25.0+, azd deploy (and azd up) runs dotnet publish for all services in parallel during the Packaging/Publishing phase. Per the release blog post, this is by design: "Packaging and publishing always run in parallel regardless of uses — it's only the deploy step that gates on these edges."
This breaks .NET Aspire projects where multiple services share a common class library via <ProjectReference>. Each parallel dotnet publish invocation walks into the shared project and tries to write to the same obj/Release/<tfm>/<SharedLib>.dll, producing an MSB4018 / System.IO.IOException: The process cannot access the file ... because it is being used by another process.
There is no opt-out: uses only controls the deploy step, not packaging/publishing, so users cannot avoid this race even when they know about the shared reference.
To Reproduce
- Create an Aspire app host with 2+ services (e.g. a web API, a web app, and a migration console) where two or more reference a shared class library project, e.g.
MyApp.Common.Contracts.csproj.
- Use azd 1.25.x.
- Run
azd deploy (or azd up).
- Observe parallel packaging kick off
dotnet publish on each service simultaneously, racing on the shared project's obj/Release/<tfm>/*.dll.
Trimmed pipeline log:
redis: Packaging
myapp-apps-webapi: Packaging
myapp-apps-webapp: Packaging
redis: Publishing
myapp-apps-webapp: Publishing
myapp-apps-webapi: Publishing
myapp-migrationconsole: Packaging
myapp-migrationconsole: Publishing
...
myapp-migrationconsole: Failed (step "deploy-myapp-migrationconsole" failed: deploying service myapp-migrationconsole: failed deploying service 'myapp-migrationconsole': publishing container: dotnet publish on project '/azp/_work/1/s/src/MyApp.MigrationConsole/MyApp.MigrationConsole.csproj' failed: exit code: 1, stdout:
, stderr: /azp/_work/_tool/dotnet/sdk/10.0.300/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.targets(1200,5): error MSB4018: The "GetAssemblyAttributes" task failed unexpectedly. [/azp/_work/1/s/src/MyApp.Common.Contracts/MyApp.Common.Contracts.csproj]
/azp/_work/_tool/dotnet/sdk/10.0.300/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.Sdk.targets(1200,5): error MSB4018: System.IO.IOException: The process cannot access the file '/azp/_work/1/s/src/MyApp.Common.Contracts/obj/Release/net10.0/MyApp.Common.Contracts.dll' because it is being used by another process. [/azp/_work/1/s/src/MyApp.Common.Contracts/MyApp.Common.Contracts.csproj]
The failure is non-deterministic — which service "wins" and which fails varies between runs. On azd 1.24 and earlier, the same project deploys cleanly because publish steps were serialized.
Expected behavior
Either:
dotnet publish invocations for projects that share <ProjectReference> ancestors should be serialized (azd could detect overlapping project graphs during the analyze step), or
- The
uses field (or a new field) should gate the packaging/publishing phase as well, not only deploy, so users can opt out of the race when they know their projects share references, or
- At minimum, an env var like
AZD_PACKAGE_CONCURRENCY=1 to force serial packaging, mirroring AZD_DEPLOY_CONCURRENCY.
Environment
- Language: C# / .NET 10.0.300 (Aspire app host + multiple class-library-sharing projects)
- OS: <linux / azure pipelines hosted agent>
- CI: Azure Pipelines (
/azp/_work/...)
- IDE: <n/a — failure is on pipeline agent>
Additional context
- Worked fine on azd <= 1.24.
- Adding
uses to azure.yaml does not help — packaging/publishing run in parallel regardless per the 1.25.0 release blog.
AZD_DEPLOY_CONCURRENCY=1 looks like a workaround, but it does not solve the issue.
Output from
azd versionDescribe the bug
In azd 1.25.0+,
azd deploy(andazd up) runsdotnet publishfor all services in parallel during the Packaging/Publishing phase. Per the release blog post, this is by design: "Packaging and publishing always run in parallel regardless ofuses— it's only the deploy step that gates on these edges."This breaks .NET Aspire projects where multiple services share a common class library via
<ProjectReference>. Each paralleldotnet publishinvocation walks into the shared project and tries to write to the sameobj/Release/<tfm>/<SharedLib>.dll, producing anMSB4018/System.IO.IOException: The process cannot access the file ... because it is being used by another process.There is no opt-out:
usesonly controls the deploy step, not packaging/publishing, so users cannot avoid this race even when they know about the shared reference.To Reproduce
MyApp.Common.Contracts.csproj.azd deploy(orazd up).dotnet publishon each service simultaneously, racing on the shared project'sobj/Release/<tfm>/*.dll.Trimmed pipeline log:
The failure is non-deterministic — which service "wins" and which fails varies between runs. On azd 1.24 and earlier, the same project deploys cleanly because publish steps were serialized.
Expected behavior
Either:
dotnet publishinvocations for projects that share<ProjectReference>ancestors should be serialized (azd could detect overlapping project graphs during the analyze step), orusesfield (or a new field) should gate the packaging/publishing phase as well, not only deploy, so users can opt out of the race when they know their projects share references, orAZD_PACKAGE_CONCURRENCY=1to force serial packaging, mirroringAZD_DEPLOY_CONCURRENCY.Environment
/azp/_work/...)Additional context
usestoazure.yamldoes not help — packaging/publishing run in parallel regardless per the 1.25.0 release blog.AZD_DEPLOY_CONCURRENCY=1looks like a workaround, but it does not solve the issue.