Skip to content

Commit

Permalink
feat: move states data from ask-resources.json configuration to .ask/…
Browse files Browse the repository at this point in the history
  • Loading branch information
RonWang committed Mar 27, 2020
1 parent f50184a commit 45d550e
Show file tree
Hide file tree
Showing 49 changed files with 1,184 additions and 665 deletions.
22 changes: 11 additions & 11 deletions lib/commands/deploy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ const fs = require('fs-extra');
const path = require('path');

const { AbstractCommand } = require('@src/commands/abstract-command');
const ResourcesConfig = require('@src/model/resources-config');
const Manifest = require('@src/model/manifest');
const Messenger = require('@src/view/messenger');
const SpinnerView = require('@src/view/spinner-view');
const optionModel = require('@src/commands/option-model');
const profileHelper = require('@src/utils/profile-helper');
const stringUtils = require('@src/utils/string-utils');
const CONSTANTS = require('@src/utils/constants');
const CliError = require('@src/exceptions/cli-error');
const CliFileNotFoundError = require('@src/exceptions/cli-file-not-found-error');
const CliWarn = require('@src/exceptions/cli-warn');
const ResourcesConfig = require('@src/model/resources-config');
const Manifest = require('@src/model/manifest');
const CONSTANTS = require('@src/utils/constants');
const profileHelper = require('@src/utils/profile-helper');
const stringUtils = require('@src/utils/string-utils');
const Messenger = require('@src/view/messenger');
const SpinnerView = require('@src/view/spinner-view');

const helper = require('./helper');

class DeployCommand extends AbstractCommand {
Expand Down Expand Up @@ -73,10 +74,6 @@ class DeployCommand extends AbstractCommand {

_filterAlexaHostedSkill(profile) {
const deployerType = ResourcesConfig.getInstance().getSkillInfraType(profile);
const rootPath = process.cwd();
if (!fs.existsSync(path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_PACKAGE.PACKAGE))) {
throw new CliError('The skill-package does not exist. This skill cannot be deployed.');
}
if (deployerType === CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) {
throw new CliWarn('Alexa hosted skills can be deployed by performing a git push.\n'
+ 'The master branch gets deployed to skill\'s development stage\n'
Expand All @@ -90,6 +87,9 @@ class DeployCommand extends AbstractCommand {
if (!stringUtils.isNonBlankString(skillPackageSrc)) {
throw new CliError('Skill package src is not found in ask-resources.json.');
}
if (!fs.existsSync(skillPackageSrc)) {
throw new CliError(`The skillMetadata src file ${skillPackageSrc} does not exist.`);
}
const manifestPath = path.join(skillPackageSrc, CONSTANTS.FILE_PATH.SKILL_PACKAGE.MANIFEST);
new Manifest(manifestPath);
}
Expand Down
32 changes: 25 additions & 7 deletions lib/commands/init/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const path = require('path');
const R = require('ramda');

const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller');
const AskResources = require('@src/model/resources-config/ask-resources');
const AskStates = require('@src/model/resources-config/ask-states');
const ResourcesConfig = require('@src/model/resources-config');
const CONSTANTS = require('@src/utils/constants');
const Messenger = require('@src/view/messenger');
Expand Down Expand Up @@ -117,8 +119,8 @@ function getSkillInfraUserInput(callback) {
* @param {Function} callback (err)
*/
function previewAndWriteAskResources(rootPath, userInput, profile, callback) {
const askResources = _assembleAskResources(userInput, profile);
ui.showPreviewAndConfirm(rootPath, askResources, (confirmErr, isConfirmed) => {
const { askResources, askStates } = _assembleAskResources(userInput, profile);
ui.showPreviewAndConfirm(rootPath, { askResources, askStates }, (confirmErr, isConfirmed) => {
if (confirmErr) {
return callback(confirmErr);
}
Expand All @@ -127,7 +129,12 @@ function previewAndWriteAskResources(rootPath, userInput, profile, callback) {
}
try {
const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG);
fs.writeJSONSync(askResourcesFilePath, askResources, { spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT });
const askHiddenFolder = path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER);
const askStatesFilePath = path.join(askHiddenFolder, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG);
fs.removeSync(askResourcesFilePath);
AskResources.withContent(askResourcesFilePath, askResources);
fs.removeSync(askHiddenFolder);
AskStates.withContent(askStatesFilePath, askStates);
} catch (writeErr) {
return callback(writeErr);
}
Expand All @@ -136,14 +143,25 @@ function previewAndWriteAskResources(rootPath, userInput, profile, callback) {
}

function _assembleAskResources(userInput, profile) {
const askResourcesJson = R.clone(ResourcesConfig.BASE);
const profileResources = {
skillId: userInput.skillId,
const askResourcesJson = R.clone(AskResources.BASE);
const askStatesJson = R.clone(AskStates.BASE);
const askProfileResources = {
skillMetadata: userInput.skillMeta,
code: userInput.skillCode,
skillInfrastructure: userInput.skillInfra
};
return R.set(R.lensPath(['profiles', profile]), profileResources, askResourcesJson);
const askProfileStates = {
skillId: userInput.skillId,
skillInfrastructure: {
[userInput.skillInfra.type]: {
deployState: {}
}
}
};
return {
askResources: R.set(R.lensPath(['profiles', profile]), askProfileResources, askResourcesJson),
askStates: R.set(R.lensPath(['profiles', profile]), askProfileStates, askStatesJson)
};
}

/**
Expand Down
11 changes: 8 additions & 3 deletions lib/commands/init/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,15 @@ function getSkillInfra(callback) {
});
}

function showPreviewAndConfirm(rootPath, askResources, callback) {
function showPreviewAndConfirm(rootPath, resourcesConfig, callback) {
const { askResources, askStates } = resourcesConfig;
Messenger.getInstance().info(`
Writing to ${path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)}:
${JsonView.toString(askResources)}\n`);
Writing to ${path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG)}:
${JsonView.toString(askResources)}
Writing to ${path.join(rootPath, CONSTANTS.FILE_PATH.HIDDEN_ASK_FOLDER, CONSTANTS.FILE_PATH.ASK_STATES_JSON_CONFIG)}:
${JsonView.toString(askStates)}
`);
inquirer.prompt([{
message: 'Does this look correct? ',
type: 'confirm',
Expand Down
7 changes: 3 additions & 4 deletions lib/commands/util/upgrade-project/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ const fs = require('fs-extra');
const path = require('path');
const R = require('ramda');


const SkillMetadataController = require('@src/controllers/skill-metadata-controller');
const awsUtil = require('@src/clients/aws-client/aws-util');
const CliError = require('@src/exceptions/cli-error');
const ResourcesConfig = require('@src/model/resources-config');
const AskResources = require('@src/model/resources-config/ask-resources');
const Messenger = require('@src/view/messenger');
const CONSTANTS = require('@src/utils/constants');
const stringUtils = require('@src/utils/string-utils');
Expand Down Expand Up @@ -162,7 +162,7 @@ function createV2ProjectSkeleton(rootPath, skillId, profile) {
const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA);
fs.ensureDirSync(skillCodePath);
// prepare ask-resources config
const askResourcesJson = R.clone(ResourcesConfig.BASE);
const askResourcesJson = R.clone(AskResources.BASE);
askResourcesJson.profiles[profile] = {
skillId,
skillMetadata: {},
Expand Down Expand Up @@ -230,8 +230,7 @@ function handleExistingLambdaCode(rootPath, lambdaResourcesMap, profile) {
const v2CodePath = path.join(rootPath, v2CodeUri);
fs.copySync(v1CodePath, v2CodePath);
// 3.2 update skill code setting
const regionalCode = { src: path.relative(rootPath, v2CodePath) };
ResourcesConfig.getInstance().setCodeByRegion(profile, region, regionalCode);
ResourcesConfig.getInstance().setCodeSrcByRegion(profile, region, path.relative(rootPath, v2CodePath));
// 3.3 update regional skill infrastructure deployState
const deployState = ResourcesConfig.getInstance().getSkillInfraDeployState(profile) || {};
deployState[region] = {
Expand Down
5 changes: 3 additions & 2 deletions lib/commands/util/upgrade-project/hosted-skill-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const HostedSkillController = require('@src/controllers/hosted-skill-controller'
const SkillMetadataController = require('@src/controllers/skill-metadata-controller');
const CLiError = require('@src/exceptions/cli-error');
const ResourcesConfig = require('@src/model/resources-config');
const AskResources = require('@src/model/resources-config/ask-resources');
const CONSTANTS = require('@src/utils/constants');
const stringUtils = require('@src/utils/string-utils');

Expand Down Expand Up @@ -49,12 +50,12 @@ function createV2ProjectSkeleton(rootPath, skillId, profile) {
const skillCodePath = path.join(rootPath, CONSTANTS.FILE_PATH.SKILL_CODE.LAMBDA);
fs.ensureDirSync(skillCodePath);
// prepare ask-resources config
const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG);
const askResourcesJson = R.clone(ResourcesConfig.BASE);
askResourcesJson.profiles[profile] = {
skillId
};
const askResourcesFilePath = path.join(rootPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG);
fs.writeJSONSync(askResourcesFilePath, askResourcesJson, { spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT });
AskResources.withContent(askResourcesFilePath, askResourcesJson);
}

/**
Expand Down
8 changes: 3 additions & 5 deletions lib/commands/v2new/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,9 @@ function bootstrapProject(deployDelegateType, infrastructurePath, profile, doDeb
const ddFolderPath = deployDelegateType.startsWith('@ask-cli/') ? deployDelegateType.replace('@ask-cli/', '') : deployDelegateType;
const workspacePath = path.join(infrastructurePath, stringUtils.filterNonAlphanumeric(ddFolderPath));
fs.ensureDirSync(workspacePath);
ResourcesConfig.getInstance().setSkillInfra(profile, {
type: deployDelegateType,
userConfig: ResourcesConfig.getInstance().getSkillInfraUserConfig(profile),
deployState: {}
});
ResourcesConfig.getInstance().setSkillInfraType(profile, deployDelegateType);
ResourcesConfig.getInstance().setSkillInfraDeployState(profile, {});

// 2.Bootstrap skill project with deploy delegate logic
const skillInfraController = new SkillInfrastructureController({ profile, doDebug });
skillInfraController.bootstrapInfrastructures(workspacePath, (bootstrapErr) => {
Expand Down
3 changes: 1 addition & 2 deletions lib/controllers/hosted-skill-controller/clone-flow.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const fs = require('fs-extra');
const jsonfile = require('jsonfile');
const path = require('path');
const R = require('ramda');

Expand Down Expand Up @@ -33,7 +32,7 @@ function _generateProjectDirectory(projectPath) {
const askResourcesPath = path.join(projectPath, CONSTANTS.FILE_PATH.ASK_RESOURCES_JSON_CONFIG);
const askResourcesJson = R.clone(ResourcesConfig.BASE);
fs.mkdirSync(projectPath);
jsonfile.writeFileSync(askResourcesPath, askResourcesJson, { spaces: 2 });
fs.writeJSONSync(askResourcesPath, askResourcesJson, { spaces: CONSTANTS.CONFIGURATION.JSON_DISPLAY_INDENT });
}

function _updateAskResources(projectPath, skillId, metadata, profile) {
Expand Down
7 changes: 3 additions & 4 deletions lib/controllers/skill-code-controller/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const R = require('ramda');
const fs = require('fs-extra');
const async = require('async');

Expand Down Expand Up @@ -50,13 +49,13 @@ module.exports = class SkillCodeController {
* @return {Array} codeList in the structure of [{ src, build, regionsList }]
*/
_resolveUniqueCodeList() {
const codeResources = ResourcesConfig.getInstance().getCode(this.profile);
if (!codeResources) {
const codeRegions = ResourcesConfig.getInstance().getCodeRegions(this.profile);
if (!codeRegions) {
throw 'Invalid skill code settings. Please make sure to provide the "code" field correctly in ask-resources file.';
}
// register codeResources as a HashMap with following structure { codeSrc: [regionsList] }
const codeSrcToRegionMap = new Map();
for (const region of R.keys(codeResources)) {
for (const region of codeRegions) {
const codeSrc = ResourcesConfig.getInstance().getCodeSrcByRegion(this.profile, region);
if (!stringUtils.isNonBlankString(codeSrc)) {
throw `Invalid code setting in region ${region}. "src" must be set if you want to deploy skill code with skill package.`;
Expand Down
4 changes: 2 additions & 2 deletions lib/controllers/skill-infrastructure-controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ module.exports = class SkillInfrastructureController {
return callback('[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. '
+ 'Please make sure your skill name or skill project folder basename contains alphanumeric characters.');
}
const regionsList = Object.keys(ResourcesConfig.getInstance().getCode(this.profile));
const regionsList = ResourcesConfig.getInstance().getCodeRegions(this.profile);
if (!regionsList || regionsList.length === 0) {
return callback('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.');
}
Expand Down Expand Up @@ -204,7 +204,7 @@ module.exports = class SkillInfrastructureController {
}
const { deployState, message, reasons } = invokeResult;
// track the current hash when deploy state contains s3 result
if (deployState && deployState.s3) {
if (deployState && deployState.s3) { // TODO how come there is an S3 here...
invokeResult.lastDeployHash = currentHash;
}
if (reasons) {
Expand Down
55 changes: 38 additions & 17 deletions lib/model/abstract-config-file.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
const R = require('ramda');
const fs = require('fs');
const fs = require('fs-extra');
const path = require('path');

const jsonView = require('@src/view/json-view');
const CliFileNotFoundError = require('@src/exceptions/cli-file-not-found-error');
const yaml = require('./yaml-parser');
const jsonView = require('@src/view/json-view');

const yaml = require('./yaml-parser');

const FILE_EXTNAME_JSON = '.json';
const FILE_EXTNAME_YAML = '.yaml';
const FILE_EXTNAME_YML = '.yml';
const FILE_TYPE_JSON = 'JSON';
const FILE_TYPE_YAML = 'YAML';

Expand Down Expand Up @@ -51,6 +54,21 @@ module.exports = class ConfigFile {
this.read();
}

/**
* Write content to file path using ConfigFile's WRITE_METHODs
* @param {String} filePath
* @param {Object} content
*/
static withContent(filePath, content) {
// ensure file exits with content
if (fs.existsSync(filePath)) {
throw new Error(`Failed to create file ${filePath} as it already exists.`);
}
fs.ensureDirSync(path.dirname(filePath));
const fileType = _resolveFileType(filePath);
WRITE_METHOD_BY_FILE_TYPE[fileType](filePath, content);
}

/**
* Get property based on the property array.
* Return undefined if not found.
Expand Down Expand Up @@ -95,19 +113,22 @@ module.exports = class ConfigFile {
} catch (error) {
throw new Error(`No access to read/write file ${this.path}.`);
}
// check file name
if (path.basename(this.path) === 'cli_config') {
this.fileType = FILE_TYPE_JSON;
} else {
// check file extension
const fileExtension = path.extname(this.path).toLowerCase();
if (fileExtension === '.json') {
this.fileType = FILE_TYPE_JSON;
} else if (fileExtension === '.yaml' || fileExtension === '.yml') {
this.fileType = FILE_TYPE_YAML;
} else {
throw new Error(`File type for ${this.path} is not supported. Only JSON and YAML files are supported.`);
}
}
this.fileType = _resolveFileType(this.path);
}
};

function _resolveFileType(filePath) {
if (path.basename(filePath) === 'cli_config') {
return FILE_TYPE_JSON;
}
// check file extension
const fileExtension = path.extname(filePath).toLowerCase();
if (fileExtension === FILE_EXTNAME_JSON) {
return FILE_TYPE_JSON;
}
if (fileExtension === FILE_EXTNAME_YAML || fileExtension === FILE_EXTNAME_YML) {
return FILE_TYPE_YAML;
}

throw new Error(`File type for ${filePath} is not supported. Only JSON and YAML files are supported.`);
}
Loading

0 comments on commit 45d550e

Please sign in to comment.