Skip to content

Commit

Permalink
feat: implement diagnose hooks for preflight validation
Browse files Browse the repository at this point in the history
  • Loading branch information
ZauberNerd committed Apr 9, 2019
1 parent b56fd9e commit 4e8f1f8
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 71 deletions.
12 changes: 12 additions & 0 deletions packages/graphql/mixin.core.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { existsSync } = require('fs');
const { Mixin } = require('hops-mixin');
const strip = require('strip-indent');
const {
Expand Down Expand Up @@ -109,6 +110,17 @@ class GraphQLMixin extends Mixin {
);
}
}

diagnose() {
if (!existsSync(this.config.fragmentsFile)) {
return [
`Could not find a graphql introspection query result at "${
this.config.fragmentsFile
}".`,
'You might need to execute "hops graphql introspect"',
];
}
}
}

module.exports = GraphQLMixin;
8 changes: 0 additions & 8 deletions packages/graphql/mixin.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const {
const fetch = require('cross-fetch');

let introspectionResult = undefined;
let warned = false;

class GraphQLMixin extends Mixin {
constructor(config, element, { graphql: options = {} } = {}) {
Expand All @@ -31,13 +30,6 @@ class GraphQLMixin extends Mixin {
if (existsSync(config.fragmentsFile)) {
const fileContent = readFileSync(config.fragmentsFile, 'utf-8');
introspectionResult = JSON.parse(fileContent);
} else if (!warned) {
warned = true;
console.warn(
'Could not find a graphql introspection query result at %s.',
config.fragmentsFile,
'You might need to execute `hops graphql introspect`'
);
}
} catch (_) {
introspectionResult = null;
Expand Down
46 changes: 0 additions & 46 deletions packages/lambda/lib/aws-config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
'use strict';

const semver = require('semver');
const { trimSlashes } = require('pathifist');

const MAX_NODE_VERSION = '8.10';

module.exports = function getAWSConfig(hopsConfig) {
const awsConfig = hopsConfig._aws || hopsConfig.aws || {};

Expand All @@ -27,48 +24,5 @@ module.exports = function getAWSConfig(hopsConfig) {
exclude: [...(awsConfig.exclude || [])],
};

const targetNodeVersion =
!hopsConfig.node || hopsConfig.node === 'current'
? process.version
: hopsConfig.node;

if (
semver.gt(semver.coerce(targetNodeVersion), semver.coerce(MAX_NODE_VERSION))
) {
console.warn(
'AWS Lambda only supports Node.js up to version:',
MAX_NODE_VERSION
);
console.warn(
'Please specify or use a Node.js version lower than or equal to this',
'version in your Hops config (hops.node) to tell Babel for which version',
'it should transpile for.'
);
}

if (
!config.domainName &&
config.basePath.indexOf(config.stageName) !== 0 &&
trimSlashes(hopsConfig.assetPath).indexOf(config.stageName) !== 0
) {
console.warn(
'When no custom domain is configured, the stageName (' +
config.stageName +
') should be the first path segment in basePath (' +
config.basePath +
') and assetPath (' +
hopsConfig.assetPath +
').'
);
}

if (config.domainName && !config.certificateArn) {
console.error(
'Setting a custom domain name also requires to specify the ACM',
'certificate ARN.'
);
process.exit(1);
}

return config;
};
24 changes: 14 additions & 10 deletions packages/lambda/lib/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
var fs = require('fs');
var path = require('path');
var AWS = require('aws-sdk');
var getAWSConfig = require('./aws-config');
var createLambdaBundle = require('./create-lambda-bundle');
var progressWriter = require('./progress-writer');
var fsUtils = require('./fs-utils');
Expand Down Expand Up @@ -140,14 +139,19 @@ function createOrUpdateStack(cloudformation, stackName, templateUrl, params) {
});
}

module.exports = function deploy(config, options, parametersOverrides) {
var awsConfig = getAWSConfig(config);

if (!fs.existsSync(config.buildDir)) {
console.error(
'Could not find build directory. Please make sure that you ' +
'have executed "hops build" before trying to deploy your application.'
);
module.exports = function deploy(
{ hopsConfig, awsConfig },
options,
parametersOverrides,
logger
) {
if (!fs.existsSync(hopsConfig.buildDir)) {
if (logger) {
logger.error(
'Could not find build directory. Please make sure that you ' +
'have executed "hops build" before trying to deploy your application.'
);
}
return process.exit(1);
}

Expand All @@ -173,7 +177,7 @@ module.exports = function deploy(config, options, parametersOverrides) {

return Promise.all([
createLambdaBundle(
config.rootDir,
hopsConfig.rootDir,
zippedBundleLocation,
awsConfig.include,
awsConfig.exclude,
Expand Down
5 changes: 1 addition & 4 deletions packages/lambda/lib/destroy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

var AWS = require('aws-sdk');
var prompt = require('./prompt');
var getAWSConfig = require('./aws-config');

function emptyBucket(s3, bucketName) {
console.log('Deleting objects in S3 bucket');
Expand Down Expand Up @@ -57,9 +56,7 @@ function deleteStack(cloudFormation, stackName) {
});
}

module.exports = function destroy(config, options) {
var awsConfig = getAWSConfig(config);

module.exports = function destroy({ awsConfig }, options, logger) {
AWS.config.update({ region: awsConfig.region });

AWS.config.apiVersions = {
Expand Down
66 changes: 63 additions & 3 deletions packages/lambda/mixin.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,35 @@ const {
async: { callable: callableAsync },
},
} = require('hops-mixin');
const { trimSlashes } = require('pathifist');
const semver = require('semver');
const strip = require('strip-indent');

const MAX_NODE_VERSION = '8.10';
const getAWSConfig = require('./lib/aws-config');

class LambdaMixin extends Mixin {
constructor(config, ...args) {
super(config, ...args);

this.awsConfig = getAWSConfig(this.config);
}

deployLambda(parameterOverrides) {
return require('./lib/deploy')(
this.config,
{ hopsConfig: this.config, awsConfig: this.awsConfig },
this.options,
parameterOverrides
parameterOverrides,
typeof this.getLogger === 'function' ? this.getLogger() : null
);
}

destroyLambda() {
return require('./lib/destroy')(this.config, this.options);
return require('./lib/destroy')(
{ hopsConfig: this.config, awsConfig: this.awsConfig },
this.options,
typeof this.getLogger === 'function' ? this.getLogger() : null
);
}

registerCommands(yargs) {
Expand Down Expand Up @@ -69,6 +85,50 @@ class LambdaMixin extends Mixin {
handleArguments(argv) {
this.options = { ...this.options, ...argv };
}

diagnose() {
const warnings = [];
const targetNodeVersion =
!this.config.node || this.config.node === 'current'
? process.version
: this.config.node;

if (
semver.gt(
semver.coerce(targetNodeVersion),
semver.coerce(MAX_NODE_VERSION)
)
) {
warnings.push(
[
`AWS Lambda only supports Node.js up to version: ${MAX_NODE_VERSION}.`,
'Please specify or use a Node.js version lower than or equal to this',
'version in your Hops config (hops.node) to tell Babel for which version',
'it should transpile for.',
].join('\n')
);
}

if (
!this.awsConfig.domainName &&
this.awsConfig.basePath.indexOf(this.awsConfig.stageName) !== 0 &&
trimSlashes(this.config.assetPath).indexOf(this.awsConfig.stageName) !== 0
) {
warnings.push(
`When no custom domain is configured, the stageName (${
this.awsConfig.stageName
}) should be the first path segment in basePath (${
this.awsConfig.basePath
}) and assetPath (${this.config.assetPath}).`
);
}

if (this.awsConfig.domainName && !this.awsConfig.certificateArn) {
warnings.push(
'Setting a custom domain name also requires to specify the ACM certificate ARN.'
);
}
}
}

LambdaMixin.strategies = {
Expand Down
16 changes: 16 additions & 0 deletions packages/typescript/mixin.core.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const { existsSync } = require('fs');
const { join } = require('path');
const { Mixin } = require('hops-mixin');

class TypescriptMixin extends Mixin {
Expand All @@ -19,6 +21,20 @@ class TypescriptMixin extends Mixin {
});
webpackConfig.resolve.extensions.push('.ts', '.tsx');
}

diagnose() {
const tsConfigPath = join(this.config.rootDir, 'tsconfig.json');
const exampleTsConfigPath = require.resolve(
'hops-typescript/tsconfig.json'
);
if (!existsSync(tsConfigPath)) {
return `No "tsconfig.json" file found in your project root directory ("${
this.config.rootDir
}").\nAs a starting point you can copy our minimal example config file: "cp ${exampleTsConfigPath} ${
this.config.rootDir
}/tsconfig.json"`;
}
}
}

module.exports = TypescriptMixin;

0 comments on commit 4e8f1f8

Please sign in to comment.