diff --git a/bin/helpers/buildArtifacts.js b/bin/helpers/buildArtifacts.js index e4aacd6b..6f361af9 100644 --- a/bin/helpers/buildArtifacts.js +++ b/bin/helpers/buildArtifacts.js @@ -10,7 +10,7 @@ const logger = require('./logger').winstonLogger, const request = require('request'); const decompress = require('decompress'); - +const unzipper = require("unzipper"); let BUILD_ARTIFACTS_TOTAL_COUNT = 0; let BUILD_ARTIFACTS_FAIL_COUNT = 0; @@ -121,13 +121,15 @@ const downloadAndUnzip = async (filePath, fileName, url) => { reject(err); }); writer.on('close', async () => { - if (!error) { - await unzipFile(filePath, fileName); - fs.unlinkSync(tmpFilePath); - resolve(true); + try { + if (!error) { + await unzipFile(filePath, fileName); + fs.unlinkSync(tmpFilePath); + } + } catch (error) { + reject(error); } - //no need to call the reject here, as it will have been called in the - //'error' stream; + resolve(true); }); } }); @@ -136,13 +138,25 @@ const downloadAndUnzip = async (filePath, fileName, url) => { const unzipFile = async (filePath, fileName) => { return new Promise( async (resolve, reject) => { - await decompress(path.join(filePath, fileName), filePath) - .then((files) => { + try { + await decompress(path.join(filePath, fileName), filePath); resolve(); - }) - .catch((error) => { - reject(error); - }); + } catch (error) { + logger.debug(`Error unzipping with decompress, trying with unzipper. Stacktrace: ${error}.`); + try { + fs.createReadStream(path.join(filePath, fileName)) + .pipe(unzipper.Extract({ path: filePath })) + .on("close", () => { + resolve(); + }) + .on("error", (err) => { + reject(err); + }); + } catch (unzipperError) { + logger.debug(`Unzipper package error: ${unzipperError}`); + reject(Constants.userMessages.BUILD_ARTIFACTS_UNZIP_FAILURE); + } + } }); } diff --git a/bin/helpers/constants.js b/bin/helpers/constants.js index deba24db..a19f188d 100644 --- a/bin/helpers/constants.js +++ b/bin/helpers/constants.js @@ -123,7 +123,8 @@ const userMessages = { CYPRESS_PORT_WARNING: "The requested port number is ignored. The default BrowserStack port will be used for this execution", CYPRESS_INTERACTIVE_SESSION_CONFLICT_VALUES: - "Conflicting values (True & False) were found for the interactive_debugging capability. Please resolve this issue to proceed further." + "Conflicting values (True & False) were found for the interactive_debugging capability. Please resolve this issue to proceed further.", + BUILD_ARTIFACTS_UNZIP_FAILURE: "Failed to unzip build artifacts.", }; const validationMessages = { diff --git a/package.json b/package.json index 01975ee0..e8895ffc 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "windows-release": "^5.1.0", "winston": "2.4.4", "yargs": "14.2.3", - "decompress": "4.2.1" + "decompress": "4.2.1", + "unzipper": "^0.12.3" }, "repository": { "type": "git", diff --git a/test/unit/bin/helpers/buildArtifacts.js b/test/unit/bin/helpers/buildArtifacts.js new file mode 100644 index 00000000..08d2ef1a --- /dev/null +++ b/test/unit/bin/helpers/buildArtifacts.js @@ -0,0 +1,60 @@ +const { expect } = require("chai"); +const chai = require("chai"), + chaiAsPromised = require("chai-as-promised"), + sinon = require('sinon'), + rewire = require('rewire'); + +const logger = require("../../../../bin/helpers/logger").winstonLogger; + +chai.use(chaiAsPromised); +logger.transports["console.info"].silent = true; + +describe('unzipFile', () => { + let unzipFile; + let decompressStub; + let createReadStreamStub; + let unzipperStub; + let loggerStub; + let pathJoinStub; + let Constants; + + const filePath = '/some/path'; + const fileName = 'file.zip'; + + beforeEach(() => { + const unzipFileModule = rewire('../../../../bin/helpers/buildArtifacts'); + + decompressStub = sinon.stub(); + createReadStreamStub = sinon.stub(); + unzipperStub = { + Extract: sinon.stub(), + }; + loggerStub = { debug: sinon.stub() }; + pathJoinStub = sinon.stub().returns(`${filePath}/${fileName}`); + + Constants = { + userMessages: { + BUILD_ARTIFACTS_UNZIP_FAILURE: 'Unzip failed', + }, + }; + + // Injecting the dependencies + unzipFileModule.__set__('decompress', decompressStub); + unzipFileModule.__set__('fs.createReadStream', createReadStreamStub); + unzipFileModule.__set__('unzipper', unzipperStub); + unzipFileModule.__set__('logger', loggerStub); + unzipFileModule.__set__('path.join', pathJoinStub); + unzipFileModule.__set__('Constants', Constants); + + unzipFile = unzipFileModule.__get__('unzipFile'); + }); + + it('should successfully unzip using decompress', async () => { + decompressStub.resolves(); + + await unzipFile(filePath, fileName); + + expect(decompressStub.calledWith(`${filePath}/${fileName}`, filePath)).to.be.true; + }); + +});