Skip to content

Commit 37073b8

Browse files
Fix Python starter TypeScript health check build (#16625)
* Fix Python starter health check template Update the Python starter TypeScript AppHost to use the supported withHttpHealthCheck options object and align its root build script with AppHost-only type checking. Add E2E coverage that verifies the generated starter builds successfully. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use fail-fast helper for Python starter build test Update the Python React template E2E build verification to use the existing fail-fast command helper so npm build failures are surfaced immediately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Verify TypeScript templates build Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add build script aliases to TypeScript AppHost scaffold Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use AppHost tsconfig for TypeScript AppHost lint Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use AppHost tsconfig name for Python starter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a6738f6 commit 37073b8

11 files changed

Lines changed: 59 additions & 23 deletions

File tree

src/Aspire.Cli/Templating/Templates/py-starter/apphost.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const app = await builder
1717
.withReference(cache)
1818
.waitFor(cache)
1919
// {{/redis}}
20-
.withHttpHealthCheck("/health");
20+
.withHttpHealthCheck({ path: "/health" });
2121

2222
// Run the Vite frontend after the API and inject the API URL for local proxying.
2323
const frontend = await builder

src/Aspire.Cli/Templating/Templates/py-starter/eslint.config.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export default defineConfig({
88
extends: [tseslint.configs.base],
99
languageOptions: {
1010
parserOptions: {
11-
projectService: true,
11+
project: './tsconfig.apphost.json',
12+
tsconfigRootDir: import.meta.dirname,
1213
},
1314
},
1415
rules: {

src/Aspire.Cli/Templating/Templates/py-starter/package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
"private": true,
44
"type": "module",
55
"scripts": {
6-
"lint": "eslint apphost.ts",
7-
"predev": "npm run lint",
8-
"dev": "aspire run",
9-
"prebuild": "npm run lint",
10-
"build": "tsc",
11-
"watch": "tsc --watch"
6+
"aspire:lint": "eslint apphost.ts",
7+
"aspire:start": "aspire run",
8+
"aspire:build": "tsc -p tsconfig.apphost.json",
9+
"aspire:dev": "tsc --watch -p tsconfig.apphost.json",
10+
"lint": "npm run aspire:lint",
11+
"predev": "npm run aspire:lint",
12+
"dev": "npm run aspire:start",
13+
"prebuild": "npm run aspire:lint",
14+
"build": "npm run aspire:build",
15+
"watch": "npm run aspire:dev"
1216
},
1317
"dependencies": {
1418
"vscode-jsonrpc": "^8.2.0"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"module": "NodeNext",
5+
"moduleResolution": "NodeNext",
6+
"esModuleInterop": true,
7+
"forceConsistentCasingInFileNames": true,
8+
"skipLibCheck": true,
9+
"outDir": "./dist/apphost",
10+
"rootDir": ".",
11+
"strict": true
12+
},
13+
"include": ["apphost.ts", ".modules/**/*.ts"],
14+
"exclude": ["node_modules"]
15+
}

src/Aspire.Cli/Templating/Templates/py-starter/tsconfig.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/Aspire.Cli/Templating/Templates/ts-starter/eslint.config.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export default defineConfig({
88
extends: [tseslint.configs.base],
99
languageOptions: {
1010
parserOptions: {
11-
projectService: true,
11+
project: './tsconfig.apphost.json',
12+
tsconfigRootDir: import.meta.dirname,
1213
},
1314
},
1415
rules: {

src/Aspire.Hosting.CodeGeneration.TypeScript/TypeScriptLanguageSupport.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ public Dictionary<string, string> Scaffold(ScaffoldRequest request)
102102
extends: [tseslint.configs.base],
103103
languageOptions: {
104104
parserOptions: {
105-
projectService: true,
105+
project: './tsconfig.apphost.json',
106+
tsconfigRootDir: import.meta.dirname,
106107
},
107108
},
108109
rules: {
@@ -148,7 +149,8 @@ private static string CreatePackageJson(ScaffoldRequest request)
148149
var packageJson = new JsonObject();
149150
var packageJsonPath = Path.Combine(request.TargetPath, PackageJsonFileName);
150151

151-
if (!File.Exists(packageJsonPath))
152+
var isGreenfield = !File.Exists(packageJsonPath);
153+
if (isGreenfield)
152154
{
153155
// Greenfield: include root metadata so the scaffold output is a complete package.json.
154156
var packageName = request.ProjectName?.ToLowerInvariant() ?? "aspire-apphost";
@@ -171,6 +173,16 @@ private static string CreatePackageJson(ScaffoldRequest request)
171173
scripts["aspire:build"] = $"tsc -p {AppHostTsConfigFileName}";
172174
scripts["aspire:dev"] = $"tsc --watch -p {AppHostTsConfigFileName}";
173175

176+
if (isGreenfield)
177+
{
178+
scripts["lint"] = "npm run aspire:lint";
179+
scripts["predev"] = "npm run aspire:lint";
180+
scripts["dev"] = "npm run aspire:start";
181+
scripts["prebuild"] = "npm run aspire:lint";
182+
scripts["build"] = "npm run aspire:build";
183+
scripts["watch"] = "npm run aspire:dev";
184+
}
185+
174186
EnsureDependency(packageJson, "dependencies", "vscode-jsonrpc", "^8.2.0");
175187
EnsureDependency(packageJson, "devDependencies", "@types/node", "^22.0.0");
176188
EnsureDependency(packageJson, "devDependencies", "eslint", "^10.0.3");

tests/Aspire.Cli.EndToEnd.Tests/PythonReactTemplateTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ public async Task CreateAndRunPythonReactProject()
4646
await auto.EnterAsync();
4747
await auto.WaitForSuccessPromptAsync(counter);
4848

49-
// Step 3: Start and stop the project
49+
// Step 3: Verify the generated TypeScript AppHost builds successfully.
50+
await auto.RunCommandFailFastAsync("npm run build", counter, TimeSpan.FromMinutes(2));
51+
52+
// Step 4: Start and stop the project
5053
await auto.AspireStartAsync(counter);
5154
await auto.AspireStopAsync(counter);
5255

tests/Aspire.Cli.EndToEnd.Tests/TypeScriptEmptyAppHostTemplateTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public async Task CreateAndRunTypeScriptEmptyAppHostProject()
4444
await auto.EnterAsync();
4545
await auto.WaitForSuccessPromptAsync(counter);
4646

47+
await auto.RunCommandFailFastAsync("npm run build", counter, TimeSpan.FromMinutes(2));
48+
4749
await auto.AspireStartAsync(counter);
4850
await auto.AspireStopAsync(counter);
4951

tests/Aspire.Cli.EndToEnd.Tests/TypeScriptStarterTemplateTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public async Task CreateAndRunTypeScriptStarterProject()
5757
await auto.EnterAsync();
5858
await auto.WaitForSuccessPromptAsync(counter);
5959

60+
await auto.RunCommandFailFastAsync("npm run build", counter, TimeSpan.FromMinutes(2));
61+
6062
await auto.AspireStartAsync(counter);
6163
await auto.AspireStopAsync(counter);
6264

0 commit comments

Comments
 (0)