Skip to content

Instantly share code, notes, and snippets.

@imaustink
Created October 15, 2016 22:02
Show Gist options
  • Save imaustink/e090c33a957b054d29c4e0fbd5a14b6a to your computer and use it in GitHub Desktop.
Save imaustink/e090c33a957b054d29c4e0fbd5a14b6a to your computer and use it in GitHub Desktop.
Lambda build tasks
var argv = require('yargs').argv;
var chmod = require("gulp-chmod");
var debug = require('gulp-debug');
var fs = require('fs');
var gulp = require('gulp');
var gutil = require('gulp-util');
var istanbul = require('gulp-istanbul');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var path = require('path');
var publishLambda = require('gulp-awslambda');
var Readline = require('readline');
var sequence = require('gulp-sequence');
var zip = require('gulp-zip');
gulp.task('default', function() {
// be ready to read in any commands
readSTDIN((command) => {
gulp.start(command);
});
// watch for changes to the lambda functions
return gulp.watch(['functions/**', '!*', '!functions/**/test/**', '!functions/**/coverage/**'], function(event){
// get the lambda that was modified
var lambda = getLambdaArg(event.path);
// if no lambda, return
if(!lambda){
return;
}
// log the lambda that was changed
gutil.log(`${lambda} changed!`);
// add to unpublished
Unpublished.push(lambda);
});
});
gulp.task('test', function(){
// try to get a lambda from the -l arg
var lambda = getLambdaArg(argv.l);
var unpublished = Unpublished.get();
// if we did have a lambda arg...
if(lambda){
// publish the lambda
return gulp.start(`test-and-lint-${lambda}`);
}
// otherwise, we're going to use the unpublished array from the watcher
// anything?
if(!unpublished.length){
// notify user that we couldn't find anything to publish
return console.error('Nothing to test!');
}
// publish everything waiting to be published
unpublished.forEach(() => gulp.start(`test-and-lint-${lambda}`));
// reset the unpublished array
Unpublished.set([]);
});
gulp.task('publish', function(){
// try to get a lambda from the -l arg
var lambda = getLambdaArg(argv.l);
// if we did have a lambda arg...
if(lambda){
// publish the lambda
return gulp.start(`publish-${lambda}`);
}
// otherwise, we're going to use the unpublished array from the watcher
var unpublished = Unpublished.get();
// anything?
if(!unpublished.length){
// notify user that we couldn't find anything to publish
return gutil.log('Nothing to publish!');
}
// publish everything waiting to be published
unpublished.forEach(lambda => gulp.start(`publish-${lambda}`));
// reset the unpublished array
Unpublished.save([]);
});
// for each lambda
getLambdas().forEach(lambda => {
var package;
var lambda_settings;
// register a gulp tasks
gulp.task(`check-${lambda}`, done => {
sequence(`test-${lambda}`, `lint-${lambda}`, done);
});
gulp.task(`lint-${lambda}`, () => {
return gulp.src([`./functions/${lambda}/**/*.js`, `!./functions/${lambda}/+(node_modules|coverage)/**/*`])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'));
});
gulp.task(`pre-test-${lambda}`, [`read-package-${lambda}`], () => {
return gulp.src([path.join('.', 'functions', lambda, package.main || 'index.js')])
.pipe(istanbul())
.pipe(istanbul.hookRequire());
});
gulp.task(`publish-${lambda}`, [`read-package-${lambda}`, `check-${lambda}`], () => {
return gulp.src([`./functions/${lambda}/**`, `!./functions/${lambda}/test`, `!./functions/${lambda}/test/**`])
.pipe(chmod(777, true))
.pipe(zip(lambda + '.zip'))
.pipe(publishLambda(
{
FunctionName: lambda,
Handler: lambda_settings.handler || 'index.handler',
Role: lambda_settings.role || 'arn:aws:iam::455160284107:role/lambda-basic-execution',
Description: lambda_settings.description || package.description || ''
},
{
profile: 'personal',
region: lambda_settings.region || 'us-east-1'
}
))
//.pipe(gulp.dest('./dist'))
;
});
gulp.task(`read-package-${lambda}`, (done) => {
fs.readFile(`./functions/${lambda}/package.json`, 'utf8', (err, file) => {
if(err){
package = {};
lambda_settings = {};
return done();
}
// try to parse the JSON
try {
package = JSON.parse(file);
lambda_settings = package.lambda || {};
return done();
} catch(err){
package = {};
lambda_settings = {};
return done();
}
});
});
gulp.task(`test-${lambda}`, [`pre-test-${lambda}`], () => {
return gulp.src([`./functions/${lambda}/test/**/*.js`], { read:false })
.pipe(mocha())
.pipe(istanbul.writeReports({ reporters: ['lcov', 'json', 'text-summary'], dir: `./functions/${lambda}/coverage`}));
//.pipe(istanbul.enforceThresholds({ thresholds: { global: 100 } }));
});
gulp.task(`test-and-lint-${lambda}`, [`test-${lambda}`, `lint-${lambda}`]);
});
function getLambdas() {
return fs.readdirSync(path.join(__dirname, './functions/')).filter(function(file) {
return fs.statSync(path.join(__dirname, 'functions', file)).isDirectory();
});
}
function getLambdaArg(arg){
// make sure we have something to work with
if(!arg){
return;
}
// vars
var lambda_dir = path.join(__dirname, 'functions');
var lambda = arg;
var stat;
// see if the arg is simply a lambda name
if(path.join(lambda_dir, arg, '..') !== lambda_dir){
// wasn't a lambda name
// see if it's a relative or absolute path to the lambda file or subfolder/file
lambda = path.resolve(arg);
// does the first part of our lambda match the lambda directory?
if(lambda.substr(0, lambda_dir.length).toLowerCase() === lambda_dir.toLowerCase()){
// strip off the lambda directory and any trailing directories
lambda = lambda.substr(lambda_dir.length + 1).match(/^([^\\\/]*)/)[0];
} else {
// didn't match the lambda directory so we got nothing
return;
}
}
// check if something exists
try {
stat = fs.statSync(path.join(lambda_dir, lambda));
} catch(err){
return;
}
// check if folder
if(!stat.isDirectory()){
return;
}
// return the valid lambda name
return lambda;
}
function readSTDIN(cb){
Readline.createInterface({
input: process.stdin
}).on('line', (line) => {
cb(line.trim());
});
}
function Unpublished(){};
(function(){
// This is where we save the file to
const FILE = './.unpublished.json';
// Returns Array of file paths from FILE
this.get = (retry) => {
try{
return JSON.parse(fs.readFileSync(FILE));
}catch(err){
// Prevent infinite loop
if(retry === false) throw 'Failed to create publish file!';
// Create FILE with empty Array
this.save([]);
// Try again and disable retry
return this.get(false);
}
};
// Push to Array of FILE
this.push = (val) => {
// Get starting value
var vals = this.get();
// If it isn't already in the Array
if(!~vals.indexOf(val)){
// Push to Array
vals.push(val);
// And save
this.save(vals);
}
};
// Saves string to FILE
this.save = (val) => {
fs.writeFileSync(FILE, JSON.stringify(val));
};
return this;
}).call(Unpublished);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment