diff --git a/README.md b/README.md index 835cfc836d..fda744cd4d 100644 --- a/README.md +++ b/README.md @@ -305,17 +305,17 @@ custom: #### Runtime dependencies If a runtime dependency is detected that is found in the `devDependencies` section and -so would not be packaged, the plugin will error until you explicitly exclude it (see `forceExclude` below) +so would not be packaged, the plugin will error until you explicitly exclude it (see `forceExclude` below) or move it to the `dependencies` section. #### AWS-SDK An exception for the runtime dependency error is the AWS-SDK. All projects using the AWS-SDK normally -have it listed in `devDependencies` because AWS provides it already in their Lambda environment. In this case +have it listed in `devDependencies` because AWS provides it already in their Lambda environment. In this case the aws-sdk is automatically excluded and only an informational message is printed (in `--verbose` mode). The main reason for the warning is, that silently ignoring anything contradicts the declarative nature -of Serverless' service definition. So the correct way to define the handling for the aws-sdk is, as +of Serverless' service definition. So the correct way to define the handling for the aws-sdk is, as you would do for all other excluded modules (see `forceExclude` below). ```yaml @@ -342,7 +342,7 @@ custom: ``` You should select the packager, that you use to develop your projects, because only -then locked versions will be handled correctly, i.e. the plugin uses the generated +then locked versions will be handled correctly, i.e. the plugin uses the generated (and usually committed) package lock file that is created by your favorite packager. Each packager might support specific options that can be set in the `packagerOptions` @@ -375,7 +375,7 @@ You can specify custom scripts that are executed after the installation of the f has been finished. These are standard packager scripts as they can be used in any `package.json`. Warning: The use cases for them are very rare and specific and you should investigate first, -if your use case can be covered with webpack plugins first. They should never access files +if your use case can be covered with webpack plugins first. They should never access files outside of their current working directory which is the compiled function folder, if any. A valid use case would be to start anything available as binary from `node_modules`. @@ -455,14 +455,14 @@ This is also useful for projects that use TypeScript. #### Exclude Files with Regular Expression This config option allows you to filter files that match a regex pattern before -adding to the zip file. Just add: `excludeRegex: \.ts|test|\.map` (with whatever +adding to the zip file. Just add: `excludeRegex: \.ts|test|\.map` (with whatever regex you want to exclude). ```yaml # serverless.yml custom: webpack: - excludeRegex: \.ts|test|\.map + excludeRegex: /\.ts|test|\.map/ ``` #### Keep output directory after packaging diff --git a/lib/packageModules.js b/lib/packageModules.js index ff7bda5683..4d6eac5f22 100644 --- a/lib/packageModules.js +++ b/lib/packageModules.js @@ -40,8 +40,10 @@ function zip(directory, name) { silent: true, follow: true }); - - if (this.configuration.excludeRegex) files = files.filter(f => f.match(this.configuration.excludeRegex) === null); + + if (this.configuration.excludeRegex) { + files = _.filter(files, f => f.match(this.configuration.excludeRegex) === null); + } if (_.isEmpty(files)) { const error = new this.serverless.classes.Error('Packaging: No files found'); diff --git a/tests/packageModules.test.js b/tests/packageModules.test.js index 514a230ec6..1875e13ac9 100644 --- a/tests/packageModules.test.js +++ b/tests/packageModules.test.js @@ -7,6 +7,7 @@ const path = require('path'); const sinon = require('sinon'); const mockery = require('mockery'); const Serverless = require('serverless'); +const Configuration = require('../lib/Configuration'); // Mocks const fsMockFactory = require('./mocks/fs.mock'); @@ -73,7 +74,8 @@ describe('packageModules', () => { { serverless, options: {}, - webpackOutputPath: '.webpack' + webpackOutputPath: '.webpack', + configuration: new Configuration() }, baseModule ); @@ -308,6 +310,54 @@ describe('packageModules', () => { module.compileStats = stats; return expect(module.packageModules()).to.be.rejectedWith('Packaging: No files found'); }); + + it('should reject if no files are found because all files are exlucded using regex', () => { + module.configuration = new Configuration({ + webpack: { + excludeRegex: /.*/ + } + }); + + // Test data + const stats = { + stats: [ + { + compilation: { + compiler: { + outputPath: '/my/Service/Path/.webpack/service' + } + } + } + ] + }; + const files = [ 'README.md', 'src/handler1.js', 'src/handler1.js.map', 'src/handler2.js', 'src/handler2.js.map' ]; + const allFunctions = [ 'func1', 'func2' ]; + const func1 = { + handler: 'src/handler1', + events: [] + }; + const func2 = { + handler: 'src/handler2', + events: [] + }; + // Serverless behavior + sandbox.stub(serverless.config, 'servicePath').value('/my/Service/Path'); + getVersionStub.returns('1.18.0'); + getServiceObjectStub.returns({ + name: 'test-service' + }); + getAllFunctionsStub.returns(allFunctions); + getFunctionStub.withArgs('func1').returns(func1); + getFunctionStub.withArgs('func2').returns(func2); + // Mock behavior + globMock.sync.returns(files); + fsMock._streamMock.on.withArgs('open').yields(); + fsMock._streamMock.on.withArgs('close').yields(); + fsMock._statMock.isDirectory.returns(false); + + module.compileStats = stats; + return expect(module.packageModules()).to.be.rejectedWith('Packaging: No files found'); + }); }); describe('with individual packaging', () => {