diff --git a/.gitignore b/.gitignore index 29ade9b7..cf155a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ node_modules .env event.json npm-debug.log* +.lambda diff --git a/README.md b/README.md index 9de2bb5a..a0a307e0 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,10 @@ $ node-lambda setup --help -h, --help output usage information ``` -After running setup, it's a good idea to gitignore the generated `event.json` and `.env` files. +After running setup, it's a good idea to gitignore the generated `event.json` and `.env` files, as well as `.lambda`. ``` -echo -e ".env\ndeploy.env\nevent.json" >> .gitignore +echo -e ".env\ndeploy.env\nevent.json\n.lambda" >> .gitignore ``` #### run @@ -87,6 +87,7 @@ $ node-lambda package --help -h, --help output usage information -A, --packageDirectory [build] Local Package Directory + -I, --dockerImage [] Docker image for npm install -n, --functionName [node-lambda] Lambda FunctionName -H, --handler [index.handler] Lambda Handler {index.handler} -e, --environment [staging] Choose environment {development, staging, production} @@ -129,6 +130,7 @@ $ node-lambda deploy --help -Q, --deadLetterConfigTargetArn [] Lambda DLQ resource -T, --tracingConfig [] Lambda tracing settings -A, --packageDirectory [] Local package directory + -I, --dockerImage [] Docker image for npm install -S, --eventSourceFile [event_sources.json] Path to file holding event source mapping variables (e.g. "event_sources.json") -x, --excludeGlobs [] Add a space separated list of file(type)s to ignore (e.g. "*.json .env") -D, --prebuiltDirectory [] Prebuilt directory @@ -164,16 +166,6 @@ The `--prebuiltDirectory` flag is useful for working with Webpack for example. I ## Handling `npm link` and Dependencies With Local Paths Perhaps the easiest way to handle these cases is to bundle the code using Webpack and use the `--prebuiltDirectory` flag to package the output for deployment. -## Running `node-lambda` as an NPM script -Strangely, NPM overwrites the TMPDIR environment variable (and therefore the result of `os.tmpDir()`) to the current working directory. This means when running node-lambda deploy as a NPM script in `package.json`, it fails on the rsync step as the destination directory exists in the folder you're synchronising (causing heaps of file has vanished: type errors). - -You can resolve this by explicitly setting the `TMPDIR` variable as you deploy, something like: -``` -"scripts": { - "deploy-stage": "TMPDIR=/tmp node-lambda deploy" -} -``` - ## Other AWS Lambda Tools Projects + [lambdaws](https://github.com/mentum/lambdaws) diff --git a/bin/node-lambda b/bin/node-lambda index e034ff0c..20b44821 100755 --- a/bin/node-lambda +++ b/bin/node-lambda @@ -70,6 +70,7 @@ var EVENT_FILE = process.env.EVENT_FILE || 'event.json'; var PACKAGE_DIRECTORY = process.env.PACKAGE_DIRECTORY; var CONTEXT_FILE = process.env.CONTEXT_FILE || 'context.json'; var PREBUILT_DIRECTORY = process.env.PREBUILT_DIRECTORY || ''; +var DOCKER_IMAGE = process.env.DOCKER_IMAGE || ''; var DEPLOY_ZIPFILE = process.env.DEPLOY_ZIPFILE || ''; var AWS_DLQ_TARGET_ARN = (function() { // You can clear the setting by passing an empty string @@ -107,6 +108,7 @@ program .option('-T, --tracingConfig [' + AWS_TRACING_CONFIG + ']', 'Lambda tracing settings', AWS_TRACING_CONFIG) .option('-A, --packageDirectory [' + PACKAGE_DIRECTORY + ']', 'Local Package Directory', PACKAGE_DIRECTORY) + .option('-I, --dockerImage [' + DOCKER_IMAGE + ']', 'Docker image for npm install', DOCKER_IMAGE) .option('-f, --configFile [' + CONFIG_FILE + ']', 'Path to file holding secret environment variables (e.g. "deploy.env")', CONFIG_FILE) .option('-S, --eventSourceFile [' + EVENT_SOURCE_FILE + ']', @@ -124,6 +126,7 @@ program .alias('zip') .description('Create zipped package for Amazon Lambda deployment') .option('-A, --packageDirectory [' + PACKAGE_DIRECTORY + ']', 'Local Package Directory', PACKAGE_DIRECTORY) + .option('-I, --dockerImage [' + DOCKER_IMAGE + ']', 'Docker image for npm install', DOCKER_IMAGE) .option('-n, --functionName [' + AWS_FUNCTION_NAME + ']', 'Lambda FunctionName', AWS_FUNCTION_NAME) .option('-H, --handler [' + AWS_HANDLER + ']', 'Lambda Handler {index.handler}', AWS_HANDLER) .option('-e, --environment [' + AWS_ENVIRONMENT + ']', 'Choose environment {dev, staging, production}', diff --git a/lib/main.js b/lib/main.js index fd339500..8c14edea 100644 --- a/lib/main.js +++ b/lib/main.js @@ -195,6 +195,7 @@ Lambda.prototype._fileCopy = function (program, src, dest, excludeNodeModules, c '.git*', '*.swp', '.editorconfig', + '.lambda', 'deploy.env', '*.log', '/build/' @@ -234,7 +235,7 @@ Lambda.prototype._fileCopy = function (program, src, dest, excludeNodeModules, c }; Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, callback) { - var excludes = ['.git*', '*.swp', '.editorconfig', 'deploy.env', '*.log', '/build/'], + var excludes = ['.git*', '*.swp', '.editorconfig', '.lambda', 'deploy.env', '*.log', '/build/'], excludeGlobs = []; if (program.excludeGlobs) { excludeGlobs = program.excludeGlobs.split(' '); @@ -270,7 +271,10 @@ Lambda.prototype._rsync = function (program, src, dest, excludeNodeModules, call }; Lambda.prototype._npmInstall = function (program, codeDirectory, callback) { - exec('npm -s install --production --prefix ' + codeDirectory, { + var command = program.dockerImage ? + 'docker run --rm -v ' + codeDirectory + ':/var/task ' + program.dockerImage + ' npm -s install --production' : + 'npm -s install --production --prefix ' + codeDirectory; + exec(command, { maxBuffer: maxBufferSize, env: process.env }, function (err) { @@ -349,7 +353,7 @@ Lambda.prototype._nativeZip = function (program, codeDirectory, callback) { Lambda.prototype._codeDirectory = function (program) { var epoch_time = +new Date(); - return path.join(os.tmpDir(), program.functionName + '-' + epoch_time); + return path.resolve('.', '.lambda'); }; Lambda.prototype._cleanDirectory = function (codeDirectory, callback) { @@ -453,7 +457,7 @@ Lambda.prototype._buildAndArchive = function (program, archive_callback) { // Warn if not building on 64-bit linux var arch = process.platform + '.' + process.arch; - if (arch !== 'linux.x64') { + if (arch !== 'linux.x64' && !program.dockerImage) { console.warn('Warning!!! You are building on a platform that is not 64-bit Linux (%s). ' + 'If any of your Node dependencies include C-extensions, they may not work as expected in the ' + 'Lambda environment.\n\n', arch);