UNPKG

ask-cli-x

Version:

Alexa Skills Kit (ASK) Command Line Interfaces

222 lines (221 loc) 11.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCommand = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const abstract_command_1 = require("../abstract-command"); const option_model_json_1 = __importDefault(require("../option-model.json")); const cli_error_1 = __importDefault(require("../../exceptions/cli-error")); const cli_file_not_found_error_1 = __importDefault(require("../../exceptions/cli-file-not-found-error")); const cli_warn_1 = __importDefault(require("../../exceptions/cli-warn")); const resources_config_1 = __importDefault(require("../../model/resources-config")); const manifest_1 = __importDefault(require("../../model/manifest")); const constants_1 = __importDefault(require("../../utils/constants")); const profile_helper_1 = __importDefault(require("../../utils/profile-helper")); const string_utils_1 = __importDefault(require("../../utils/string-utils")); const messenger_1 = __importDefault(require("../../view/messenger")); const spinner_view_1 = __importDefault(require("../../view/spinner-view")); const ui_1 = __importDefault(require("./ui")); const helper_1 = __importDefault(require("./helper")); const ac_util_1 = require("../../utils/ac-util"); class DeployCommand extends abstract_command_1.AbstractCommand { name() { return "deploy"; } description() { return "deploy the skill project"; } requiredOptions() { return []; } optionalOptions() { return ["ignore-hash", "target", "profile", "debug"]; } async handle(cmd) { let profile; try { profile = profile_helper_1.default.runtimeProfile(cmd.profile); new resources_config_1.default(path_1.default.join(process.cwd(), constants_1.default.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)); messenger_1.default.getInstance().info(`Deploy configuration loaded from ${constants_1.default.FILE_PATH.ASK_RESOURCES_JSON_CONFIG}`); helper_1.default.confirmProfile(profile); this._filterAlexaHostedSkill(profile); this._initiateManifestModel(profile); } catch (err) { if (err instanceof cli_warn_1.default) { messenger_1.default.getInstance().warn(err.message); } else if (err instanceof cli_file_not_found_error_1.default) { messenger_1.default.getInstance().warn(err.message); } else if (err instanceof cli_error_1.default) { messenger_1.default.getInstance().error(err.message); } else { messenger_1.default.getInstance().error(err); } throw err; } const allowedTargets = Object.values(constants_1.default.DEPLOY_TARGET); if (cmd.target && !allowedTargets.includes(cmd.target)) { const errMessage = `Target ${cmd.target} is not supported. Supported targets: ${allowedTargets}.`; messenger_1.default.getInstance().error(errMessage); throw new cli_error_1.default(errMessage); } const options = { profile, doDebug: cmd.debug, ignoreHash: cmd.ignoreHash, target: cmd.target }; return new Promise((resolve, reject) => { ui_1.default.confirmDeploymentIfNeeded(profile, (err, confirmResult) => { if (err) { messenger_1.default.getInstance().error(err); return reject(err); } if (!confirmResult) { messenger_1.default.getInstance().info("Deployment cancelled."); return resolve(); } deployResources(options) .then(() => { const deploymentType = helper_1.default.getDeploymentType(profile); // Save the deployment type to ask states resources_config_1.default.getInstance().setSkillMetaLastDeployType(profile, deploymentType); // Write updates back to resources file resources_config_1.default.getInstance().write(); manifest_1.default.getInstance().write(); // Skipping enable logic if deploying with target flag // since we may don't have the endpoint if (cmd.target) { return resolve(); } // Post deploy logic // call smapiClient to enable skill helper_1.default.enableSkill(profile, cmd.debug, (enableError) => { if (enableError instanceof cli_warn_1.default) { messenger_1.default.getInstance().warn(enableError); return resolve(); } if (enableError) { messenger_1.default.getInstance().error(enableError); return reject(enableError); } return resolve(); }); }) .catch((err) => { messenger_1.default.getInstance().error(err); return reject(err); }); }); }); } _filterAlexaHostedSkill(profile) { const deployerType = resources_config_1.default.getInstance().getSkillInfraType(profile); if (deployerType === constants_1.default.DEPLOYER_TYPE.HOSTED.NAME) { throw new cli_warn_1.default("Alexa hosted skills can be deployed by performing a git push.\n" + "The master branch gets deployed to skill's development stage\n" + "The prod branch gets deployed to skill's live stage\n" + 'Please run "git push" at the proper branch to deploy hosted skill to your targeted stage.'); } } _initiateManifestModel(profile) { const skillPackageSrc = resources_config_1.default.getInstance().getSkillMetaSrc(profile); if (!string_utils_1.default.isNonBlankString(skillPackageSrc)) { throw new cli_error_1.default("Skill package src is not found in ask-resources.json."); } if (!fs_extra_1.default.existsSync(skillPackageSrc)) { throw new cli_error_1.default(`The skillMetadata src file ${skillPackageSrc} does not exist.`); } const manifestPath = path_1.default.join(skillPackageSrc, constants_1.default.FILE_PATH.SKILL_PACKAGE.MANIFEST); new manifest_1.default(manifestPath); } } exports.default = DeployCommand; /** * The deploy function used to deploy all skill related resources * This steps includes the deploy of skillMeta, skillCode and skillInfra using the deployDelegate plugin * @param {String} profile The profile name * @param {Boolean} doDebug The flag of debug or not * @param {Boolean} ignoreHash The flag to ignore difference between local and remote version * @param {Function} callback */ async function deployResources(options) { const { profile, doDebug, target, ignoreHash } = options; await _deploySkillMetadata(options); if (target && target !== constants_1.default.DEPLOY_TARGET.SKILL_INFRASTRUCTURE) { return; } if (!resources_config_1.default.getInstance().getSkillId(profile)) { const errorMessage = `Unable to deploy target ${target} when the skillId has not been created yet. ` + "Please deploy your skillMetadata first by running “ask deploy” command."; throw new cli_error_1.default(errorMessage); } // Skill Code const regionsList = resources_config_1.default.getInstance().getCodeRegions(profile); if (!regionsList || regionsList.length === 0) { return; } messenger_1.default.getInstance().info("\n==================== Build Skill Code ===================="); return new Promise((resolve, reject) => { helper_1.default.buildSkillCode(profile, doDebug, (buildErr, uniqueCodeList) => { if (buildErr) { return reject(buildErr); } messenger_1.default.getInstance().info("Skill code built successfully."); uniqueCodeList.forEach((codeProperty) => { const buildFilePath = codeProperty.build.file; messenger_1.default.getInstance().info(`Code for region ${codeProperty.regionsList.join("+")} built to ${buildFilePath} successfully \ with build flow ${codeProperty.buildFlow}.`); }); // Skill Infrastructure const infraType = resources_config_1.default.getInstance().getSkillInfraType(profile); if (!string_utils_1.default.isNonBlankString(infraType)) { return resolve(); } messenger_1.default.getInstance().info("\n==================== Deploy Skill Infrastructure ===================="); helper_1.default.deploySkillInfrastructure(profile, doDebug, ignoreHash, (infraErr) => { if (infraErr) { return reject(infraErr); } messenger_1.default.getInstance().info(`\nSkill infrastructures deployed successfully through ${infraType}.`); resolve(); }); }); }); } async function _deploySkillMetadata(options) { const { profile, target } = options; if (target && target !== constants_1.default.DEPLOY_TARGET.SKILL_METADATA) { return; } // Skill Metadata messenger_1.default.getInstance().info("==================== Deploy Skill Metadata ===================="); const skillMetaSpinner = new spinner_view_1.default(); const acMsg = "Uploading the entire skill package and building the models. For Alexa Conversations it can take 20-60 minutes..."; const imMsg = "Uploading the entire skill package and building the models. Normally it takes a few minutes..."; const startMsg = (0, ac_util_1.isAcSkill)(profile) ? acMsg : imMsg; skillMetaSpinner.start(startMsg); return new Promise((resolve, reject) => { helper_1.default.deploySkillMetadata(options, skillMetaSpinner, (metaErr) => { skillMetaSpinner.terminate(); if (metaErr && metaErr !== "The hash of current skill package folder does not change compared to the last deploy hash result, " + "CLI will skip the deploy of skill package.") { return reject(metaErr); } if (metaErr) { // this case is the warning message of the same hash skip, deploy will continue messenger_1.default.getInstance().warn(metaErr); } else { resources_config_1.default.getInstance().write(); messenger_1.default.getInstance().info("Skill package deployed and all models built successfully."); } messenger_1.default.getInstance().info(`Skill ID: ${resources_config_1.default.getInstance().getSkillId(profile)}`); return resolve(); }); }); } exports.createCommand = new DeployCommand(option_model_json_1.default).createCommand();