Add TypeScript Express/React deployment E2E test and template updates#14967
Add TypeScript Express/React deployment E2E test and template updates#14967davidfowl merged 8 commits intorelease/13.2from
Conversation
Add TypeScriptExpressDeploymentTests that deploys the ts-starter template to Azure Container Apps. Also: - Export PublishWithContainerFiles via [AspireExport] for polyglot apphost usage - Update Express API template to serve static files from ./static directory when present (deploy mode) The deployment bundles the Vite frontend into the Express API container via publishWithContainerFiles, matching the pattern used by the Python FastAPI template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14967Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 14967" |
There was a problem hiding this comment.
Pull request overview
This PR adds a new end-to-end deployment test for TypeScript Express/React applications and updates the ts-starter template to support deployment via Azure Container Apps. It also exports PublishWithContainerFiles for use by polyglot (TypeScript/Python) apphosts through the [AspireExport] attribute.
Changes:
- New
TypeScriptExpressDeploymentTests.csE2E test that creates a project from the Express/React template, adds Azure Container Apps hosting, deploys, and verifies endpoints — closely following the existingPythonFastApiDeploymentTestspattern. - Template updates:
apphost.tscaptures thefrontendvariable and callspublishWithContainerFilesto bundle Vite build output into the Express container;api/src/index.tsserves static files from a./staticdirectory when present. [AspireExport]attribute added toPublishWithContainerFilesto make it available to TypeScript/Python apphosts via codegen.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
tests/Aspire.Deployment.EndToEnd.Tests/TypeScriptExpressDeploymentTests.cs |
New E2E deployment test for TypeScript Express/React template, following established patterns |
src/Aspire.Hosting/ResourceBuilderExtensions.cs |
Adds [AspireExport] attribute to PublishWithContainerFiles for polyglot apphost codegen |
src/Aspire.Cli/Templating/Templates/ts-starter/apphost.ts |
Template update: captures frontend builder and calls publishWithContainerFiles to bundle static assets |
src/Aspire.Cli/Templating/Templates/ts-starter/api/src/index.ts |
Serves static files from ./static directory when present (for deploy mode) |
The API endpoint needs to be marked as external so it gets exposed publicly when deployed (Docker Compose or ACA). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ython template Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Node 22 supports import.meta.dirname natively, removing the need for the fileURLToPath/dirname workaround. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The [AspireExport] attribute on PublishWithContainerFiles causes the method and IContainerFilesDestinationResource type to appear in the TwoPassScanning codegen output for all languages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🎬 CLI E2E Test RecordingsThe following terminal recordings are available for commit
📹 Recordings uploaded automatically from CI run #22707857569 |
|
/deployment-test |
|
🚀 Deployment tests starting on PR #14967... This will deploy to real Azure infrastructure. Results will be posted here when complete. |
The apphost names the resource 'app', so the environment variables injected by Aspire are APP_HTTP/APP_HTTPS, not API_HTTP/API_HTTPS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
❌ Deployment E2E Tests failed Summary: 25 passed, 1 failed, 0 cancelled Passed Tests
Failed Tests
🎬 Terminal Recordings
|
When aspire new resolves a version from an explicit channel (e.g. local, daily), persist the channel name in .aspire/settings.json so that subsequent aspire add commands use the same channel without prompting. Implicit channels (stable/nuget.org) are not written, keeping the default behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/deployment-test |
1 similar comment
|
/deployment-test |
|
❌ Deployment E2E Tests failed Summary: 25 passed, 1 failed, 0 cancelled Passed Tests
Failed Tests
🎬 Terminal Recordings
|
|
/deployment-test TypeScriptExpressDeploymentTests |
| /// <param name="builder">The resource builder to which container files will be copied to.</param> | ||
| /// <param name="source">The resource which contains the container files to be copied.</param> | ||
| /// <param name="destinationPath">The destination path within the resource's container where the files will be copied.</param> | ||
| [AspireExport("publishWithContainerFiles", Description = "Configures the resource to copy container files from the specified source during publishing")] |
There was a problem hiding this comment.
@sebastienros - when is the Description on this annotation ever different from the summary of the XML docs?
There was a problem hiding this comment.
This is something we're likely going to remove once we figure out the doc comment story.
|
The failure is:
|
|
Yea I tried, to re-run it. I'll test it manually and open a new PR if there are any issues. |
…microsoft#14967) * Add TypeScript Express/React deployment E2E test Add TypeScriptExpressDeploymentTests that deploys the ts-starter template to Azure Container Apps. Also: - Export PublishWithContainerFiles via [AspireExport] for polyglot apphost usage - Update Express API template to serve static files from ./static directory when present (deploy mode) The deployment bundles the Vite frontend into the Express API container via publishWithContainerFiles, matching the pattern used by the Python FastAPI template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add withExternalHttpEndpoints to ts-starter template The API endpoint needs to be marked as external so it gets exposed publicly when deployed (Docker Compose or ACA). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename ts-starter resource from 'api' to 'app' for consistency with Python template Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify static file imports using import.meta.dirname Node 22 supports import.meta.dirname natively, removing the need for the fileURLToPath/dirname workaround. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add await to publishWithContainerFiles call in template Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update codegen snapshots for PublishWithContainerFiles export The [AspireExport] attribute on PublishWithContainerFiles causes the method and IContainerFilesDestinationResource type to appear in the TwoPassScanning codegen output for all languages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix React template env vars to match resource name The apphost names the resource 'app', so the environment variables injected by Aspire are APP_HTTP/APP_HTTPS, not API_HTTP/API_HTTPS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Write channel to settings.json during aspire new for CLI templates When aspire new resolves a version from an explicit channel (e.g. local, daily), persist the channel name in .aspire/settings.json so that subsequent aspire add commands use the same channel without prompting. Implicit channels (stable/nuget.org) are not written, keeping the default behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Mitch Denny <mitch@mitchdeny.com>
…#14967) * Add TypeScript Express/React deployment E2E test Add TypeScriptExpressDeploymentTests that deploys the ts-starter template to Azure Container Apps. Also: - Export PublishWithContainerFiles via [AspireExport] for polyglot apphost usage - Update Express API template to serve static files from ./static directory when present (deploy mode) The deployment bundles the Vite frontend into the Express API container via publishWithContainerFiles, matching the pattern used by the Python FastAPI template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add withExternalHttpEndpoints to ts-starter template The API endpoint needs to be marked as external so it gets exposed publicly when deployed (Docker Compose or ACA). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename ts-starter resource from 'api' to 'app' for consistency with Python template Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify static file imports using import.meta.dirname Node 22 supports import.meta.dirname natively, removing the need for the fileURLToPath/dirname workaround. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add await to publishWithContainerFiles call in template Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update codegen snapshots for PublishWithContainerFiles export The [AspireExport] attribute on PublishWithContainerFiles causes the method and IContainerFilesDestinationResource type to appear in the TwoPassScanning codegen output for all languages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix React template env vars to match resource name The apphost names the resource 'app', so the environment variables injected by Aspire are APP_HTTP/APP_HTTPS, not API_HTTP/API_HTTPS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Write channel to settings.json during aspire new for CLI templates When aspire new resolves a version from an explicit channel (e.g. local, daily), persist the channel name in .aspire/settings.json so that subsequent aspire add commands use the same channel without prompting. Implicit channels (stable/nuget.org) are not written, keeping the default behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Mitch Denny <mitch@mitchdeny.com>
Description
Add a TypeScript Express/React deployment E2E test and update the ts-starter template for deployment readiness.
Changes:
TypeScript deployment E2E test (
TypeScriptExpressDeploymentTests.cs) — follows the same pattern asPythonFastApiDeploymentTests:aspire new(Express/React template)Aspire.Hosting.Azure.AppContainersviaaspire addapphost.tsto addaddAzureContainerAppEnvironmentaspire deployTemplate updates for deployment support:
apphost.ts: Renamed resource fromapitoappfor consistency with Python template. Capturefrontendvariable and addawait app.publishWithContainerFiles(frontend, "./static")so the Vite frontend build output is bundled into the Express API container during publish. AddedwithExternalHttpEndpoints()so the API is publicly accessible when deployed.api/src/index.ts: Serve static files from./staticdirectory when present (deploy mode), usingimport.meta.dirname(Node 22+)Export
PublishWithContainerFilesfor polyglot apphosts — Added[AspireExport]attribute toResourceBuilderExtensions.PublishWithContainerFilesso TypeScript/Python apphosts can use it via ATS codegen. This exposes the existing public API to the polyglot SDK generation pipeline.Checklist
<remarks />and<code />elements on your triple slash comments?aspire.devissue: