Conversation
This commit adds code generation support for Go and Java AppHosts: Go Code Generator (Aspire.Hosting.CodeGeneration.Go): - AtsGoCodeGenerator.cs: Generates Go SDK wrapper code from ATS capabilities - GoLanguageSupport.cs: Provides scaffolding, detection, and runtime config - Resources/transport.go: JSON-RPC client with Windows named pipe support - Resources/base.go: Base types (HandleWrapperBase, ReferenceExpression, etc.) Java Code Generator (Aspire.Hosting.CodeGeneration.Java): - AtsJavaCodeGenerator.cs: Generates Java SDK wrapper code with camelCase naming - JavaLanguageSupport.cs: Provides scaffolding, detection, and runtime config - Resources/Transport.java: JSON-RPC client with Windows named pipe support - Resources/Base.java: Base types for handle wrappers Both generators: - Generate wrapper classes that proxy capabilities via JSON-RPC - Support enums, DTOs, and handle types from ATS context - Include registration helpers for handle wrapper factories - Generate connection helpers (Aspire.Connect(), Aspire.CreateBuilder()) CLI Integration: - Register Go and Java in DefaultLanguageDiscovery.cs - Add language constants to KnownLanguageId.cs - Add code generator assemblies to AppHostServerProject.cs - Add InternalsVisibleTo entries in Aspire.Hosting.csproj - Add projects to Aspire.slnx
This commit adds initial Rust code generation support for AppHosts: Rust Code Generator (Aspire.Hosting.CodeGeneration.Rust): - AtsRustCodeGenerator.cs: Generates Rust SDK wrapper code with snake_case naming - RustLanguageSupport.cs: Provides scaffolding, detection, and runtime config - Resources/transport.rs: JSON-RPC client with Windows named pipe support - Resources/base.rs: Base types for handle wrappers The generator produces: - Enum types with serde Serialize/Deserialize derives - DTO structs with optional field support - Handle wrapper structs that proxy capabilities via JSON-RPC - Connection helpers (connect(), create_builder()) CLI Integration: - Register Rust in DefaultLanguageDiscovery.cs - Add language constants to KnownLanguageId.cs - Add code generator assembly to AppHostServerProject.cs - Add InternalsVisibleTo entry in Aspire.Hosting.csproj - Add project to Aspire.slnx Note: This is a work-in-progress. The generated Rust code compiles the infrastructure but needs further refinement for full AppHost functionality. The handle wrapping pattern needs adjustment for Rust's ownership model.
- Add serde Serialize/Deserialize derives to ReferenceExpression in base.rs - Fix DTO property serde attributes to only use skip_serializing_if for optional fields - Exclude ReferenceExpression from IsHandleType check - Add special handling for CancellationToken, AspireDict, AspireList return types - Update CancellationToken to support both local and handle-backed modes The generated Rust code now compiles successfully with cargo build.
…pendencies runs before code generation, so it cannot compile generated code. Moved compilation to Execute step for both Java and Rust. - Make Rust parameters idiomatic: String parameters now use &str instead of String, which is more idiomatic Rust.
- Remove InstallDependencies (go run handles dependencies automatically) - Add 'require' directive to go.mod (needed alongside 'replace' directive)
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 13978Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 13978" |
- Added 19 tests covering: - Language property returns Python - Embedded resources (transport.py, base.py) match snapshots - Generated code includes expected capabilities - Method names derive correctly - Parameters are captured correctly - ReturnsBuilder is set for fluent chaining - Scanner metadata verification via Verify snapshots - Two-pass scanning merges types from all assemblies - Generated code uses snake_case method names - Generated code has create_builder function - Generated code uses Python type hints - Shares TestTypes with TypeScript tests via Compile Include - Added Verify.XunitV3 for snapshot testing - All tests pass
- Go: 19 tests with snapshot verification for generated code - Java: 19 tests with snapshot verification for generated code - Rust: 19 tests with snapshot verification for generated code - Tests follow the TypeScript test project pattern with shared TestTypes - Uses Verify.XunitV3 for snapshot testing
… Rust Following the TypeScript improvements in main for List properties on context classes, this commit applies the same pattern to all other language generators: - Add lazy handle resolution to AspireList and AspireDict classes - Generate cached property getters for List/Dict type properties - Context classes now create AspireList/AspireDict with getter capability ID - The handle is resolved lazily on first access This ensures consistent behavior across all polyglot code generators when accessing List/Dict properties on [AspireExport(ExposeProperties=true)] types.
🐛 Go SDK Code Generation ErrorTested with CLI version Commandaspire sdk generate path/to/Aspire.Hosting.csproj --language go --output ./go-sampleErrorStack TraceRoot CauseThe Go code generator is calling Suggested FixAdd |
|
@copilot in the Python polyglot E2E CLI test you need to enably polyglot support via the feature flag. Review the typescript E2E for an example. |
|
@mitchdenny I've opened a new pull request, #13981, to work on those changes. Once the pull request is ready, I'll request review from you. |
…generators Replace calls to internal AtsConstants.IsDict()/IsList() methods with AtsTypeCategory checks. The internal methods caused MethodAccessException when assemblies were dynamically loaded at runtime. - Go, Python, Java generators now use Dictionary<string, bool> to track whether each collected type ID is a Dict or List - Category is determined at collection time using AtsTypeCategory enum - Fixes runtime error: MethodAccessException when accessing internal methods
Remove the 'aspire run' step from the E2E test since Python runtime may not be available on CI. The test now only verifies: - Creating a Python apphost with 'aspire init -l python' - Adding Redis integration with 'aspire add redis'
Verify that generated files contain expected code: - apphost.py contains create_builder import and usage - .modules/aspire.py contains add_redis method after adding Redis integration
# Conflicts: # .github/workflows/cli-e2e-recording-comment.yml
- Use 'aspire run --detach' instead of timeout with background process - Use 'aspire stop' for cleanup instead of kill - Add polling loop (12 attempts x 10s = 2 min, 18 for Rust = 3 min) - Keep --non-interactive flag on aspire add command
- Use 'aspire run --detach' instead of timeout with background process - Use 'aspire stop' for cleanup instead of kill - Add polling loop (12 attempts x 10s = 2 min, 18 for Rust = 3 min) - Keep --non-interactive flag on aspire add command # Conflicts: # .github/workflows/polyglot-validation/test-go.sh # .github/workflows/polyglot-validation/test-java.sh # .github/workflows/polyglot-validation/test-python.sh # .github/workflows/polyglot-validation/test-rust.sh
The save_global_settings call for channel can fail in some container environments. Since the workflow explicitly sets the channel config afterward, this failure should not be fatal.
When --non-interactive flag is passed and there are multiple packages or versions to choose from, auto-select the first one (latest version) instead of trying to prompt and throwing an exception.
This ensures the workflow uses the script from the current branch/PR, which includes fixes for non-fatal config set errors.
Run aspire run in background with &, poll for Redis container, then kill the process on cleanup. Also capture aspire.log on failure for debugging.
The native AOT Aspire CLI requires GLIBC 2.38 which is only available in Debian 13 (trixie), not Debian 12 (bookworm).
…lotJavaTests These are replaced by the polyglot-validation workflow which runs SDK validation in Docker containers.
Start aspire run in its own process group with setsid, then kill the entire group with kill -9 -$PID to ensure all child processes are terminated.
|
Would it be cleaner to build docker files for each scenario |
- Create Dockerfile.python, Dockerfile.go, Dockerfile.java, Dockerfile.rust, Dockerfile.typescript - Update polyglot-validation.yml to build and run Dockerfiles instead of inline scripts - Improves maintainability and enables easier local testing
|
/azp run aspire-tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@radical why did you break my build? |
|
/ba-g known failures |
Just making sure it didn't break on azdo. It's green to merge now. |
| } | ||
|
|
||
| // ... otherwise we had better prompt. | ||
| // In non-interactive mode, auto-select the latest version. |
There was a problem hiding this comment.
omg thank you this was driving me nuts....
|
|
||
| # Add Redis integration | ||
| echo "Adding Redis integration..." | ||
| aspire add Aspire.Hosting.Redis --non-interactive 2>&1 || { |
There was a problem hiding this comment.
@sebastienros would this use the default docker registry? it might get rate limited.
There was a problem hiding this comment.
That could be the case. To solve that we need to call .WithImageRegistry("netaspireci.azurecr.io") when we add AddRedis(...) in the apphosts. #14113
Description
Adds Python, Go, Java and Rust polyglot apphost support.
Currently in Draft to test the CI.
Checklist
<remarks />and<code />elements on your triple slash comments?