Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 7, 2025

This PR implements a new primitive Files resource in the Aspire project, providing a standardized way to manage file collections within the Aspire application model.

Overview

The Files resource introduces a lightweight primitive for representing and managing collections of files in Aspire applications. This is useful for scenarios where applications need to track configuration files, templates, assets, or other file-based resources.

Implementation Details

Core Components

IResourceWithFiles Interface

  • New standard interface for resources that work with files
  • Exposes a Files property as IEnumerable<string> for file path access
  • Follows established Aspire interface patterns

FilesResource Class

  • Concrete implementation inheriting from Resource
  • Implements both IResourceWithFiles and IResourceWithoutLifetime
  • Provides dynamic file management with AddFile() and AddFiles() methods
  • Uses primary constructor pattern consistent with C# 13

FilesProducedEvent

  • Event raised when files are produced by a resource
  • Implements IDistributedApplicationResourceEvent for consistency
  • Includes Resource, Services, and Files properties for complete context

Builder Extensions

  • Simple AddFiles() method that creates an empty files resource
  • WithSource() method for adding source paths to the resource
  • Comprehensive null checking and argument validation
  • Event-driven architecture: WithSource() now wires up to the OnResourceInitialize event for directory validation and event firing

Event Handling

When WithSource(...) is called, it:

  • Immediately adds the source to the resource (maintains existing behavior)
  • Adds a FilesSourceAnnotation to track the source path
  • Registers an initialization event handler (only once per resource)

During resource initialization, the event handler:

  • Verifies that each source path is a valid directory
  • Logs warnings for invalid directories
  • Fires FilesProducedEvent with all valid files found in directories
  • Fires ResourceReadyEvent to signal the resource is ready

Usage Examples

// Create a files resource and add a source directory
var staticContent = builder.AddFiles("static-content")
    .WithSource("content");

// Add multiple sources
var templates = builder.AddFiles("templates")
    .WithSource("/templates/email.html")
    .WithSource("/templates/directory");

Playground Application

A complete playground application is included at playground/files/ that demonstrates the Files resource usage:

  • Files.AppHost project with proper configuration
  • Uses AddFiles("static-content").WithSource("../content") to reference a content directory
  • Includes a sample index.html file that explains the Files resource functionality

Testing

Comprehensive test suite includes:

  • Resource creation with empty initial state
  • Source addition using WithSource() method
  • Interface implementation validation
  • Event creation and handling
  • Error condition testing with proper exception handling

Benefits

  • Lightweight: No lifecycle management overhead (implements IResourceWithoutLifetime)
  • Simple: Clean API with AddFiles() and WithSource() methods
  • Flexible: Supports both file and directory sources
  • Consistent: Follows established Aspire patterns and conventions
  • Type Safe: Full null safety with proper argument validation
  • Extensible: Standard interface allows other resources to implement file capabilities
  • Event-Driven: Proper integration with Aspire's event system for validation and notifications

This primitive resource provides a foundation for file-based scenarios in Aspire applications while maintaining consistency with the existing resource model.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI changed the title [WIP] Add primitive FilesResource and IResourceWithFiles with FilesProducedEvent Add primitive Files resource to Aspire.Hosting Sep 7, 2025
@Copilot Copilot AI requested a review from mitchdenny September 7, 2025 10:15
Copilot finished work on behalf of mitchdenny September 7, 2025 10:15
@mitchdenny
Copy link
Member

@copilot remove the list of files on the AddFiles method the AddFiles method simply adds the resource. Change the WithFile and WithFiles methods to a single WithSource method that takes a single string argument.

Also add a playground/files playground app which makes use of this integration. It should contain an apphost and a AddFiles(...).WithSource(...) call that points to a directory that contains a single index.html file.

Copy link
Contributor

github-actions bot commented Sep 7, 2025

🚀 Dogfood this PR with:

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

Or

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

1 similar comment
Copy link
Contributor

github-actions bot commented Sep 7, 2025

🚀 Dogfood this PR with:

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

Or

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

…nd replace WithFile/WithFiles with WithSource

Co-authored-by: mitchdenny <[email protected]>
Copy link
Contributor Author

Copilot AI commented Sep 7, 2025

@copilot remove the list of files on the AddFiles method the AddFiles method simply adds the resource. Change the WithFile and WithFiles methods to a single WithSource method that takes a si...

I've made the requested changes in commit 8d99ff3:

  1. Removed the list of files parameter from AddFiles - now only takes a name and creates an empty resource
  2. Replaced WithFile and WithFiles methods with a single WithSource method that takes a string argument
  3. Created playground/files with a Files.AppHost project that demonstrates AddFiles().WithSource("content") pointing to a directory containing index.html

The API is now simplified to:

builder.AddFiles("static-content").WithSource("content");

Copilot finished work on behalf of mitchdenny September 7, 2025 11:27
@mitchdenny
Copy link
Member

@copilot when WithSource(...) is called it should wire-up to the OnResourceInitialize(...) event. In the event handler it should verify that the path specified in WithSource(path) is a valid directory and then fore the FilesProducedEvent followed by the ResourceReadyEvent.

Copy link
Contributor Author

Copilot AI commented Sep 7, 2025

@copilot when WithSource(...) is called it should wire-up to the OnResourceInitialize(...) event. In the event handler it should verify that the path specified in WithSource(path) is a valid direc...

I've implemented the requested event-driven architecture in commit 5dcaf5c. When WithSource(...) is called, it now:

  1. Wires up to the OnResourceInitialize event (using a marker annotation to ensure single registration)
  2. In the event handler, verifies that each source path is a valid directory
  3. Fires the FilesProducedEvent with all valid files found in directories
  4. Fires the ResourceReadyEvent to signal the resource is ready

Invalid directories log warnings but don't fail the resource initialization. All existing tests continue to pass.

Copilot finished work on behalf of mitchdenny September 7, 2025 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants