diff --git a/lib/plugins/aws/deploy/lib/uploadArtifacts.js b/lib/plugins/aws/deploy/lib/uploadArtifacts.js index 951d11ace..8d6c94556 100644 --- a/lib/plugins/aws/deploy/lib/uploadArtifacts.js +++ b/lib/plugins/aws/deploy/lib/uploadArtifacts.js @@ -2,6 +2,7 @@ /* eslint-disable no-use-before-define */ +const _ = require('lodash'); const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); @@ -9,6 +10,8 @@ const BbPromise = require('bluebird'); const filesize = require('filesize'); const normalizeFiles = require('../../lib/normalizeFiles'); +const NUM_CONCURRENT_UPLOADS = 3; + module.exports = { uploadArtifacts() { return BbPromise.bind(this) @@ -76,36 +79,36 @@ module.exports = { }, uploadFunctions() { - let shouldUploadService = false; this.serverless.cli.log('Uploading artifacts...'); + const functionNames = this.serverless.service.getAllFunctions(); - return BbPromise.map(functionNames, (name) => { - const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(name); - const functionObject = this.serverless.service.getFunction(name); - functionObject.package = functionObject.package || {}; - let artifactFilePath = functionObject.package.artifact || - this.serverless.service.package.artifact; - if (!artifactFilePath || - (this.serverless.service.artifact && !functionObject.package.artifact)) { - if (this.serverless.service.package.individually || functionObject.package.individually) { - const artifactFileName = functionArtifactFileName; - artifactFilePath = path.join(this.packagePath, artifactFileName); - return this.uploadZipFile(artifactFilePath); + const artifactFilePaths = _.uniq( + _.map(functionNames, (name) => { + const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(name); + const functionObject = this.serverless.service.getFunction(name); + functionObject.package = functionObject.package || {}; + const artifactFilePath = functionObject.package.artifact || + this.serverless.service.package.artifact; + + if (!artifactFilePath || + (this.serverless.service.artifact && !functionObject.package.artifact)) { + if (this.serverless.service.package.individually || functionObject.package.individually) { + const artifactFileName = functionArtifactFileName; + return path.join(this.packagePath, artifactFileName); + } + return this.provider.naming.getServiceArtifactName(); } - shouldUploadService = true; - return BbPromise.resolve(); - } + + return artifactFilePath; + }) + ); + + return BbPromise.map(artifactFilePaths, (artifactFilePath) => { + const stats = fs.statSync(artifactFilePath); + this.serverless.cli.log(`Uploading service .zip file to S3 (${filesize(stats.size)})...`); return this.uploadZipFile(artifactFilePath); - }, { concurrency: 3 }).then(() => { - if (shouldUploadService) { - const artifactFileName = this.provider.naming.getServiceArtifactName(); - const artifactFilePath = path.join(this.packagePath, artifactFileName); - const stats = fs.statSync(artifactFilePath); - this.serverless.cli.log(`Uploading service .zip file to S3 (${filesize(stats.size)})...`); - return this.uploadZipFile(artifactFilePath); - } - return BbPromise.resolve(); - }); + }, { concurrency: NUM_CONCURRENT_UPLOADS } + ); }, }; diff --git a/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js b/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js index 7c907b345..3168988df 100644 --- a/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js +++ b/lib/plugins/aws/deploy/lib/uploadArtifacts.test.js @@ -225,19 +225,45 @@ describe('uploadArtifacts', () => { }); describe('#uploadFunctions()', () => { + let uploadZipFileStub; + + beforeEach(() => { + sinon.stub(fs, 'statSync').returns({ size: 1024 }); + uploadZipFileStub = sinon.stub(awsDeploy, 'uploadZipFile').resolves(); + }); + + afterEach(() => { + fs.statSync.restore(); + uploadZipFileStub.restore(); + }); + it('should upload the service artifact file to the S3 bucket', () => { awsDeploy.serverless.config.servicePath = 'some/path'; awsDeploy.serverless.service.service = 'new-service'; - sinon.stub(fs, 'statSync').returns({ size: 0 }); + return awsDeploy.uploadFunctions().then(() => { + expect(uploadZipFileStub.calledOnce).to.be.equal(true); + expect(uploadZipFileStub.args[0][0]).to.be.equal('new-service.zip'); + }); + }); - const uploadZipFileStub = sinon - .stub(awsDeploy, 'uploadZipFile').resolves(); + it('should upload a single .zip file to the S3 bucket when not packaging individually', () => { + awsDeploy.serverless.service.functions = { + first: { + package: { + artifact: 'artifact.zip', + }, + }, + second: { + package: { + artifact: 'artifact.zip', + }, + }, + }; return awsDeploy.uploadFunctions().then(() => { expect(uploadZipFileStub.calledOnce).to.be.equal(true); - fs.statSync.restore(); - awsDeploy.uploadZipFile.restore(); + expect(uploadZipFileStub.args[0][0]).to.be.equal('artifact.zip'); }); }); @@ -256,16 +282,12 @@ describe('uploadArtifacts', () => { }, }; - const uploadZipFileStub = sinon - .stub(awsDeploy, 'uploadZipFile').resolves(); - return awsDeploy.uploadFunctions().then(() => { expect(uploadZipFileStub.calledTwice).to.be.equal(true); expect(uploadZipFileStub.args[0][0]) .to.be.equal(awsDeploy.serverless.service.functions.first.package.artifact); expect(uploadZipFileStub.args[1][0]) .to.be.equal(awsDeploy.serverless.service.functions.second.package.artifact); - uploadZipFileStub.restore(); }); }); @@ -284,19 +306,12 @@ describe('uploadArtifacts', () => { }, }; - const uploadZipFileStub = sinon - .stub(awsDeploy, 'uploadZipFile').resolves(); - const statSyncStub = sinon.stub(fs, 'statSync').returns({ size: 1024 }); - return awsDeploy.uploadFunctions().then(() => { expect(uploadZipFileStub.calledTwice).to.be.equal(true); expect(uploadZipFileStub.args[0][0]) .to.be.equal(awsDeploy.serverless.service.functions.first.package.artifact); expect(uploadZipFileStub.args[1][0]) .to.be.equal(awsDeploy.serverless.service.package.artifact); - }).finally(() => { - uploadZipFileStub.restore(); - statSyncStub.restore(); }); }); @@ -304,16 +319,11 @@ describe('uploadArtifacts', () => { awsDeploy.serverless.config.servicePath = 'some/path'; awsDeploy.serverless.service.service = 'new-service'; - const statSyncStub = sinon.stub(fs, 'statSync').returns({ size: 1024 }); - const uploadZipFileStub = sinon.stub(awsDeploy, 'uploadZipFile').resolves(); sinon.spy(awsDeploy.serverless.cli, 'log'); return awsDeploy.uploadFunctions().then(() => { const expected = 'Uploading service .zip file to S3 (1 KB)...'; expect(awsDeploy.serverless.cli.log.calledWithExactly(expected)).to.be.equal(true); - }).finally(() => { - statSyncStub.restore(); - uploadZipFileStub.restore(); }); }); });