Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ you should use any version `<5.5 >=5.7.1` as the versions in-between have some n

Right now there are no `packagerOptions` that can be set with NPM.

#### Yarn
##### Yarn

Using yarn will switch the whole packaging pipeline to use yarn, so does it use a `yarn.lock` file.

Expand All @@ -284,6 +284,28 @@ The yarn packager supports the following `packagerOptions`:
|---------------|------|---------|-------------|
| ignoreScripts | bool | true | Do not execute package.json hook scripts on install |

##### Common packager options

There are some settings that are common to all packagers and affect the packaging itself.

###### Custom scripts

You can specify custom scripts that are executed after the installation of the function/service packages
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
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`.

```yaml
custom:
webpack:
packagerOptions:
scripts:
- npm rebuild grpc --target=6.1.0 --target_arch=x64 --target_platform=linux --target_libc=glibc
```

#### Forced inclusion

Sometimes it might happen that you use dynamic requires in your code, i.e. you
Expand Down
18 changes: 17 additions & 1 deletion lib/packExternalModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ module.exports = {
const packageForceExcludes = _.get(includes, 'forceExclude', []);
const packagePath = includes.packagePath || './package.json';
const packageJsonPath = path.join(process.cwd(), packagePath);
const packageScripts = _.reduce(this.configuration.packagerOptions.scripts || [], (__, script, index) => {
__[`script${index}`] = script;
return __;
}, {});

// Determine and create packager
return BbPromise.try(() => Packagers.get.call(this, this.configuration.packager))
Expand Down Expand Up @@ -228,7 +232,8 @@ module.exports = {
name: this.serverless.service.service,
version: '1.0.0',
description: `Packaged externals for ${this.serverless.service.service}`,
private: true
private: true,
scripts: packageScripts
};
const relPath = path.relative(compositeModulePath, path.dirname(packageJsonPath));
addModulesToPackageJson(compositeModules, compositePackage, relPath);
Expand Down Expand Up @@ -276,6 +281,11 @@ module.exports = {
// Create package.json
const modulePackageJson = path.join(modulePath, 'package.json');
const modulePackage = {
name: this.serverless.service.service,
version: '1.0.0',
description: `Packaged externals for ${this.serverless.service.service}`,
private: true,
scripts: packageScripts,
dependencies: {}
};
const prodModules = getProdModules.call(this,
Expand Down Expand Up @@ -312,6 +322,12 @@ module.exports = {
const startPrune = _.now();
return packager.prune(modulePath, maxExecBufferSize, this.configuration.packagerOptions)
.tap(() => this.options.verbose && this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`));
})
.then(() => {
// Prune extraneous packages - removes not needed ones
const startRunScripts = _.now();
return packager.runScripts(modulePath, maxExecBufferSize, _.keys(packageScripts))
.tap(() => this.options.verbose && this.serverless.cli.log(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`));
});
})
.return();
Expand Down
1 change: 1 addition & 0 deletions lib/packagers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* static rebaseLockfile(pathToPackageRoot: string, lockfile: Object): void;
* static install(cwd: string, maxExecBufferSize = undefined): BbPromise<void>;
* static prune(cwd: string): BbPromise<void>;
* static runScripts(cwd: string, maxExecBufferSize, scriptNames): BbPromise<void>;
*
* }
*/
Expand Down
11 changes: 11 additions & 0 deletions lib/packagers/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ class NPM {
})
.return();
}

static runScripts(cwd, maxExecBufferSize, scriptNames) {
return BbPromise.mapSeries(scriptNames, scriptName => BbPromise.fromCallback(cb => {
childProcess.exec(`npm run ${scriptName}`, {
cwd: cwd,
maxBuffer: maxExecBufferSize,
encoding: 'utf8'
}, cb);
}))
.return();
}
}

module.exports = NPM;
30 changes: 30 additions & 0 deletions lib/packagers/npm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,36 @@ describe('npm', () => {
});
});

describe('runScripts', () => {
it('should use npm run for the given scripts', () => {
childProcessMock.exec.yields(null, 'success', '');
return expect(npmModule.runScripts('myPath', 2000, [ 's1', 's2' ])).to.be.fulfilled
.then(result => {
expect(result).to.be.undefined;
expect(childProcessMock.exec).to.have.been.calledTwice;
expect(childProcessMock.exec.firstCall).to.have.been.calledWithExactly(
'npm run s1',
{
cwd: 'myPath',
encoding: 'utf8',
maxBuffer: 2000
},
sinon.match.any
);
expect(childProcessMock.exec.secondCall).to.have.been.calledWithExactly(
'npm run s2',
{
cwd: 'myPath',
encoding: 'utf8',
maxBuffer: 2000
},
sinon.match.any
);
return null;
});
});
});

describe('getProdDependencies', () => {
it('should use npm ls', () => {
childProcessMock.exec.yields(null, '{}', '');
Expand Down
11 changes: 11 additions & 0 deletions lib/packagers/yarn.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ class Yarn {
static prune(cwd, maxExecBufferSize, packagerOptions) {
return Yarn.install(cwd, maxExecBufferSize, packagerOptions);
}

static runScripts(cwd, maxExecBufferSize, scriptNames) {
return BbPromise.mapSeries(scriptNames, scriptName => BbPromise.fromCallback(cb => {
childProcess.exec(`yarn run ${scriptName}`, {
cwd: cwd,
maxBuffer: maxExecBufferSize,
encoding: 'utf8'
}, cb);
}))
.return();
}
}

module.exports = Yarn;
30 changes: 30 additions & 0 deletions lib/packagers/yarn.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,34 @@ describe('yarn', () => {
});
});

describe('runScripts', () => {
it('should use yarn run for the given scripts', () => {
childProcessMock.exec.yields(null, 'success', '');
return expect(yarnModule.runScripts('myPath', 2000, [ 's1', 's2' ])).to.be.fulfilled
.then(result => {
expect(result).to.be.undefined;
expect(childProcessMock.exec).to.have.been.calledTwice;
expect(childProcessMock.exec.firstCall).to.have.been.calledWithExactly(
'yarn run s1',
{
cwd: 'myPath',
encoding: 'utf8',
maxBuffer: 2000
},
sinon.match.any
);
expect(childProcessMock.exec.secondCall).to.have.been.calledWithExactly(
'yarn run s2',
{
cwd: 'myPath',
encoding: 'utf8',
maxBuffer: 2000
},
sinon.match.any
);
return null;
});
});
});

});
Loading