aws lambda nodejs - error when uploading a zip file compressing by GULP - gulp

I'm using Gulp to compress a zip file and then upload it to AWS Lambda. The upload zip file is done manually. Only the process of compressing is handled by Gulp.
Here is my gulpfile.js
var gulp = require('gulp');
var zip = require('gulp-zip');
var del = require('del');
var install = require('gulp-install');
var runSequence = require('run-sequence');
var awsLambda = require("node-aws-lambda");
gulp.task('clean', function() {
return del(['./dist', './dist.zip']);
});
gulp.task('js', function() {
return gulp.src('index.js')
.pipe(gulp.dest('dist/'));
});
gulp.task('npm', function() {
return gulp.src('./package.json')
.pipe(gulp.dest('dist/'))
.pipe(install({production: true}));
});
gulp.task('zip', function() {
return gulp.src(['dist/**/*', '!dist/package.json'])
.pipe(zip('dist.zip'))
.pipe(gulp.dest('./'));
});
gulp.task('deploy', function(callback) {
return runSequence(
['clean'],
['js', 'npm'],
['zip'],
callback
);
});
After running the deploy task, a zip folder named dist.zip is created consists of a index.js file and a node_modules folder. The node_modules folder contains only a lodash library.
This is index.js
var _ = require('lodash');
console.log('Loading function');
exports.handler = (event, context, callback) => {
//console.log('Received event:', JSON.stringify(event, null, 2));
var b = _.chunk(['a', 'b', 'c', 'd', 'e'], 3);
console.log(b);
callback(null, event.key1); // Echo back the first key value
//callback('Something went wrong');
};
After using AWS lambda console to upload the dist.zip folder. There is an error showing that the lodash library cannot be found
{
"errorMessage": "Cannot find module 'lodash'",
"errorType": "Error",
"stackTrace": [
"Function.Module._load (module.js:276:25)",
"Module.require (module.js:353:17)",
"require (internal/module.js:12:17)",
"Object.<anonymous> (/var/task/index.js:1:71)",
"Module._compile (module.js:409:26)",
"Object.Module._extensions..js (module.js:416:10)",
"Module.load (module.js:343:32)",
"Function.Module._load (module.js:300:12)",
"Module.require (module.js:353:17)"
]
}
But in the zip folder, there is a node_modules directory that contains the lodash lib.
dist.zip
|---node_modules
|--- lodash
|---index.js
When i zip the node_modules directory and the file index.js manually, it works fine.
Does anyone have idea what wrongs ? Maybe when compressing using Gulp, there is a misconfigured for the lib path ?

I had same problem few days back.
Everyone pointed to gulp zip, however it was not problem with gulp zip.
Below worked fine:
gulp
.src(['sourceDir/**'], {nodir: true, dot: true} )
.pipe(zip('target.zip'))
.pipe(gulp.dest('build/'));
That is, note the below, in 2nd param of src, in the above:
{nodir: true, dot: true}
That is, we have to include dot files for the zip (ex: .config, .abc, etc.)
So, include above in .src of gulp, else all others like copy, zip, etc. will be improper.

The package gulp-zip is massively popular (4.3k downloads per day) and there does not seem to be any Gulp substitute. The problem is definitely with relative paths and how gulp-zip processes them. Even when using a base path option in the gulp.src function (example below), gulp-zip finds a way to mess it up.
gulp.task("default", ["build-pre-zip"], function () {
return gulp.src([
"dist/**/*"
], { base: "dist/" })
.pipe(debug())
.pipe(zip("dist.zip"))
.pipe(gulp.dest("./dist/"));
});
Since there is no good Gulp solution as of 1/4/2017 I suggest a work-around. I use Gulp to populate the dist folder first, exactly how I need it with the proper node_modules folder. Then it is time to zip the dist folder properly with relative file paths stored. To do that and also update Lambda, I use a batch file (Windows) of command line options to get the job done. Here is the upload.bat file I created to take the place of the gulp-zip task:
start /wait cmd /c "gulp default"
start /wait cmd /c "C:\Program Files\WinRAR\WinRAR.exe" a -r -ep1 dist\dist.zip dist\*.*
aws lambda update-function-code --zip-file fileb://dist/dist.zip --function-name your-fn-name-here
If you use WinRAR you will find their command line docs here, for WinZip go here. That .bat file assumes you are using the AWS Command Line Interface (CLI) which is a godsend; get it here.
If you are wishing this answer pointed you towards a 100% Gulp solution, to that I say, "You and me both!". Good luck.

Related

Gulp-octo is ignoring my choice of output directory

I'm trying to build an Octopus Deploy package for an angular-cli project using Gulp and Gulp-Octo:
const gulp = require("gulp"),
octopus = require("#octopusdeploy/gulp-octo"),
version = require("./package.json").version;
gulp.task("octopack",
["build-prod"],
() => gulp.src("dist/*")
.pipe(octopus.pack(
"zip", // octopackjs does not support nupkg format yet
{
id: "myprojectid",
version: `${version}.${commandLineOptions.buildnumber}`
}))
.pipe(gulp.dest('./octopus'))
);
This creates a package with the correct contents and version number, but it always goes into the current directory (alongside gulpfile.js) instead of the directory that I specified in gulp.dest().
I have tried all of the following variations in the call to gulp.dest, with the same result:
./octopus
./octopus/
octopus/
octopus
path.join(__dirname, 'octopus')
Am I misunderstanding how gulp.dest() works, or is octopus.pack() doing something weird?
(Note: If I leave out the gulp.dest() altogether then no zip file is created.)
It's a bug in gulp-octo. In this line they set the path of the generated archive. Unfortunately they just use the filename of the archive instead of a full path (which is what they're supposed to do), so the file is always written relative to the current working directory.
I might send them a pull request when I get the chance, since this is an easy fix.
In the meantime you can use the following workaround:
var path = require('path');
gulp.task("default",
() => gulp.src("dist/*")
.pipe(octopus.pack(
"zip", // octopackjs does not support nupkg format yet
{
id: "myprojectid",
version: `${version}.${commandLineOptions.buildnumber}`
}))
.on('data', (f) => { f.path = path.join(f.base, f.path) })
.pipe(gulp.dest('./octopus'))
);

Polymer: two gulp errors at build time: 'async completion' and 'apply' property

I'm trying to run gulp to build my app like Rob Dodson explains here.
Original error
At the command line, if I run:
npm run build
I get the following error:
[20:50:55] Using gulpfile ~/path/to/gulpfile.js
[20:50:55] Starting 'default'...
Deleting build/ directory...
[20:50:56] The following tasks did not complete: default
[20:50:56] Did you forget to signal async completion?
It appears there is some task described as "signal async completion?" What does this mean? And how do I do it?
Alternate error
However if I run the following at the command line:
gulp
I get a different error message as follows:
[23:40:57] Using gulpfile ~/path/to/gulpfile.js
/usr/local/lib/node_modules/gulp/bin/gulp.js:129
gulpInst.start.apply(gulpInst, toRun);
^
TypeError: Cannot read property 'apply' of undefined
at /usr/local/lib/node_modules/gulp/bin/gulp.js:129:19
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickCallback (node.js:349:13)
at Function.Module.runMain (module.js:443:11)
at startup (node.js:139:18)
at node.js:968:3
Why would there be different error messages? Does that give a hint what's actually causing the errors? If so, what is it? And what can I do to fix it?
My code
I just copied the files package.json, polymer.json and gulpfile.js from the sample code Rob supplied here. Then I ran npm install as this answer describes.
gulpfile.js
'use strict';
// Documentation on what goes into PolymerProject.
const path = require('path');
const gulp = require('gulp');
const mergeStream = require('merge-stream');
const del = require('del');
const polymerJsonPath = path.join(process.cwd(), 'polymer.json');
const polymerJSON = require(polymerJsonPath);
const polymer = require('polymer-build');
const polymerProject = new polymer.PolymerProject(polymerJSON);
const buildDirectory = 'build/bundled';
/**
* Waits for the given ReadableStream
*/
function waitFor(stream) {
return new Promise((resolve, reject) => {
stream.on('end', resolve);
stream.on('error', reject);
});
}
function build() {
return new Promise((resolve, reject) => {
// Okay, so first thing we do is clear the build
console.log(`Deleting build/ directory...`);
del([buildDirectory])
.then(_ => {
// Okay, now lets get your source files
let sourcesStream = polymerProject.sources()
// Oh, well do you want to minify stuff? Go for it!
// Here's how splitHtml & gulpif work
.pipe(polymerProject.splitHtml())
.pipe(gulpif(/\.js$/, uglify()))
.pipe(gulpif(/\.css$/, cssSlam()))
.pipe(gulpif(/\.html$/, htmlMinifier()))
.pipe(polymerProject.rejoinHtml());
// Okay now lets do the same to your dependencies
let depsStream = polymerProject.dependencies()
.pipe(polymerProject.splitHtml())
.pipe(gulpif(/\.js$/, uglify()))
.pipe(gulpif(/\.css$/, cssSlam()))
.pipe(gulpif(/\.html$/, htmlMinifier()))
.pipe(polymerProject.rejoinHtml());
// Okay, now lets merge them into a single build stream.
let buildStream = mergeStream(sourcesStream, depsStream)
.once('data', () => {
console.log('Analyzing build dependencies...');
});
// If you want bundling, do some bundling! Explain why?
buildStream = buildStream.pipe(polymerProject.bundler);
// If you want to add prefetch links, do it! Explain why?
// buildStream = buildStream.pipe(new PrefetchTransform(polymerProject));
// Okay, time to pipe to the build directory
buildStream = buildStream.pipe(gulp.dest(buildDirectory));
// waitFor the buildStream to complete
return waitFor(buildStream);
})
.then(_ => {
// You did it!
console.log('Build complete!');
resolve();
});
});
}
gulp.task('default', build);
The original error is unrelated to the "alternate error".
While the build task runs gulp, npm run prioritizes the locally-installed gulp (at node_modules/.bin/gulp) before the system-installed gulp. Running gulp yourself (without npm run) would invoke the globally-installed gulp, which may result in an error if it's incompatible with your project (e.g., Gulp 3 binary with Gulp 4 API in your scripts, which appears to be the case). You could either install Gulp 4 so that you can run gulp yourself, or continue using npm run build.
To troubleshoot the original error, I recommend starting from the Polycast's original source (if you haven't already) to determine what the difference could be.
If you prefer to stick with your current track, I suggest a few things:
Verify the paths in your HTML imports, as a path to a non-existent file would cause a silent error (polymer-build issue 88). It might be helpful to run polymer build -v (verbose build).
Add buildStream.on('error', (err) => console.log(err)) after let buildStream = ... in case any unsuppressed error events crop up in that stream.
I recommend you use the new version of PSK Custom Build:
https://github.com/PolymerElements/generator-polymer-init-custom-build/
It has the gulpfile.js updated.
The problem was caused by an incorrect import path.
incorrect path
<link rel="import" href="../../../bower_components/polymer/polymer.html">
correct path
<link rel="import" href="../../bower_components/polymer/polymer.html">
As #tony19, correctly described, that errant import path caused a silent failure.
I found this by pursuing the path suggested by #abdonrd. I followed the instructions here as follows.
First, I copied my project. Then I loaded into the my-app directory per the below described procedure.
https://github.com/PolymerElements/generator-polymer-init-custom-build/
npm install -g polymer-cli
npm install -g generator-polymer-init-custom-build
mkdir my-app
cd my-app
polymer init custom-build
polymer build -v # the results of this command highlighted my error in red
The error showed the path of the missing file. Which I noticed was located one level higher than it should have been because the root directory my-app/ was missing from the path. Then I had to search manually through all the files using the search string polymer/polymer.html until I found a mismatch between the number of ../ in the import path (3 in this case) and the number of folders deep into the root directory the importing file was (2 in this case).
After I corrected the file path, I again ran:
polymer build -v # building the project again, correctly this time
polymer serve build/bundled # to test serve the build/bundled version

Teamcity running gulp and passing in arguments

I have setup and configured by gulp process locally and now I am trying to get it working with Teamcity.
I have already installed node, and the gulp plug in.
One of the gulp packages I am using is gulp-bump so that I can use the %build-number% variable and use it to set the version of my package.json file. I am using yargs so that I can read arguments from the command line
This is the gulp task that I am using
gulp.task('setVersion', function () {
var msg = 'Setting version';
var version = args.version;
var options = {};
if (version) {
options.version = version;
msg += ' to ' + version;
}
log(msg);
return gulp
.src(config.packages)
.pipe($.print())
.pipe(version ? $.bump(options) : $.util.noop())
.pipe(gulp.dest(config.dest.root));
});
To get this to work, from the command line i call
gulp build --version=2.3.4
build is the gulp task that I want to run, and --version is the value i want to read from the command line.
The task setVersion is a dependency of the build task.
There are other gulp tasks that use the package.json file to be included at the op of all .css and js files that are outputted but these are called as part of the build task using the package 'run-sequence'
When I run this from the command line, everything works as expected.
Within my teamcity build I have two steps defined.
Step 1 is Node.js NPM runner, which i can see is correctly pulling down all the relevant packages .
Step 2 is using the Gulp runner.
Within this task, I have set the gulp task as "build", and the additional command line parameters as --version=%build.number%
But it does not appear that the version number is being set correctly as even though in the build log it is saying
"Setting version to 2.3.4"
It is not setting the version correctly as when I review the css and js files after the build, they are not using the correct version.
However I know that teamcity is using %build.number% correctly as the next task is to produce a nuget file using NuGet Pack, and the version is set to %build.number%, and the file name of the nuget file produced does correctly include the version number.
I just cannot get the version within package.json set correctly as part of the build process.
What else can I do to correctly pass in the build number and to correctly set the version of package.json
Update
After the comments received, I have discovered that the error was with the way in which I was reading package.json
My gulpfile.js had the following:
var pkg = require('./package.json');
var banner = ['/**',
' * <%= pkg.name %>',
' * #version v<%= pkg.version %>',
' */',
''].join('\n');
I was using package gulp-header to then insert the banner at the top of the page.
$.header(banner, { pkg: pkg })
Looking at the answer to this question : Javascript: get package.json data in gulpfile.js
it was mentioned that when you use require to load package.json the file is cached, and if any process modifies the package.json file, gulp will not update the version that it has already cached.
So I modified the routine to read the package.json file on demand:
var fs = require('fs');
function getPackageJson() {
return JSON.parse(fs.readFileSync('./package.json'));
}
So in my processes that where appending the header, I changed to call getPackageJson. Now when i run the process in teamcity, it is correctly setting the correct version
e.g.
var pkg = getPackageJson();
return gulp
.src(config.src.sass)
.pipe($.sass())
.pipe($.header(banner, { pkg: pkg }))
just check if below works
update package.json
gulp.task('bump-version', function () {
return gulp.src(['./bower.json', './package.json'])
.pipe(plugins.if(!bumpOpt.type, plugins.prompt.prompt(bumpPrompt, function(res){ bumpOpt.type = res.bump; })))
.pipe(plugins.bump(bumpOpt).on('error', plugins.util.log))
.pipe(gulp.dest('./'));
});
and then read the version using
function getPackageJsonVersion () {
//We parse the json file instead of using require because require caches multiple calls so the version number won't be updated
return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
};
and use this function like
gulp.task('create-new-tag', function (cb) {
var version = getPackageJsonVersion();
plugins.git.tag(version, 'Created Tag for version: ' + version, function (error) {
if (error) { return cb(error); }
plugins.git.push('origin', 'master', {args: '--tags'}, cb);
});
});

gulp task can't find karma.conf.js

I am trying to run karma test via a gulp task. I use https://github.com/karma-runner/gulp-karma and for some reason gulp cannot locate my karma.conf.js. That file is located in the same folder as the gulpfile. The root of the project. No matter what path I put, I get the same error File ./karma.conf.js does not exist. I cannot figure out how to path it correctly. Here is the code for the gulp task.
gulp.task('tdd', function (done) {
new Server({
configFile: 'karma.conf.js'
}, done).start();
});
This is how I spool up karma using Gulp ( and both files are in the same root ).
var karma = require('karma');
gulp.task('karma', function (done) {
karma.server.start({
configFile: __dirname + '/karma.conf.js'
}, done);
});
UPDATE
If you are running NODE.js then
NODE Explnation for __dirname link
"The name of the directory that the currently executing script resides in."
If you are not running NODE.js, then perhaps all you needed was
configFile: '/karma.conf.js'
But if you are running NODE then use the first example.
If another destination directory is assigned to __dirname, then it doesn't work.
Try this:
var Server = require('karma').Server
gulp.task('test', function (done) {
new Server({
configFile: require('path').resolve('karma.conf.js'),
singleRun: true
}, done).start();
});

how to gulp rsync locally

I'm working on site files outside of my local htdocs that I want to deploy to the local site. I will use gulp-watch to watch for changes, but I'm stumbling on just the rsync set up. File structure:
sitename/ --
--htdocs/sites/all/themes/themename
--source/themes/themename
And here's the gulpfile:
var gulp = require('gulp');
var rsync = require('gulp-rsync');
gulp.task('deploy', function() {
gulp.src('source/**')
.pipe(rsync({
root: 'source',
destination: '/htdocs/sites/all'
}));
});
And when I run gulp deploy
[11:36:53] Using gulpfile ~/Sites/sitename/gulpfile.js
[11:36:53] Starting 'deploy'...
[11:36:53] Finished 'deploy' after 5.23 ms
Nothing is written anywhere. Am I missing something obvious...
rsync is short for "remote sync", and thus needs a destination somehwere else than your local system. If you want to synchronize stuff from one directory to the other, just use the built-in gulp methods.
gulp.task('deploy', function() {
gulp.src('source/**')
.pipe(gulp.dest('/htdocs/sites/all');
});
This will copy everything you need to the other folder. If you are looking to also delete files, add this to your watcher:
var watcher = gulp.watch('./source/**/*', ['deploy']);
watcher.on('change', function(ev) {
if(ev.type === 'deleted') {
// path.relative gives us a string where we can easily switch
// directories
del(path.relative('./', ev.path).replace('./source','/htdocs/sites/all'));
}
});