Skip to content

Commit

Permalink
Merge pull request #612 from serverless-heaven/feature/exclude-regex
Browse files Browse the repository at this point in the history
Option to exclude files using regular expression
  • Loading branch information
miguel-a-calles-mba committed Jul 26, 2020
2 parents 36994a3 + 467decd commit a114524
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 8 deletions.
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`
Expand Down Expand Up @@ -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`.

Expand Down Expand Up @@ -439,7 +439,7 @@ If you have a project structure that uses something like `index.js` and a
co-located `index.test.js` then you have likely seen an error like:
`WARNING: More than one matching handlers found for index. Using index.js`

This config option allows you to exlcude files that match a glob from function
This config option allows you to exclude files that match a glob from function
resolution. Just add: `excludeFiles: **/*.test.js` (with whatever glob you want
to exclude).

Expand All @@ -452,6 +452,19 @@ custom:

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
regex you want to exclude).

```yaml
# serverless.yml
custom:
webpack:
excludeRegex: /\.ts|test|\.map/
```

#### Keep output directory after packaging

You can keep the output directory (defaults to `.webpack`) from being removed
Expand Down
4 changes: 4 additions & 0 deletions lib/Configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class Configuration {
get excludeFiles() {
return this._config.excludeFiles;
}

get excludeRegex() {
return this._config.excludeRegex;
}

get packager() {
return this._config.packager;
Expand Down
6 changes: 5 additions & 1 deletion lib/packageModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ function zip(directory, name) {

const output = fs.createWriteStream(artifactFilePath);

const files = glob.sync('**', {
let files = glob.sync('**', {
cwd: directory,
dot: true,
silent: true,
follow: true
});

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');
return BbPromise.reject(error);
Expand Down
52 changes: 51 additions & 1 deletion tests/packageModules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -73,7 +74,8 @@ describe('packageModules', () => {
{
serverless,
options: {},
webpackOutputPath: '.webpack'
webpackOutputPath: '.webpack',
configuration: new Configuration()
},
baseModule
);
Expand Down Expand Up @@ -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 excluded 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', () => {
Expand Down

0 comments on commit a114524

Please sign in to comment.