Skip to content

Commit

Permalink
Merge pull request #876 from FatalTouch/non-node-packaging-fix-2021-0…
Browse files Browse the repository at this point in the history
…6-10

Fix packaging for non-node functions
  • Loading branch information
j0k3r authored Jun 10, 2021
2 parents dab8ef3 + b4a7014 commit 69db76d
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 32 deletions.
5 changes: 3 additions & 2 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ describe('ServerlessWebpack', () => {

before(() => {
slsw = new ServerlessWebpack(serverless, rawOptions);
if(serverless.processedInput) { // serverless.processedInput does not exist in serverless@<2.0.0
if (serverless.processedInput) {
// serverless.processedInput does not exist in serverless@<2.0.0
serverless.processedInput.options = processedOptions;
}
sandbox.stub(slsw, 'cleanup').returns(BbPromise.resolve());
Expand Down Expand Up @@ -477,7 +478,7 @@ describe('ServerlessWebpack', () => {
test: () => {
it('should override the raw options with the processed ones', () => {
slsw.hooks.initialize();
if(serverless.processedInput) {
if (serverless.processedInput) {
expect(slsw.options).to.equal(processedOptions);
} else {
// serverless.processedInput does not exist in serverless@<2.0.0
Expand Down
3 changes: 2 additions & 1 deletion lib/packageModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { nativeZip, nodeZip, hasNativeZip } = require('bestzip');
const glob = require('glob');
const semver = require('semver');
const fs = require('fs');
const { getAllNodeFunctions } = require('./utils');

function setArtifactPath(funcName, func, artifactPath) {
const version = this.serverless.getVersion();
Expand Down Expand Up @@ -150,7 +151,7 @@ module.exports = {
this.serverless.cli.log('Copying existing artifacts...');
// When invoked as a part of `deploy function`,
// only function passed with `-f` flag should be processed.
const functionNames = this.options.function ? [this.options.function] : this.serverless.service.getAllFunctions();
const functionNames = this.options.function ? [this.options.function] : getAllNodeFunctions.call(this);

// Copy artifacts to package location
if (isIndividialPackaging.call(this)) {
Expand Down
12 changes: 11 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,22 @@ function splitLines(str) {
return _.split(str, /\r?\n/);
}

function getAllNodeFunctions() {
const functions = this.serverless.service.getAllFunctions();
return _.filter(functions, funcName => {
const func = this.serverless.service.getFunction(funcName);
const runtime = func.runtime || this.serverless.service.provider.runtime || 'nodejs';
return runtime.match(/node/);
});
}

module.exports = {
guid,
purgeCache,
searchAndProcessCache,
SpawnError,
spawnProcess,
safeJsonParse,
splitLines
splitLines,
getAllNodeFunctions
};
30 changes: 12 additions & 18 deletions lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const glob = require('glob');
const lib = require('./index');
const _ = require('lodash');
const Configuration = require('./Configuration');
const { getAllNodeFunctions } = require('./utils');

/**
* For automatic entry detection we sort the found files to solve ambiguities.
Expand Down Expand Up @@ -109,7 +110,7 @@ module.exports = {
// Expose entries - must be done before requiring the webpack configuration
const entries = {};

const functions = this.serverless.service.getAllFunctions();
const functions = getAllNodeFunctions.call(this);
if (this.options.function) {
const serverlessFunction = this.serverless.service.getFunction(this.options.function);
const entry = getEntryForFunction.call(this, this.options.function, serverlessFunction);
Expand Down Expand Up @@ -222,23 +223,16 @@ module.exports = {
}

// Lookup associated Serverless functions
const allEntryFunctions = _.map(
_.filter(this.serverless.service.getAllFunctions(), funcName => {
const func = this.serverless.service.getFunction(funcName);
const runtime = func.runtime || this.serverless.service.provider.runtime || 'nodejs';
return runtime.match(/node/);
}),
funcName => {
const func = this.serverless.service.getFunction(funcName);
const handler = getHandlerFileAndFunctionName(func);
const handlerFile = path.relative('.', getHandlerFile(handler));
return {
handlerFile,
funcName,
func
};
}
);
const allEntryFunctions = _.map(getAllNodeFunctions.call(this), funcName => {
const func = this.serverless.service.getFunction(funcName);
const handler = getHandlerFileAndFunctionName(func);
const handlerFile = path.relative('.', getHandlerFile(handler));
return {
handlerFile,
funcName,
func
};
});

this.entryFunctions = _.flatMap(entries, (value, key) => {
const entry = path.relative('.', value);
Expand Down
6 changes: 3 additions & 3 deletions lib/wpwatch.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ module.exports = {
callback();
} else if (canEmit && currentCompileWatch === null) {
// eslint-disable-next-line promise/no-promise-in-callback
currentCompileWatch = BbPromise.resolve(
this.serverless.pluginManager.spawn('webpack:compile:watch')
).then(() => this.serverless.cli.log('Watching for changes...'));
currentCompileWatch = BbPromise.resolve(this.serverless.pluginManager.spawn('webpack:compile:watch')).then(
() => this.serverless.cli.log('Watching for changes...')
);
}
});
};
Expand Down
1 change: 0 additions & 1 deletion tests/compile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ describe('compile', () => {
webpackMock.compilerMock.run.reset();
webpackMock.compilerMock.run.yields(null, multiStats);
return expect(module.compile()).to.be.fulfilled.then(() => {
console.log(JSON.stringify(module.compileStats.stats[0].externalModules));
expect(module.compileStats.stats[0].externalModules).to.eql([
{ external: '@scoped/vendor', origin: undefined },
{ external: 'uuid', origin: undefined },
Expand Down
20 changes: 17 additions & 3 deletions tests/packageModules.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,14 +445,21 @@ describe('packageModules', () => {
});

describe('copyExistingArtifacts()', () => {
const allFunctions = [ 'func1', 'func2' ];
const allFunctions = [ 'func1', 'func2', 'funcPython' ];
const func1 = {
handler: 'src/handler1',
events: []
};
const func2 = {
handler: 'src/handler2',
events: []
events: [],
runtime: 'node14'
};

const funcPython = {
handler: 'src/handlerPython',
events: [],
runtime: 'python3.7'
};

const entryFunctions = [
Expand All @@ -465,6 +472,11 @@ describe('packageModules', () => {
handlerFile: 'src/handler2.js',
funcName: 'func2',
func: func2
},
{
handlerFile: 'src/handlerPython.js',
funcName: 'funcPython',
func: funcPython
}
];

Expand All @@ -483,6 +495,7 @@ describe('packageModules', () => {
getAllFunctionsStub.returns(allFunctions);
getFunctionStub.withArgs('func1').returns(func1);
getFunctionStub.withArgs('func2').returns(func2);
getFunctionStub.withArgs('funcPython').returns(funcPython);
});

it('copies the artifact', () => {
Expand Down Expand Up @@ -624,9 +637,10 @@ describe('packageModules', () => {
getAllFunctionsStub.returns(allFunctions);
getFunctionStub.withArgs('func1').returns(func1);
getFunctionStub.withArgs('func2').returns(func2);
getFunctionStub.withArgs('funcPython').returns(funcPython);
});

it('copies each artifact', () => {
it('copies each node artifact', () => {
const expectedFunc1Destination = path.join('.serverless', 'func1.zip');
const expectedFunc2Destination = path.join('.serverless', 'func2.zip');

Expand Down
47 changes: 44 additions & 3 deletions tests/validate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ describe('validate', () => {
});
});

it('should allow custom runtime', () => {
it('should ignore non-node runtimes', () => {
const testOutPath = 'test';
const testFunctionsConfig = {
func1: {
Expand Down Expand Up @@ -683,17 +683,58 @@ describe('validate', () => {
const lib = require('../lib/index');
const expectedLibEntries = {
module1: './module1.js',
module2: './module2.js',
module4: './module4.js'
};

expect(lib.entries).to.deep.equal(expectedLibEntries);
expect(globSyncStub).to.have.callCount(3);
expect(globSyncStub).to.have.callCount(2);
expect(serverless.cli.log).to.not.have.been.called;
return null;
});
});

it('should throw error if container image is not well defined', () => {
const testOutPath = 'test';
const testFunctionsConfig = {
func1: {
artifact: 'artifact-func1.zip',
events: [
{
http: {
method: 'POST',
path: 'func1path'
}
},
{
nonhttp: 'non-http'
}
],
image: {
name: 'custom-image',
command: []
}
}
};

const testConfig = {
entry: 'test',
context: 'testcontext',
output: {
path: testOutPath
},
getFunction: func => {
return testFunctionsConfig[func];
}
};

_.set(module.serverless.service, 'custom.webpack.config', testConfig);
module.serverless.service.functions = testFunctionsConfig;
globSyncStub.callsFake(filename => [_.replace(filename, '*', 'js')]);
expect(() => {
module.validate();
}).to.throw(/Either function.handler or function.image must be defined/);
});

describe('google provider', () => {
beforeEach(() => {
_.set(module.serverless, 'service.provider.name', 'google');
Expand Down

0 comments on commit 69db76d

Please sign in to comment.