firebase-tools
Version:
Command-Line Interface for Firebase
109 lines (108 loc) • 5.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.command = void 0;
const clc = require("colorette");
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
const command_1 = require("../command");
const projectUtils_1 = require("../projectUtils");
const experiments = require("../experiments");
const extensionsHelper_1 = require("../extensions/extensionsHelper");
const requirePermissions_1 = require("../requirePermissions");
const requireConfig_1 = require("../requireConfig");
const migrate_1 = require("../extensions/migrate");
const export_1 = require("../extensions/export");
const install_1 = require("../functions/kits/install");
const kits_1 = require("../functions/kits");
const utils_1 = require("../utils");
const error_1 = require("../error");
const deploy_1 = require("../deploy");
const checkIam_1 = require("../deploy/functions/checkIam");
const prompt_1 = require("../prompt");
exports.command = new command_1.Command("ext:migrate")
.description("migrate an extension instance to a function kit")
.option("-p, --package <package>", "optional kit package override to use")
.option("--ext-instance <instanceId>", "extension instance ID to migrate")
.option("-e, --extension <extensionRef>", "extension reference or name to migrate")
.option("-f, --force", "force update and migration without prompting")
.before(() => {
experiments.assertEnabled("extMigrationFeatures", "migrate an extension instance to a function kit");
experiments.assertEnabled("kits", "migrate an extension instance to a function kit");
experiments.assertEnabled("secretEnvParams", "migrate an extension instance to a function kit");
})
.before(requireConfig_1.requireConfig)
.before(requirePermissions_1.requirePermissions, [
"firebaseextensions.instances.list",
"firebaseextensions.instances.delete",
...deploy_1.TARGET_PERMISSIONS["functions"],
])
.before(extensionsHelper_1.ensureExtensionsApiEnabled)
.before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
.before((options) => {
const projectId = (0, projectUtils_1.needProjectId)(options);
return (0, checkIam_1.checkServiceAccountIam)(projectId);
})
.action(async (options) => {
const projectId = (0, projectUtils_1.needProjectId)(options);
if (options.package) {
(0, kits_1.validateNpmPackageName)(options.package);
}
const plan = await (0, migrate_1.createMigrationPlan)(projectId, {
package: options.package,
extInstance: options.extInstance,
extension: options.extension,
nonInteractive: options.nonInteractive,
force: options.force,
});
(0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `Selected instance ${clc.bold(plan.instanceId)} (${plan.kitPackage}) for migration.`);
plan.instance = await (0, extensionsHelper_1.ensureInstanceSpec)(plan.instance);
if (!plan.instance.config?.source?.spec) {
throw new error_1.FirebaseError(`Could not load extension specification for ${clc.bold(plan.instanceId)}. Unable to export configuration.`);
}
plan.instance = await (0, migrate_1.ensureInstanceUpToDate)(projectId, plan.instance, options);
if (plan.instance.state !== "ACTIVE") {
(0, utils_1.logLabeledWarning)(extensionsHelper_1.logPrefix, `Extension instance ${clc.bold(plan.instanceId)} is in state ${plan.instance.state}. Migration may not function as expected.`);
}
const exportedEnvs = (0, export_1.functionsEnvFromInstance)(plan.instance);
await (0, migrate_1.migrateSecrets)(plan.instance, { force: options.force });
(0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `Installing kit ${clc.bold(plan.kitPackage)} for instance ${clc.bold(plan.instanceId)}...`);
const installResult = await (0, install_1.installKitOrInstance)({
...options,
config: options.config,
package: plan.kitPackage,
template: "migration",
defaultInstanceId: plan.instanceId,
seedEnv: {
projectId,
envs: exportedEnvs,
},
});
const kitInstanceId = installResult.instanceId;
if (!kitInstanceId) {
throw new error_1.FirebaseError("Kit installation failed: no instance ID returned.", { exit: 1 });
}
(0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `Deploying functions kit instance ${clc.bold(kitInstanceId)}...`);
const deployOptions = {
...options,
only: `functions:${kitInstanceId}`,
filteredTargets: ["functions"],
project: projectId,
};
try {
await (0, deploy_1.deploy)(["functions"], deployOptions);
}
catch (err) {
throw new error_1.FirebaseError(`Failed to deploy. Please fix and retry with firebase deploy --only functions:${kitInstanceId}. After success you may remove the old extension with firebase ext:uninstall ${plan.instanceId} --project ${projectId} --immediate`, { original: err instanceof Error ? err : undefined, exit: 1 });
}
const shouldUninstall = await (0, prompt_1.confirm)({
message: `Functions kit ${kitInstanceId} successfully deployed. After checking function logs to verify that your backend is performing correctly, you should uninstall extension instance ${plan.instanceId}. It can take a few minutes for Eventarc to fully provision and new kits to react to events. Uninstall it now?`,
default: false,
nonInteractive: options.nonInteractive,
force: options.force,
});
if (!shouldUninstall) {
(0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `You may safely uninstall extension instance ${clc.bold(plan.instanceId)} in the future with the command ${clc.bold(`firebase ext:uninstall ${plan.instanceId} --project ${projectId} --immediate`)}`);
return plan;
}
await (0, migrate_1.uninstallExtension)(projectId, plan.instanceId, options, true);
return plan;
});