esa-cli
Version:
A CLI for operating Alibaba Cloud ESA EdgeRoutine (Edge Functions).
220 lines (219 loc) • 10.8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import chalk from 'chalk';
import { getProjectConfig, readEdgeRoutineFile } from '../../utils/fileUtils/index.js';
import SelectItems from '../../components/selectInput.js';
import { Environment, PublishType } from '../../libs/interface.js';
import logger from '../../libs/logger.js';
import { checkDirectory, checkIsLoginSuccess, getRoutineVersionList } from '../utils.js';
import { displayMultiSelectTable } from '../../components/mutiSelectTable.js';
import { Base64 } from 'js-base64';
import { ApiService } from '../../libs/apiService.js';
import { createAndDeployVersion, displaySelectDeployType, promptSelectVersion, yesNoPromptAndExecute } from './helper.js';
import t from '../../i18n/index.js';
import prodBuild from '../commit/prodBuild.js';
import { exit } from 'process';
import path from 'path';
import { checkRoutineExist } from '../../utils/checkIsRoutineCreated.js';
import moment from 'moment';
const deploy = {
command: 'deploy [entry]',
builder: (yargs) => {
return yargs
.positional('entry', {
describe: t('dev_entry_describe').d('Entry file of the Routine'),
type: 'string',
demandOption: false
})
.option('quick', {
alias: 'q',
type: 'boolean'
});
},
describe: `🚀 ${t('deploy_describe').d('Deploy your project')}`,
handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
handleDeploy(argv);
})
};
export default deploy;
export function quickDeploy(entry, projectConfig) {
return __awaiter(this, void 0, void 0, function* () {
const server = yield ApiService.getInstance();
const entryFile = path.resolve(entry !== null && entry !== void 0 ? entry : '', 'src/index.js');
yield prodBuild(false, entryFile, entry);
const code = readEdgeRoutineFile(entry) || '';
const res = yield server.quickDeployRoutine({
name: projectConfig.name,
code: code
});
if (res) {
logger.success(t('quick_deploy_success').d('Your code has been successfully deployed'));
logger.log(`👉 ${t('quick_deploy_success_guide').d('Run this command to add domains')}: ${chalk.green('esa domain add <DOMAIN>')}`);
}
else {
logger.error(t('quick_deploy_failed').d('Quick deploy failed'));
process.exit(0);
}
});
}
export function handleDeploy(argv) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
if (!checkDirectory()) {
return;
}
const projectConfig = getProjectConfig();
if (!projectConfig)
return logger.notInProject();
const isSuccess = yield checkIsLoginSuccess();
if (!isSuccess)
return;
const server = yield ApiService.getInstance();
const entry = argv.entry;
yield checkRoutineExist(projectConfig.name, entry);
const req = { Name: projectConfig.name };
const routineDetail = yield server.getRoutine(req, false);
const versionList = ((_a = routineDetail === null || routineDetail === void 0 ? void 0 : routineDetail.data) === null || _a === void 0 ? void 0 : _a.CodeVersions) || [];
const customEntry = argv.entry;
const stagingVersion = (_c = (_b = routineDetail === null || routineDetail === void 0 ? void 0 : routineDetail.data) === null || _b === void 0 ? void 0 : _b.Envs[1]) === null || _c === void 0 ? void 0 : _c.CodeVersion;
const productionVersion = (_e = (_d = routineDetail === null || routineDetail === void 0 ? void 0 : routineDetail.data) === null || _d === void 0 ? void 0 : _d.Envs[0]) === null || _e === void 0 ? void 0 : _e.CodeVersion;
if (argv.quick) {
yield quickDeploy(customEntry, projectConfig);
exit(0);
}
if (versionList.length === 0) {
logger.log(t('no_formal_version_found').d('No formal version found, you need to create a version first.'));
yield handleOnlyUnstableVersionFound(projectConfig, customEntry);
}
else {
yield displayVersionList(versionList, stagingVersion, productionVersion);
logger.log(chalk.bold(`${t('deploy_version_select').d('Select the version you want to publish')}:`));
const selectedVersion = yield promptSelectVersion(versionList);
const selectedType = yield displaySelectDeployType();
yield deploySelectedCodeVersion(projectConfig.name, selectedType, selectedVersion);
}
});
}
export function displaySelectSpec(specList) {
return __awaiter(this, void 0, void 0, function* () {
logger.log(`📃 ${t('deploy_spec_select').d('Please select the spec of the routine you want to create')}`);
const selectItems = specList.map((spec) => {
return { label: spec, value: spec };
});
return new Promise((resolve) => {
const handleSelection = (item) => __awaiter(this, void 0, void 0, function* () {
resolve(item.value);
});
SelectItems({ items: selectItems, handleSelect: handleSelection });
});
});
}
function handleNoVersionsFound(projectConfig, customEntry) {
return __awaiter(this, void 0, void 0, function* () {
logger.log(`😄 ${t('deploy_first_time').d("This is first time to deploy. Let's create a version first!")}`);
const created = yield yesNoPromptAndExecute(`📃 ${t('deploy_create_formal_version_ques').d('Do you want to create an unstable version now?')}`, () => createAndDeployVersion(projectConfig, true));
if (created) {
yield handleOnlyUnstableVersionFound(projectConfig);
}
});
}
function promptAndDeployVersion(projectConfig) {
return __awaiter(this, void 0, void 0, function* () {
const versionList = yield getRoutineVersionList(projectConfig.name);
yield displayVersionList(versionList);
logger.log(`📃 ${t('deploy_select_version').d("Select which version you'd like to deploy")}`);
const selectedVersion = yield promptSelectVersion(versionList);
const selectedType = yield displaySelectDeployType();
yield deploySelectedCodeVersion(projectConfig.name, selectedType, selectedVersion);
});
}
const specialAreaTransfer = (canaryAreaSelectList) => {
return canaryAreaSelectList.map((item) => {
if (item.label === 'HongKong') {
return { label: 'HongKong(China)' };
}
if (item.label === 'Macau') {
return { label: 'Macau(China)' };
}
if (item.label === 'Taiwan') {
return { label: 'Taiwan(China)' };
}
return { label: item.label };
});
};
export function handleOnlyUnstableVersionFound(projectConfig, customEntry) {
return __awaiter(this, void 0, void 0, function* () {
const created = yield yesNoPromptAndExecute(`📃 ${t('deploy_create_formal_version_ques').d('Do you want to create a formal version to deploy on production environment?')}`, () => createAndDeployVersion(projectConfig));
if (created) {
yield promptAndDeployVersion(projectConfig);
}
});
}
export function deploySelectedCodeVersion(name, selectedType, version) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
const server = yield ApiService.getInstance();
const param = {
Name: name,
Env: selectedType === PublishType.Staging
? Environment.Staging
: Environment.Production
};
if (selectedType === PublishType.Canary) {
const res = yield server.listRoutineCanaryAreas();
const canaryList = (_a = res === null || res === void 0 ? void 0 : res.CanaryAreas) !== null && _a !== void 0 ? _a : [];
logger.log(`📃 ${t('deploy_select_canary').d('Please select the canary area(s) you want to deploy to')}`);
const canaryAreaSelectList = canaryList.map((area) => {
return { label: area };
});
const selectedCanaryList = yield displayMultiSelectTable(specialAreaTransfer(canaryAreaSelectList));
param.CanaryAreaList = selectedCanaryList;
param.CanaryCodeVersion = version;
}
else {
param.CodeVersion = version;
}
try {
const res = yield server.publishRoutineCodeVersion(param);
if (res) {
logger.success(t('deploy_success').d('Your code has been successfully deployed'));
logger.log(`👉 ${t('deploy_success_guide').d('Run this command to add domains')}: ${chalk.green('esa domain add <DOMAIN>')}`);
}
}
catch (e) {
console.error(e);
}
});
}
export function displayVersionList(versionList_1) {
return __awaiter(this, arguments, void 0, function* (versionList, stagingVersion = 'unstable', productionVersion = 'unstable') {
logger.log(`${chalk.bgYellow('Active')} ${t('deploy_env_staging').d('Staging')}`);
logger.log(`${chalk.bgGreen('Active')} ${t('deploy_env_production').d('Production')}`);
const data = [];
for (let i = 0; i < versionList.length; i++) {
const version = versionList[i];
const createTime = moment(version.CreateTime).format('YYYY/MM/DD HH:mm:ss');
const tags = [
version.CodeVersion === stagingVersion ? chalk.bgYellow('Active') : '',
version.CodeVersion === productionVersion ? chalk.bgGreen('Active') : ''
];
data.push([
`${version.CodeVersion} ${tags.join(' ')}`,
createTime,
Base64.decode(version.CodeDescription)
]);
}
logger.table([
t('deploy_table_header_version').d('Version'),
t('deploy_table_header_created').d('Created'),
t('deploy_table_header_description').d('Description')
], data, [30, 25, 15]);
});
}