diff --git a/src/init/features/frameworks/index.ts b/src/init/features/frameworks/index.ts index 1a42ae475d0..8897481e600 100644 --- a/src/init/features/frameworks/index.ts +++ b/src/init/features/frameworks/index.ts @@ -2,7 +2,7 @@ import * as clc from "colorette"; import * as repo from "./repo"; import * as poller from "../../../operation-poller"; import * as gcp from "../../../gcp/frameworks"; -import { logBullet, logSuccess } from "../../../utils"; +import { logBullet, logSuccess, logWarning } from "../../../utils"; import { frameworksOrigin } from "../../../api"; import { Backend, BackendOutputOnlyFields } from "../../../gcp/frameworks"; import { Repository } from "../../../gcp/cloudbuild"; @@ -26,32 +26,40 @@ export async function doSetup(setup: any, projectId: string): Promise { logBullet("First we need a few details to create your backend."); - await promptOnce( - { - name: "serviceName", + const location = await promptOnce({ + name: "region", + type: "list", + default: DEFAULT_REGION, + message: + "Please select a region " + + `(${clc.yellow("info")}: Your region determines where your backend is located):\n`, + choices: ALLOWED_REGIONS, + }); + + logSuccess(`Region set to ${location}.\n`); + + let backendId: string; + while (true) { + backendId = await promptOnce({ + name: "backendId", type: "input", default: "acme-inc-web", message: "Create a name for your backend [1-30 characters]", - }, - setup.frameworks - ); - - await promptOnce( - { - name: "region", - type: "list", - default: DEFAULT_REGION, - message: - "Please select a region " + - `(${clc.yellow("info")}: Your region determines where your backend is located):\n`, - choices: ALLOWED_REGIONS, - }, - setup.frameworks - ); - - logSuccess(`Region set to ${setup.frameworks.region}.\n`); - - const backend: Backend | undefined = await getOrCreateBackend(projectId, setup); + }); + try { + await gcp.getBackend(projectId, location, backendId); + } catch (err: any) { + if (err.status === 404) { + break; + } + throw new FirebaseError( + `Failed to check if backend with id ${backendId} already exists in ${location}`, + { original: err } + ); + } + logWarning(`Backend with id ${backendId} already exists in ${location}`); + } + const backend: Backend = await onboardBackend(projectId, location, backendId); if (backend) { logSuccess(`Successfully created backend:\n\t${backend.name}`); @@ -74,75 +82,24 @@ function toBackend(cloudBuildConnRepo: Repository): Omit { - const location: string = setup.frameworks.region; - try { - return await getExistingBackend(projectId, setup, location); - } catch (err: unknown) { - if ((err as FirebaseError).status === 404) { - const cloudBuildConnRepo = await repo.linkGitHubRepository(projectId, location); - await promptOnce( - { - name: "branchName", - type: "input", - default: "main", - message: "Which branch do you want to deploy?", - }, - setup.frameworks - ); - const backendDetails = toBackend(cloudBuildConnRepo); - return await createBackend(projectId, location, backendDetails, setup.frameworks.serviceName); - } else { - throw new FirebaseError( - `Failed to get or create a backend using the given initialization details: ${err}` - ); - } - } - - return undefined; -} - -async function getExistingBackend( +export async function onboardBackend( projectId: string, - setup: any, - location: string + location: string, + backendId: string ): Promise { - let backend = await gcp.getBackend(projectId, location, setup.frameworks.serviceName); - while (backend) { - setup.frameworks.serviceName = undefined; - await promptOnce( - { - name: "existingBackend", - type: "confirm", - default: true, - message: - "A backend already exists for the given serviceName, do you want to use existing backend? (yes/no)", - }, - setup.frameworks - ); - if (setup.frameworks.existingBackend) { - logBullet("Using the existing backend."); - return backend; - } - await promptOnce( - { - name: "serviceName", - type: "input", - default: "acme-inc-web", - message: "Please enter a new service name [1-30 characters]", - }, - setup.frameworks - ); - backend = await gcp.getBackend(projectId, location, setup.frameworks.serviceName); - setup.frameworks.existingBackend = undefined; - } - - return backend; + const cloudBuildConnRepo = await repo.linkGitHubRepository(projectId, location); + const barnchName = await promptOnce({ + name: "branchName", + type: "input", + default: "main", + message: "Which branch do you want to deploy?", + }); + // branchName unused for now. + void barnchName; + const backendDetails = toBackend(cloudBuildConnRepo); + return await createBackend(projectId, location, backendDetails, backendId); } /** diff --git a/src/test/init/frameworks/index.spec.ts b/src/test/init/frameworks/index.spec.ts index 84ecadd34c4..1dd4b9ffbae 100644 --- a/src/test/init/frameworks/index.spec.ts +++ b/src/test/init/frameworks/index.spec.ts @@ -4,7 +4,8 @@ import { expect } from "chai"; import * as gcp from "../../../gcp/frameworks"; import * as repo from "../../../init/features/frameworks/repo"; import * as poller from "../../../operation-poller"; -import { createBackend, getOrCreateBackend } from "../../../init/features/frameworks/index"; +import * as prompt from "../../../prompt"; +import { createBackend, onboardBackend } from "../../../init/features/frameworks/index"; import { FirebaseError } from "../../../error"; describe("operationsConverter", () => { @@ -14,6 +15,7 @@ describe("operationsConverter", () => { let createBackendStub: sinon.SinonStub; let getBackendStub: sinon.SinonStub; let linkGitHubRepositoryStub: sinon.SinonStub; + let promptOnce: sinon.SinonStub; beforeEach(() => { pollOperationStub = sandbox @@ -24,20 +26,23 @@ describe("operationsConverter", () => { linkGitHubRepositoryStub = sandbox .stub(repo, "linkGitHubRepository") .throws("Unexpected getBackend call"); + promptOnce = sandbox.stub(prompt, "promptOnce").throws("Unexpected promptOnce call"); }); afterEach(() => { sandbox.verifyAndRestore(); }); - describe("createBackend", () => { + describe("onboardBackend", () => { const projectId = "projectId"; const location = "us-central1"; const backendId = "backendId"; + const op = { name: `projects/${projectId}/locations/${location}/backends/${backendId}`, done: true, }; + const completeBackend = { name: `projects/${projectId}/locations/${location}/backends/${backendId}`, labels: {}, @@ -45,21 +50,14 @@ describe("operationsConverter", () => { updateTime: "1", uri: "https://placeholder.com", }; - const setup = { - frameworks: { - region: location, - serviceName: backendId, - existingBackend: true, - deployMethod: "github", - branchName: "main", - }, - }; + const cloudBuildConnRepo = { name: `projects/${projectId}/locations/${location}/connections/framework-${location}/repositories/repoId`, remoteUri: "remoteUri", createTime: "0", updateTime: "1", }; + const backendInput: Omit = { servingLocality: "GLOBAL_ACCESS", codebase: { @@ -68,6 +66,7 @@ describe("operationsConverter", () => { }, labels: {}, }; + it("should createBackend", async () => { createBackendStub.resolves(op); pollOperationStub.resolves(completeBackend); @@ -77,27 +76,18 @@ describe("operationsConverter", () => { expect(createBackendStub).to.be.calledWith(projectId, location, backendInput); }); - it("should return a backend, if user wants use the exiting backend", async () => { - getBackendStub.resolves(completeBackend); - - const result = await getOrCreateBackend("projectId", setup); - - expect(result).to.deep.equal(completeBackend); - expect(getBackendStub.calledOnceWithExactly(projectId, location, backendId)).to.be.true; - }); - - it("should create a new backend, if backend doesn't exist", async () => { + it("should onboard a new backend", async () => { const newBackendId = "newBackendId"; const newPath = `projects/${projectId}/locations/${location}/backends/${newBackendId}`; - setup.frameworks.serviceName = newBackendId; op.name = newPath; completeBackend.name = newPath; getBackendStub.throws(new FirebaseError("error", { status: 404 })); linkGitHubRepositoryStub.resolves(cloudBuildConnRepo); createBackendStub.resolves(op); pollOperationStub.resolves(completeBackend); + promptOnce.resolves("main"); - const result = await getOrCreateBackend(projectId, setup); + const result = await onboardBackend(projectId, location, backendId); expect(result).to.deep.equal(completeBackend); expect(createBackendStub).to.be.calledWith(projectId, location, backendInput);