Skip to content

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Nov 1, 2025

Backport of #12563 to release/13.0
/cc @davidfowl @copilot

Customer Impact

Customers were experiencing issues when using the Aspire CLI publish command without specifying an output path. The previous implementation always required an OutputPath and would throw InvalidOperationException in Azure, Kubernetes, and Docker Compose publishing contexts when OutputPath was null. This PR introduces a new IPipelineOutputService that provides a default output path ({CurrentDirectory}/aspire-output) when none is specified, eliminating these exceptions and providing a consistent, predictable behavior.

Testing

  • Unit tests updated to reflect removal of outputPath parameter from PipelineContext constructor
  • Existing pipeline tests should validate that default output paths are correctly generated
  • Manual testing should verify publish operations complete successfully without explicitly specifying an output path

Risk

Low to Medium. This is a refactoring that changes how output paths are managed internally:

  • Low risk: The change provides better default behavior and eliminates exceptions
  • Medium risk: Changes core pipeline infrastructure (PipelineContext, PipelineStepContext) and introduces a new service that multiple publishing contexts depend on
  • The new IPipelineOutputService is marked as [Experimental("ASPIREPIPELINES004")], appropriately flagging the API surface as subject to change
  • All consuming code (Azure, Kubernetes, Docker Compose) updated to use the new service consistently

Regression?

No - This is a bug fix that resolves exceptions when OutputPath is not specified. It maintains backward compatibility by still respecting explicitly provided output paths.

Copilot AI and others added 9 commits November 1, 2025 00:16
- Create IPipelineOutputService interface with GetOutputDirectory() and GetTempDirectory() methods
- Implement PipelineOutputService with better naming than IntermediateOutputPath
- Expose service via PipelineContext.OutputService and PipelineStepContext.OutputService
- Keep backward compatible OutputPath property for existing consumers
- Remove direct IntermediateOutputPath property per feedback

Co-authored-by: davidfowl <[email protected]>
- Add GetOutputDirectory(IResource) overload for resource-specific output directories
- Add GetTempDirectory(IResource) overload for resource-specific temp directories
- Implementation creates subdirectories using resource.Name under base directories
- Enables per-resource isolation of output and temp artifacts

Co-authored-by: davidfowl <[email protected]>
- Remove OutputPath convenience property per @davidfowl feedback
- Consumers now explicitly call OutputService.GetOutputDirectory()
- Update AzureEnvironmentResource to use OutputService.GetOutputDirectory()
- Update PublishingContextUtils to use OutputService.GetOutputDirectory()
- Update test helper to use OutputService.GetOutputDirectory()
- Keep OutputService property for explicit access to output management

Co-authored-by: davidfowl <[email protected]>
- Register IPipelineOutputService in DI container with PipelineOptions
- Remove OutputService property from PipelineContext and PipelineStepContext
- Remove outputPath parameter from PipelineContext constructor
- Update all consumers to resolve IPipelineOutputService from Services
  - AzureEnvironmentResource
  - PublishingContextUtils
  - JsonDocumentManifestPublisher test helper
- Remove IOptions<PipelineOptions> dependency from PipelineExecutor
- Steps now explicitly resolve IPipelineOutputService when needed

Co-authored-by: davidfowl <[email protected]>
…specific overload

- PipelineOutputService now injects IOptions<PipelineOptions> and IConfiguration directly in constructor
- Simplified DI registration to use standard AddSingleton without factory lambda
- PublishingContextUtils uses GetOutputDirectory(environment) for resource-specific paths
- Removes manual path combination logic in favor of service method

Co-authored-by: davidfowl <[email protected]>
- Update Experimental attribute from ASPIREPIPELINES001 to ASPIREPIPELINES004
- Add XML documentation for GetOutputDirectory() default behavior
- Add XML documentation for private fields in PipelineOutputService
- Document purpose of AppHost:PathSha256 usage in CreateTempDirectory
- Suppress ASPIREPIPELINES004 diagnostic in all consuming files

Co-authored-by: captainsafia <[email protected]>
@github-actions
Copy link
Contributor Author

github-actions bot commented Nov 1, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 12581

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 12581"

@captainsafia captainsafia requested a review from joperezr November 1, 2025 01:31
@davidfowl davidfowl merged commit 49af7b9 into release/13.0 Nov 1, 2025
296 checks passed
@davidfowl davidfowl deleted the backport/pr-12563-to-release/13.0 branch November 1, 2025 03:10
@github-actions github-actions bot locked and limited conversation to collaborators Dec 1, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants