firebase-tools 13.7.4 → 13.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/apphosting/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promptLocation = exports.deleteBackendAndPoll = exports.orchestrateRollout = exports.setDefaultTrafficPolicy = exports.createBackend = exports.doSetup = void 0;
|
|
3
|
+
exports.promptLocation = exports.deleteBackendAndPoll = exports.orchestrateRollout = exports.setDefaultTrafficPolicy = exports.createBackend = exports.ensureAppHostingComputeServiceAccount = exports.doSetup = void 0;
|
|
4
4
|
const repo = require("./repo");
|
|
5
5
|
const poller = require("../operation-poller");
|
|
6
6
|
const apphosting = require("../gcp/apphosting");
|
|
@@ -30,14 +30,16 @@ async function doSetup(projectId, webAppName, location, serviceAccount, withDevC
|
|
|
30
30
|
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.secretManagerOrigin)(), "apphosting", true),
|
|
31
31
|
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudRunApiOrigin)(), "apphosting", true),
|
|
32
32
|
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "apphosting", true),
|
|
33
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.iamOrigin)(), "apphosting", true),
|
|
33
34
|
]);
|
|
35
|
+
(0, utils_1.logBullet)("First we need a few details to create your backend.\n");
|
|
36
|
+
await ensureAppHostingComputeServiceAccount(projectId, serviceAccount);
|
|
34
37
|
const allowedLocations = (await apphosting.listLocations(projectId)).map((loc) => loc.locationId);
|
|
35
38
|
if (location) {
|
|
36
39
|
if (!allowedLocations.includes(location)) {
|
|
37
40
|
throw new error_1.FirebaseError(`Invalid location ${location}. Valid choices are ${allowedLocations.join(", ")}`);
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
|
-
(0, utils_1.logBullet)("First we need a few details to create your backend.\n");
|
|
41
43
|
location =
|
|
42
44
|
location || (await promptLocation(projectId, "Select a location to host your backend:\n"));
|
|
43
45
|
(0, utils_1.logSuccess)(`Location set to ${location}.\n`);
|
|
@@ -93,6 +95,25 @@ async function doSetup(projectId, webAppName, location, serviceAccount, withDevC
|
|
|
93
95
|
(0, utils_1.logSuccess)(`Your backend is now deployed at:\n\thttps://${backend.uri}`);
|
|
94
96
|
}
|
|
95
97
|
exports.doSetup = doSetup;
|
|
98
|
+
async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount) {
|
|
99
|
+
const sa = serviceAccount || defaultComputeServiceAccountEmail(projectId);
|
|
100
|
+
const name = `projects/${projectId}/serviceAccounts/${sa}`;
|
|
101
|
+
try {
|
|
102
|
+
await iam.testResourceIamPermissions((0, api_1.iamOrigin)(), "v1", name, ["iam.serviceAccounts.actAs"], `projects/${projectId}`);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (!(err instanceof error_1.FirebaseError)) {
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
if (err.status === 404) {
|
|
109
|
+
await provisionDefaultComputeServiceAccount(projectId);
|
|
110
|
+
}
|
|
111
|
+
else if (err.status === 403) {
|
|
112
|
+
throw new error_1.FirebaseError(`Failed to create backend due to missing delegation permissions for ${sa}. Make sure you have the iam.serviceAccounts.actAs permission.`, { original: err });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.ensureAppHostingComputeServiceAccount = ensureAppHostingComputeServiceAccount;
|
|
96
117
|
async function promptNewBackendId(projectId, location, prompt) {
|
|
97
118
|
while (true) {
|
|
98
119
|
const backendId = await (0, prompt_1.promptOnce)(prompt);
|
|
@@ -127,33 +148,23 @@ async function createBackend(projectId, location, backendId, repository, service
|
|
|
127
148
|
const op = await apphosting.createBackend(projectId, location, backendReqBody, backendId);
|
|
128
149
|
return await poller.pollOperation(Object.assign(Object.assign({}, apphostingPollerOptions), { pollerName: `create-${projectId}-${location}-${backendId}`, operationResourceName: op.name }));
|
|
129
150
|
}
|
|
130
|
-
|
|
131
|
-
return await createBackendAndPoll();
|
|
132
|
-
}
|
|
133
|
-
catch (err) {
|
|
134
|
-
if (err.status === 403) {
|
|
135
|
-
if (err.message.includes(defaultServiceAccount)) {
|
|
136
|
-
await provisionDefaultComputeServiceAccount(projectId);
|
|
137
|
-
return await createBackendAndPoll();
|
|
138
|
-
}
|
|
139
|
-
else if (serviceAccount && err.message.includes(serviceAccount)) {
|
|
140
|
-
throw new error_1.FirebaseError(`Failed to create backend due to missing delegation permissions for ${serviceAccount}. Make sure you have the iam.serviceAccounts.actAs permission.`, { children: [err] });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
throw err;
|
|
144
|
-
}
|
|
151
|
+
return await createBackendAndPoll();
|
|
145
152
|
}
|
|
146
153
|
exports.createBackend = createBackend;
|
|
147
154
|
async function provisionDefaultComputeServiceAccount(projectId) {
|
|
148
155
|
try {
|
|
149
|
-
await iam.createServiceAccount(projectId, DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME, "
|
|
156
|
+
await iam.createServiceAccount(projectId, DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME, "Default service account used to run builds and deploys for Firebase App Hosting", "Firebase App Hosting compute service account");
|
|
150
157
|
}
|
|
151
158
|
catch (err) {
|
|
152
159
|
if (err.status !== 409) {
|
|
153
160
|
throw err;
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
|
-
await (0, resourceManager_1.addServiceAccountToRoles)(projectId, defaultComputeServiceAccountEmail(projectId), [
|
|
163
|
+
await (0, resourceManager_1.addServiceAccountToRoles)(projectId, defaultComputeServiceAccountEmail(projectId), [
|
|
164
|
+
"roles/firebaseapphosting.computeRunner",
|
|
165
|
+
"roles/firebase.sdkAdminServiceAgent",
|
|
166
|
+
"roles/developerconnect.tokenAccessor",
|
|
167
|
+
], true);
|
|
157
168
|
}
|
|
158
169
|
async function setDefaultTrafficPolicy(projectId, location, backendId, codebaseBranch) {
|
|
159
170
|
const traffic = {
|
|
@@ -171,8 +182,12 @@ async function setDefaultTrafficPolicy(projectId, location, backendId, codebaseB
|
|
|
171
182
|
await poller.pollOperation(Object.assign(Object.assign({}, apphostingPollerOptions), { pollerName: `updateTraffic-${projectId}-${location}-${backendId}`, operationResourceName: op.name }));
|
|
172
183
|
}
|
|
173
184
|
exports.setDefaultTrafficPolicy = setDefaultTrafficPolicy;
|
|
185
|
+
function delay(ms) {
|
|
186
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
187
|
+
}
|
|
174
188
|
async function orchestrateRollout(projectId, location, backendId, buildInput) {
|
|
175
189
|
(0, utils_1.logBullet)("Starting a new rollout... this may take a few minutes.");
|
|
190
|
+
await delay(45 * 1000);
|
|
176
191
|
const buildId = await apphosting.getNextRolloutId(projectId, location, backendId, 1);
|
|
177
192
|
const buildOp = await apphosting.createBuild(projectId, location, backendId, buildId, buildInput);
|
|
178
193
|
const rolloutBody = {
|
|
@@ -11,7 +11,7 @@ exports.command = new command_1.Command("apphosting:backends:create")
|
|
|
11
11
|
.option("-a, --app <webApp>", "specify an existing Firebase web app to associate your App Hosting backend with")
|
|
12
12
|
.option("-l, --location <location>", "specify the location of the backend", "")
|
|
13
13
|
.option("-s, --service-account <serviceAccount>", "specify the service account used to run the server", "")
|
|
14
|
-
.option("-w, --with-dev-connect", "use the Developer Connect flow
|
|
14
|
+
.option("-w, --with-dev-connect", "use the Developer Connect flow instead of Cloud Build Repositories (testing)", true)
|
|
15
15
|
.before(apphosting_2.ensureApiEnabled)
|
|
16
16
|
.before(requireInteractive_1.default)
|
|
17
17
|
.action(async (options) => {
|