diff --git a/src/apphosting/backend.ts b/src/apphosting/backend.ts index db2228fb8b8..056f2786a32 100644 --- a/src/apphosting/backend.ts +++ b/src/apphosting/backend.ts @@ -134,12 +134,21 @@ export async function doSetup( if (nonInteractive) { runtime = DEFAULT_RUNTIME; } else { + const choices: Choice[] = [{ name: "Node.js (default)", value: DEFAULT_RUNTIME }]; + try { + const supportedRuntimes = await apphosting.listSupportedRuntimes(projectId, location); + for (const r of supportedRuntimes) { + if (r.runtimeId !== DEFAULT_RUNTIME) { + choices.push({ name: r.runtimeId, value: r.runtimeId }); + } + } + } catch (err) { + logWarning("Failed to list supported runtimes. Falling back to default."); + } + runtime = await select({ message: "Which runtime do you want to use?", - choices: [ - { name: "Node.js (default)", value: DEFAULT_RUNTIME }, - { name: "Node.js 22", value: "nodejs22" }, - ], + choices: choices, default: DEFAULT_RUNTIME, }); } diff --git a/src/gcp/apphosting.spec.ts b/src/gcp/apphosting.spec.ts index f2d4ab97184..6840e81657b 100644 --- a/src/gcp/apphosting.spec.ts +++ b/src/gcp/apphosting.spec.ts @@ -278,5 +278,17 @@ describe("apphosting", () => { queryParams: { pageToken: "2" }, }); }); + + it("lists supported runtimes", async () => { + get.resolves({ + body: { + supportedRuntimes: [{ runtimeId: "nodejs22" }], + }, + }); + await expect(apphosting.listSupportedRuntimes("p", "l")).to.eventually.deep.equal([ + { runtimeId: "nodejs22" }, + ]); + expect(get).to.have.been.calledWithMatch("projects/p/locations/l/supportedRuntimes"); + }); }); }); diff --git a/src/gcp/apphosting.ts b/src/gcp/apphosting.ts index 9392d985443..d007a9250a2 100644 --- a/src/gcp/apphosting.ts +++ b/src/gcp/apphosting.ts @@ -58,6 +58,18 @@ export interface Backend { automaticBaseImageUpdatesDisabled?: boolean; } +export interface SupportedRuntime { + name: string; + runtimeId: string; + automaticBaseImageUpdatesSupported: boolean; + deprecateTime?: string; + decommissionTime?: string; +} + +export interface ListSupportedRuntimesResponse { + supportedRuntimes: SupportedRuntime[]; +} + export interface ManagedResource { runService: { service: string }; } @@ -711,6 +723,18 @@ export async function listLocations(projectId: string): Promise { return locations; } +/** + * Lists supported runtimes for a given project and location. + */ +export async function listSupportedRuntimes( + projectId: string, + location: string, +): Promise { + const name = `projects/${projectId}/locations/${location}/supportedRuntimes`; + const res = await client.get(name); + return res.body.supportedRuntimes || []; +} + /** * Ensure that the App Hosting API is enabled on the project. */