UNPKG

@metacall/deploy

Version:

Tool for deploying into MetaCall FaaS platform.

152 lines (151 loc) 8.16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deployFromRepository = exports.deployPackage = exports.ErrorCode = void 0; const package_1 = require("@metacall/protocol/package"); const protocol_1 = require("@metacall/protocol/protocol"); const fs_1 = require("fs"); const path_1 = require("path"); const args_1 = __importDefault(require("./cli/args")); const inputs_1 = require("./cli/inputs"); const messages_1 = require("./cli/messages"); const progress_1 = __importDefault(require("./cli/progress")); const selection_1 = require("./cli/selection"); const logs_1 = require("./logs"); const tty_1 = require("./tty"); const utils_1 = require("./utils"); var ErrorCode; (function (ErrorCode) { ErrorCode[ErrorCode["Ok"] = 0] = "Ok"; ErrorCode[ErrorCode["NotDirectoryRootPath"] = 1] = "NotDirectoryRootPath"; ErrorCode[ErrorCode["EmptyRootPath"] = 2] = "EmptyRootPath"; ErrorCode[ErrorCode["NotFoundRootPath"] = 3] = "NotFoundRootPath"; ErrorCode[ErrorCode["AccountDisabled"] = 4] = "AccountDisabled"; ErrorCode[ErrorCode["DeployPackageFailed"] = 5] = "DeployPackageFailed"; ErrorCode[ErrorCode["DeployRepositoryFailed"] = 6] = "DeployRepositoryFailed"; })(ErrorCode = exports.ErrorCode || (exports.ErrorCode = {})); const deployPackage = async (rootPath, api, plan) => { try { const name = args_1.default['projectName'].toLowerCase(); let descriptor = await (0, package_1.generatePackage)(rootPath); const deploy = async (additionalJsons) => { // TODO: We should cache the plan and ask for it only once const descriptor = await (0, package_1.generatePackage)(rootPath); const { progress, pulse, hide } = (0, progress_1.default)(); const archive = await (0, utils_1.zip)(rootPath, descriptor.files, progress, pulse, hide); // TODO: We should do something with the return value, for example // check for error or show the output to the user await api.upload(name, archive, additionalJsons, descriptor.runners); // TODO: We can ask for environment variables here too and cache them const env = await (0, utils_1.getEnv)(rootPath); (0, messages_1.info)(`Deploying ${rootPath}...\n`); try { const deploy = await api.deploy(name, env, plan, protocol_1.ResourceType.Package); if ((0, tty_1.isInteractive)()) { // TODO: Need a TUI for logs await (0, logs_1.logs)(descriptor.runners, name, args_1.default['dev']); } if (deploy) { (0, messages_1.info)('Repository deployed, Use command $ metacall-deploy --inspect, to know more about deployment'); } } catch (err) { (0, messages_1.apiError)(err); } }; const createJsonAndDeploy = async (saveConsent) => { let languages = []; let packages = []; let wait = true; do { const potentialPackages = (0, package_1.generateJsonsFromFiles)(descriptor.files); const potentialLanguages = Array.from(new Set(potentialPackages.reduce((langs, pkg) => [...langs, pkg.language_id], []))); languages = await (0, selection_1.languageSelection)(potentialLanguages); if (languages.length == 0) { (0, messages_1.warn)('You must choose a language in order to proceed with the deployment procedure, do not continue without doing so.'); wait = false; continue; } packages = potentialPackages.filter(pkg => languages.includes(pkg.language_id)); await (0, utils_1.loadFilesToRun)(packages); const langId = []; for (const pkg of packages) { pkg.scripts.length === 0 && langId.push(pkg.language_id); } if (!langId.length) break; if (langId.length === packages.length) { (0, messages_1.warn)('You must choose a file to continue the deployment procedure, do not continue without doing so.'); wait = false; continue; } const deployConsent = (await (0, inputs_1.input)(`You selected language${langId.length > 1 ? 's' : ''} ${langId .map(el => (0, messages_1.printLanguage)(el)) .join(', ')} but you didn't select any file, do you want to continue? (Y/N):`)).toUpperCase(); wait = deployConsent === 'Y' || deployConsent === 'YES'; } while (!wait); const cacheJsons = saveConsent === 'Y' || saveConsent === 'YES'; const additionalPackages = cacheJsons ? await (async () => { for (const pkg of packages) { if (pkg.scripts.length === 0) continue; await fs_1.promises.writeFile((0, path_1.join)(rootPath, `metacall-${pkg.language_id}.json`), JSON.stringify(pkg, null, 2)); } // If they are cached, genearte the descriptor again descriptor = await (0, package_1.generatePackage)(rootPath); // The descriptor already contains the packages so // there is no need to send additional packages return []; })() : packages; // Otherwise, packages are not cached, send them await deploy(additionalPackages); }; switch (descriptor.error) { case package_1.PackageError.None: { await deploy([]); break; } case package_1.PackageError.Empty: { return (0, messages_1.error)(`The directory you specified (${rootPath}) is empty.`, ErrorCode.EmptyRootPath); } case package_1.PackageError.JsonNotFound: { (0, messages_1.warn)(`No metacall.json was found in ${rootPath}, launching the wizard...`); const askToCachePackagesFile = () => (0, inputs_1.input)('Do you want to save metacall.json file? (Y/N):'); await createJsonAndDeploy((await askToCachePackagesFile()).toUpperCase()); break; } } } catch (e) { (0, messages_1.error)(String(e), ErrorCode.DeployPackageFailed); } }; exports.deployPackage = deployPackage; const deployFromRepository = async (api, plan, url) => { try { const { branches } = await api.branchList(url); if (!branches.length) return (0, messages_1.error)('Invalid Repository URL'); // TODO: API response type should be created in protocol, it is string as of now const selectedBranch = branches.length === 1 ? branches[0] : await (0, selection_1.listSelection)(branches, 'Select branch:'); if (branches.length === 1) (0, messages_1.info)(`Only one branch found : ${selectedBranch}, Selecting it automatically.`); const runners = Array.from((0, package_1.findRunners)(await api.fileList(url, selectedBranch))); const name = (await api.add(url, selectedBranch, [])).id; const env = await (0, utils_1.getEnv)(); const deploy = await api.deploy(name, env, plan, protocol_1.ResourceType.Repository); (0, messages_1.info)('Deploying...'); await (0, logs_1.logs)(runners, deploy.suffix, args_1.default['dev']); if (deploy) (0, messages_1.info)('Repository deployed, Use command $ metacall-deploy --inspect, to know more about deployment'); } catch (e) { (0, messages_1.error)(String(e), ErrorCode.DeployRepositoryFailed); } }; exports.deployFromRepository = deployFromRepository;