Skip to content

Commit a2e8a4f

Browse files
Merge branch 'master' of github.com:browserstack/browserstack-cypress-cli into ACE_2714_env
2 parents 4620a0f + 0040ad8 commit a2e8a4f

File tree

15 files changed

+743
-169
lines changed

15 files changed

+743
-169
lines changed

bin/commands/runs.js

Lines changed: 92 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const archiver = require("../helpers/archiver"),
99
utils = require("../helpers/utils"),
1010
fileHelpers = require("../helpers/fileHelpers"),
1111
syncRunner = require("../helpers/syncRunner"),
12+
checkUploaded = require("../helpers/checkUploaded"),
1213
reportGenerator = require('../helpers/reporterHTML').reportGenerator,
1314
{initTimeComponents, markBlockStart, markBlockEnd, getTimeComponents} = require('../helpers/timeComponents');
1415

@@ -81,107 +82,115 @@ module.exports = function run(args) {
8182

8283
// warn if specFiles cross our limit
8384
utils.warnSpecLimit(bsConfig, args, specFiles);
84-
8585
markBlockEnd('preArchiveSteps');
86-
// Archive the spec files
87-
markBlockStart('zip');
88-
markBlockStart('zip.archive');
89-
return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude).then(function (data) {
90-
91-
markBlockEnd('zip.archive');
92-
// Uploaded zip file
93-
markBlockStart('zip.zipUpload');
94-
return zipUploader.zipUpload(bsConfig, config.fileName).then(async function (zip) {
95-
96-
markBlockEnd('zip.zipUpload');
97-
markBlockEnd('zip');
98-
// Create build
99-
100-
//setup Local Testing
101-
markBlockStart('localSetup');
102-
let bs_local = await utils.setupLocalTesting(bsConfig, args);
103-
markBlockEnd('localSetup');
104-
markBlockStart('createBuild');
105-
return build.createBuild(bsConfig, zip).then(function (data) {
106-
markBlockEnd('createBuild');
107-
markBlockEnd('total');
108-
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
109-
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
110-
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
111-
if ((utils.isUndefined(bsConfig.run_settings.parallels) && utils.isUndefined(args.parallels)) || (!utils.isUndefined(bsConfig.run_settings.parallels) && bsConfig.run_settings.parallels == Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE)) {
112-
logger.warn(Constants.userMessages.NO_PARALLELS);
113-
}
86+
markBlockStart('checkAlreadyUploaded');
87+
return checkUploaded.checkUploadedMd5(bsConfig, args).then(function (md5data) {
88+
markBlockEnd('checkAlreadyUploaded');
89+
90+
// Archive the spec files
91+
markBlockStart('zip');
92+
markBlockStart('zip.archive');
93+
return archiver.archive(bsConfig.run_settings, config.fileName, args.exclude, md5data).then(function (data) {
94+
markBlockEnd('zip.archive');
95+
96+
// Uploaded zip file
97+
markBlockStart('zip.zipUpload');
98+
return zipUploader.zipUpload(bsConfig, config.fileName, md5data).then(async function (zip) {
99+
markBlockEnd('zip.zipUpload');
100+
markBlockEnd('zip');
101+
// Create build
102+
103+
//setup Local Testing
104+
markBlockStart('localSetup');
105+
let bs_local = await utils.setupLocalTesting(bsConfig, args);
106+
markBlockEnd('localSetup');
107+
markBlockStart('createBuild');
108+
return build.createBuild(bsConfig, zip).then(function (data) {
109+
markBlockEnd('createBuild');
110+
markBlockEnd('total');
111+
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
112+
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
113+
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
114+
if ((utils.isUndefined(bsConfig.run_settings.parallels) && utils.isUndefined(args.parallels)) || (!utils.isUndefined(bsConfig.run_settings.parallels) && bsConfig.run_settings.parallels == Constants.cliMessages.RUN.DEFAULT_PARALLEL_MESSAGE)) {
115+
logger.warn(Constants.userMessages.NO_PARALLELS);
116+
}
114117

115-
if (bsConfig.run_settings.cypress_version && bsConfig.run_settings.cypress_version !== data.cypress_version) {
116-
let versionMessage = utils.versionChangedMessage(bsConfig.run_settings.cypress_version, data.cypress_version)
117-
logger.warn(versionMessage);
118-
}
118+
if (bsConfig.run_settings.cypress_version && bsConfig.run_settings.cypress_version !== data.cypress_version) {
119+
let versionMessage = utils.versionChangedMessage(bsConfig.run_settings.cypress_version, data.cypress_version)
120+
logger.warn(versionMessage);
121+
}
119122

120-
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) {
121-
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
122-
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES_READ_MORE);
123-
}
123+
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) {
124+
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
125+
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES_READ_MORE);
126+
}
124127

125-
if (args.sync) {
126-
syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => {
128+
if (args.sync) {
129+
syncRunner.pollBuildStatus(bsConfig, data).then(async (exitCode) => {
127130

128-
// stop the Local instance
129-
await utils.stopLocalBinary(bsConfig, bs_local, args);
131+
// stop the Local instance
132+
await utils.stopLocalBinary(bsConfig, bs_local, args);
130133

131-
// Generate custom report!
132-
reportGenerator(bsConfig, data.build_id, args, function(){
133-
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
134-
utils.handleSyncExit(exitCode, data.dashboard_url);
134+
// Generate custom report!
135+
reportGenerator(bsConfig, data.build_id, args, function(){
136+
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
137+
utils.handleSyncExit(exitCode, data.dashboard_url);
138+
});
135139
});
136-
});
137-
}
138-
139-
logger.info(message);
140-
logger.info(dashboardLink);
141-
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
142-
let dataToSend = {
143-
time_components: getTimeComponents(),
144-
build_id: data.build_id,
145-
};
146-
if (bsConfig && bsConfig.connection_settings) {
147-
if (bsConfig.connection_settings.local_mode) {
148-
dataToSend.local_mode = bsConfig.connection_settings.local_mode;
149140
}
150-
if (bsConfig.connection_settings.usedAutoLocal) {
151-
dataToSend.used_auto_local = bsConfig.connection_settings.usedAutoLocal;
141+
142+
logger.info(message);
143+
logger.info(dashboardLink);
144+
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
145+
let dataToSend = {
146+
time_components: getTimeComponents(),
147+
build_id: data.build_id,
148+
};
149+
if (bsConfig && bsConfig.connection_settings) {
150+
if (bsConfig.connection_settings.local_mode) {
151+
dataToSend.local_mode = bsConfig.connection_settings.local_mode;
152+
}
153+
if (bsConfig.connection_settings.usedAutoLocal) {
154+
dataToSend.used_auto_local = bsConfig.connection_settings.usedAutoLocal;
155+
}
152156
}
153-
}
154-
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null, dataToSend);
155-
return;
156-
}).catch(async function (err) {
157-
// Build creation failed
157+
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null, dataToSend);
158+
return;
159+
}).catch(async function (err) {
160+
// Build creation failed
161+
logger.error(err);
162+
// stop the Local instance
163+
await utils.stopLocalBinary(bsConfig, bs_local, args);
164+
165+
utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed');
166+
});
167+
}).catch(function (err) {
168+
// Zip Upload failed | Local Start failed
158169
logger.error(err);
159-
// stop the Local instance
160-
await utils.stopLocalBinary(bsConfig, bs_local, args);
161-
162-
utils.sendUsageReport(bsConfig, args, err, Constants.messageTypes.ERROR, 'build_failed');
170+
if(err === Constants.userMessages.LOCAL_START_FAILED){
171+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.LOCAL_START_FAILED}`, Constants.messageTypes.ERROR, 'local_start_failed');
172+
} else {
173+
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
174+
fileHelpers.deleteZip();
175+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
176+
}
163177
});
164178
}).catch(function (err) {
165-
// Zip Upload failed | Local Start failed
179+
// Zipping failed
166180
logger.error(err);
167-
if(err === Constants.userMessages.LOCAL_START_FAILED){
168-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.LOCAL_START_FAILED}`, Constants.messageTypes.ERROR, 'local_start_failed');
169-
} else {
170-
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
181+
logger.error(Constants.userMessages.FAILED_TO_ZIP);
182+
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.FAILED_TO_ZIP}`, Constants.messageTypes.ERROR, 'zip_creation_failed');
183+
try {
171184
fileHelpers.deleteZip();
172-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
185+
} catch (err) {
186+
utils.sendUsageReport(bsConfig, args, Constants.userMessages.ZIP_DELETE_FAILED, Constants.messageTypes.ERROR, 'zip_deletion_failed');
173187
}
174188
});
175189
}).catch(function (err) {
176-
// Zipping failed
190+
// md5 check failed
177191
logger.error(err);
178-
logger.error(Constants.userMessages.FAILED_TO_ZIP);
179-
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.FAILED_TO_ZIP}`, Constants.messageTypes.ERROR, 'zip_creation_failed');
180-
try {
181-
fileHelpers.deleteZip();
182-
} catch (err) {
183-
utils.sendUsageReport(bsConfig, args, Constants.userMessages.ZIP_DELETE_FAILED, Constants.messageTypes.ERROR, 'zip_deletion_failed');
184-
}
192+
logger.error(Constants.userMessages.FAILED_MD5_CHECK);
193+
utils.sendUsageReport(bsConfig, args, Constants.userMessages.MD5_CHECK_FAILED, Constants.messageTypes.ERROR, 'zip_already_uploaded_failed');
185194
});
186195
}).catch(function (err) {
187196
// browerstack.json is not valid

bin/helpers/archiver.js

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ const archiver = require("archiver"),
77
utils = require('../helpers/utils'),
88
path = require('path');
99

10-
const archiveSpecs = (runSettings, filePath, excludeFiles) => {
10+
const archiveSpecs = (runSettings, filePath, excludeFiles, md5data) => {
1111
return new Promise(function (resolve, reject) {
12+
if (md5data.zipUrlPresent) {
13+
return resolve('Zipping not required');
14+
}
1215
var output = fs.createWriteStream(filePath);
1316

1417
var cypressFolderPath = path.dirname(runSettings.cypressConfigFilePath);
@@ -41,8 +44,7 @@ const archiveSpecs = (runSettings, filePath, excludeFiles) => {
4144

4245
archive.pipe(output);
4346

44-
let ignoreFiles = getFilesToIgnore(runSettings, excludeFiles);
45-
47+
let ignoreFiles = utils.getFilesToIgnore(runSettings, excludeFiles);
4648
archive.glob(`**/*.+(${Constants.allowedFileTypes.join("|")})`, { cwd: cypressFolderPath, matchBase: true, ignore: ignoreFiles, dot:true });
4749

4850
let packageJSON = {};
@@ -78,21 +80,4 @@ const archiveSpecs = (runSettings, filePath, excludeFiles) => {
7880
});
7981
}
8082

81-
const getFilesToIgnore = (runSettings, excludeFiles) => {
82-
let ignoreFiles = Constants.filesToIgnoreWhileUploading;
83-
84-
// exclude files asked by the user
85-
// args will take precedence over config file
86-
if (!utils.isUndefined(excludeFiles)) {
87-
let excludePatterns = utils.fixCommaSeparatedString(excludeFiles).split(',');
88-
ignoreFiles = ignoreFiles.concat(excludePatterns);
89-
logger.info(`Excluding files matching: ${JSON.stringify(excludePatterns)}`);
90-
} else if (!utils.isUndefined(runSettings.exclude) && runSettings.exclude.length) {
91-
ignoreFiles = ignoreFiles.concat(runSettings.exclude);
92-
logger.info(`Excluding files matching: ${JSON.stringify(runSettings.exclude)}`);
93-
}
94-
95-
return ignoreFiles;
96-
}
97-
9883
exports.archive = archiveSpecs

bin/helpers/checkUploaded.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
'use strict';
2+
const request = require('request');
3+
4+
const crypto = require('crypto'),
5+
Constants = require('./constants'),
6+
hashHelper = require('./hashUtil'),
7+
config = require('./config'),
8+
path = require('path'),
9+
fs = require("fs"),
10+
utils = require('./utils');
11+
12+
13+
const checkSpecsMd5 = (runSettings, excludeFiles) => {
14+
return new Promise(function (resolve, reject) {
15+
let cypressFolderPath = path.dirname(runSettings.cypressConfigFilePath);
16+
let ignoreFiles = utils.getFilesToIgnore(runSettings, excludeFiles, false);
17+
let options = {
18+
cwd: cypressFolderPath,
19+
ignore: ignoreFiles,
20+
pattern: `**/*.+(${Constants.allowedFileTypes.join("|")})`
21+
};
22+
hashHelper.hashWrapper(options).then(function (data) {
23+
const outputHash = crypto.createHash(Constants.hashingOptions.algo);
24+
outputHash.update(data);
25+
let packageJSON = {};
26+
27+
if (typeof runSettings.package_config_options === 'object') {
28+
Object.assign(packageJSON, runSettings.package_config_options);
29+
}
30+
31+
if (typeof runSettings.npm_dependencies === 'object') {
32+
Object.assign(packageJSON, {
33+
devDependencies: runSettings.npm_dependencies,
34+
});
35+
}
36+
37+
if (Object.keys(packageJSON).length > 0) {
38+
let packageJSONString = JSON.stringify(packageJSON);
39+
outputHash.update(packageJSONString);
40+
}
41+
42+
if (
43+
runSettings.cypress_config_file &&
44+
runSettings.cypress_config_filename !== 'false'
45+
) {
46+
let cypressJSON = JSON.parse(
47+
fs.readFileSync(runSettings.cypressConfigFilePath)
48+
);
49+
let cypressJSONString = JSON.stringify(cypressJSON);
50+
outputHash.update(cypressJSONString);
51+
}
52+
resolve(outputHash.digest(Constants.hashingOptions.encoding));
53+
}).catch(function (error) {
54+
reject(error);
55+
});
56+
});
57+
};
58+
59+
const checkUploadedMd5 = (bsConfig, args) => {
60+
return new Promise(function (resolve) {
61+
let obj = {
62+
zipUrlPresent: false,
63+
};
64+
if (args["force-upload"]) {
65+
return resolve(obj);
66+
}
67+
checkSpecsMd5(bsConfig.run_settings, args.exclude).then(function (md5data) {
68+
Object.assign(obj, {md5sum: md5data});
69+
let data = JSON.stringify({ zip_md5sum: md5data });
70+
71+
let options = {
72+
url: config.checkMd5sum,
73+
auth: {
74+
user: bsConfig.auth.username,
75+
password: bsConfig.auth.access_key
76+
},
77+
headers: {
78+
'Content-Type': 'application/json',
79+
"User-Agent": utils.getUserAgent(),
80+
},
81+
body: data
82+
};
83+
84+
request.post(options, function (err, resp, body) {
85+
if (err) {
86+
resolve(obj);
87+
} else {
88+
let zipData = null;
89+
try {
90+
zipData = JSON.parse(body);
91+
} catch (error) {
92+
zipData = {};
93+
}
94+
if (resp.statusCode === 200 && !utils.isUndefined(zipData.zipUrl)) {
95+
Object.assign(obj, zipData, {zipUrlPresent: true});
96+
}
97+
resolve(obj);
98+
}
99+
});
100+
}).catch((error) => {
101+
resolve({zipUrlPresent: false});
102+
});
103+
});
104+
};
105+
106+
exports.checkUploadedMd5 = checkUploadedMd5;

bin/helpers/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ if(config.env !== "production") {
1515
config.cypress_v1 = `${config.rails_host}/automate/cypress/v1`;
1616
config.buildUrl = `${config.cypress_v1}/builds/`;
1717
config.buildStopUrl = `${config.cypress_v1}/builds/stop/`;
18+
config.checkMd5sum = `${config.cypress_v1}/md5sumcheck/`;
1819
config.fileName = "tests.zip";
1920
config.retries = 5;
2021
config.networkErrorExitCode = 2;

0 commit comments

Comments
 (0)