Skip to content

Commit e14a9ff

Browse files
Karan NagpalKaran Nagpal
authored andcommitted
add code for generate-downloads command
1 parent d348877 commit e14a9ff

File tree

6 files changed

+179
-157
lines changed

6 files changed

+179
-157
lines changed

bin/commands/generateDownloads.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const logger = require("../helpers/logger").winstonLogger,
4+
Constants = require("../helpers/constants"),
5+
utils = require("../helpers/utils"),
6+
downloadBuildArtifacts = require('../helpers/buildArtifacts').downloadBuildArtifacts;
7+
8+
9+
module.exports = async function generateDownloads(args) {
10+
let bsConfigPath = utils.getConfigPath(args.cf);
11+
12+
return utils.validateBstackJson(bsConfigPath).then(async function (bsConfig) {
13+
// setting setDefaults to {} if not present and set via env variables or via args.
14+
utils.setDefaults(bsConfig, args);
15+
16+
// accept the username from command line if provided
17+
utils.setUsername(bsConfig, args);
18+
19+
// accept the access key from command line if provided
20+
utils.setAccessKey(bsConfig, args);
21+
22+
utils.setUsageReportingFlag(bsConfig, args.disableUsageReporting);
23+
24+
// set cypress config filename
25+
utils.setCypressConfigFilename(bsConfig, args);
26+
27+
let messageType = Constants.messageTypes.INFO;
28+
let errorCode = null;
29+
let buildId = args._[1];
30+
31+
await downloadBuildArtifacts(bsConfig, buildId, args);
32+
utils.sendUsageReport(bsConfig, args, 'generate-downloads called', messageType, errorCode);
33+
}).catch(function (err) {
34+
logger.error(err);
35+
utils.setUsageReportingFlag(null, args.disableUsageReporting);
36+
utils.sendUsageReport(null, args, err.message, Constants.messageTypes.ERROR, utils.getErrorCodeFromErr(err));
37+
});
38+
};

bin/commands/runs.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ module.exports = function run(args) {
141141
utils.handleSyncExit(exitCode, data.dashboard_url);
142142
});
143143
});
144+
} else {
145+
logger.info(Constants.userMessages.ASYNC_DOWNLOADS.replace('<build-id>', data.build_id));
144146
}
145147

146148
logger.info(message);
147149
logger.info(dashboardLink);
148-
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
150+
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>", data.build_id));
149151
let dataToSend = {
150152
time_components: getTimeComponents(),
151153
build_id: data.build_id,

bin/helpers/buildArtifacts.js

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,65 +14,79 @@ const logger = require('./logger').winstonLogger,
1414

1515

1616
const parseAndDownloadArtifacts = async (buildId, data) => {
17-
return new Promise((resolve, reject) => {
17+
return new Promise(async (resolve, reject) => {
1818
let all_promises = [];
1919
let combs = Object.keys(data);
2020
for(let i = 0; i < combs.length; i++) {
2121
let comb = combs[i];
2222
let sessions = Object.keys(data[comb]);
2323
for(let j = 0; j < sessions.length; j++) {
2424
let sessionId = sessions[j];
25-
let filePath = path.join('./', 'buildArtifacts', buildId, comb, sessionId);
26-
let fileName = 'buildArtifacts.zip';
27-
console.log(`adding promise for sessionID=${sessionId}`);
25+
let filePath = path.join('./', 'build_artifacts', buildId, comb, sessionId);
26+
let fileName = 'build_artifacts.zip';
2827
process.env.BUILD_ARTIFACTS_TOTAL_COUNT = Number(process.env.BUILD_ARTIFACTS_TOTAL_COUNT) + 1
2928
all_promises.push(downloadAndUnzip(filePath, fileName, data[comb][sessionId]).catch((error) => {
3029
process.env.BUILD_ARTIFACTS_FAIL_COUNT = Number(process.env.BUILD_ARTIFACTS_FAIL_COUNT) + 1;
31-
reject;
30+
reject(error);
3231
}));
3332
}
3433
}
35-
Promise.all(all_promises)
36-
.then(() => {
37-
resolve;
38-
})
34+
await Promise.all(all_promises);
35+
resolve();
36+
});
37+
}
38+
39+
const createDirIfNotPresent = async (dir) => {
40+
return new Promise((resolve) => {
41+
if (!fs.existsSync(dir)){
42+
fs.mkdirSync(dir);
43+
}
44+
resolve();
3945
});
4046
}
4147

4248
const createDirectories = async (buildId, data) => {
43-
// create dir for buildArtifacts if not already present
44-
let artifactsDir = path.join('./', 'buildArtifacts');
49+
// create dir for build_artifacts if not already present
50+
let artifactsDir = path.join('./', 'build_artifacts');
4551
if (!fs.existsSync(artifactsDir)){
4652
fs.mkdirSync(artifactsDir);
4753
}
4854

4955
// create dir for buildId if not already present
50-
let buildDir = path.join('./', 'buildArtifacts', buildId);
56+
let buildDir = path.join('./', 'build_artifacts', buildId);
5157
if (fs.existsSync(buildDir)){
5258
// remove dir in case already exists
5359
fs.rmdirSync(buildDir, { recursive: true, force: true });
5460
}
5561
fs.mkdirSync(buildDir);
5662

57-
// create subdirs for combinations inside build
58-
Object.keys(data).forEach(comb => {
59-
let combDir = path.join('./', 'buildArtifacts', buildId, comb);
60-
if (!fs.existsSync(combDir)){
61-
fs.mkdirSync(combDir);
63+
let combDirs = [];
64+
let sessionDirs = [];
65+
let combs = Object.keys(data);
66+
67+
for(let i = 0; i < combs.length; i++) {
68+
let comb = combs[i];
69+
let combDir = path.join('./', 'build_artifacts', buildId, comb);
70+
combDirs.push(createDirIfNotPresent(combDir));
71+
let sessions = Object.keys(data[comb]);
72+
for(let j = 0; j < sessions.length; j++) {
73+
let sessionId = sessions[j];
74+
let sessionDir = path.join('./', 'build_artifacts', buildId, comb, sessionId);
75+
sessionDirs.push(createDirIfNotPresent(sessionDir));
6276
}
77+
}
6378

64-
// create subdirs for each parellel consumed for each combination
65-
Object.keys(data[comb]).forEach(sessionId => {
66-
let sessionDir = path.join('./', 'buildArtifacts', buildId, comb, sessionId);
67-
if (!fs.existsSync(sessionDir)){
68-
fs.mkdirSync(sessionDir);
69-
}
70-
})
79+
return new Promise(async (resolve) => {
80+
// create sub dirs for each combination in build
81+
await Promise.all(combDirs);
82+
// create sub dirs for each machine id in combination
83+
await Promise.all(sessionDirs);
84+
resolve();
7185
});
7286
}
7387

7488
const downloadAndUnzip = async (filePath, fileName, url) => {
75-
return new Promise((resolve, reject) => {
89+
return new Promise(async (resolve, reject) => {
7690
let tmpFilePath = path.join(filePath, fileName);
7791
https.get(url, function(response) {
7892
response.on('data', function (data) {
@@ -82,15 +96,16 @@ const downloadAndUnzip = async (filePath, fileName, url) => {
8296
fs.createReadStream(tmpFilePath).pipe(unzipper.Extract({ path: filePath })
8397
.on('close', function () {
8498
fs.unlinkSync(tmpFilePath);
85-
resolve;
99+
resolve();
86100
})
87101
.on('error', function(err) {
88-
reject;
102+
process.env.BUILD_ARTIFACTS_FAIL_COUNT = Number(process.env.BUILD_ARTIFACTS_FAIL_COUNT) + 1;
103+
reject(err);
89104
})
90105
);
91106
});
92107
response.on('error', function () {
93-
reject;
108+
reject();
94109
})
95110
});
96111
});
@@ -143,28 +158,32 @@ exports.downloadBuildArtifacts = async (bsConfig, buildId, args) => {
143158
let message = null;
144159
let messageType = null;
145160
let errorCode = null;
146-
let build;
147161

148162
try {
149163
const res = await axios.get(url, options);
150164
let buildDetails = res.data;
151165

152166
await createDirectories(buildId, buildDetails);
153167
await parseAndDownloadArtifacts(buildId, buildDetails);
154-
await sendUpdatesToBstack(bsConfig, buildId, args, options);
155168

156-
messageType = Constants.messageTypes.SUCCESS;
157-
message = `Build artifacts for build: ${buildId} were successfully downloaded.`;
158-
logger.info(message);
159-
} catch (err) {
160-
//TODO: handle error codes - 422 etc
169+
if (process.env.BUILD_ARTIFACTS_FAIL_COUNT > 0) {
170+
messageType = Constants.messageTypes.ERROR;
171+
message = Constants.userMessages.DOWNLOAD_BUILD_ARTIFACTS_FAILED.replace('<build-id>', buildId).replace('<machine-count>', process.env.BUILD_ARTIFACTS_FAIL_COUNT);
172+
logger.error(message);
173+
} else {
174+
messageType = Constants.messageTypes.SUCCESS;
175+
message = Constants.userMessages.DOWNLOAD_BUILD_ARTIFACTS_SUCCESS.replace('<build-id>', buildId).replace('<user-path>', process.cwd());
176+
logger.info(message);
177+
}
161178

162-
message = err;
179+
await sendUpdatesToBstack(bsConfig, buildId, args, options);
180+
utils.sendUsageReport(bsConfig, args, message, messageType, null);
181+
} catch (err) {
163182
messageType = Constants.messageTypes.ERROR;
164183
errorCode = 'api_failed_build_artifacts';
165184

166185
logger.error('Downloading the build artifacts failed.');
167-
logger.error(message);
168-
utils.sendUsageReport(bsConfig, args, message, messageType, errorCode);
186+
logger.error(err);
187+
utils.sendUsageReport(bsConfig, args, err, messageType, errorCode);
169188
}
170189
};

bin/helpers/constants.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ const userMessages = {
4343
LOCAL_STOP_FAILED: "Local Binary stop failed.",
4444
INVALID_LOCAL_MODE_WARNING: "Invalid value specified for local_mode. local_mode: (\"always-on\" | \"on-demand\"). For more info, check out https://www.browserstack.com/docs/automate/cypress/cli-reference",
4545
SPEC_LIMIT_WARNING: "You might not see all your results on the dashboard because of high spec count, please consider reducing the number of spec files in this folder.",
46-
DOWNLOAD_BUILD_ARTIFACTS: "Downloading build artifacts for the build <build-id> failed."
46+
DOWNLOAD_BUILD_ARTIFACTS_FAILED: "Downloading build artifacts for the build <build-id> failed for <machine-count> machines.",
47+
ASYNC_DOWNLOADS: "Test artifacts as specified under 'downloads' can be downloaded after the build has completed its run, using 'browserstack-cypress generate-downloads <build-id>'",
48+
DOWNLOAD_BUILD_ARTIFACTS_SUCCESS: "Your build artifact(s) have been successfully downloaded in '<user-path>/build_artifacts/<build-id>' directory"
4749
};
4850

4951
const validationMessages = {
@@ -84,17 +86,13 @@ const cliMessages = {
8486
INFO: "Check status of your build.",
8587
STOP: "Stop your build.",
8688
DEMAND: "Requires a build id.",
87-
DESC: "Path to BrowserStack config",
88-
CONFIG_DEMAND: "config file is required",
8989
INFO_MESSAGE: "Getting information for buildId ",
9090
STOP_MESSAGE: "Stopping build with given buildId ",
9191
},
9292
RUN: {
9393
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
9494
INFO: "Run your tests on BrowserStack.",
95-
DESC: "Path to BrowserStack config",
9695
CYPRESS_DESC: "Path to Cypress config file",
97-
CONFIG_DEMAND: "config file is required",
9896
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
9997
BUILD_NAME: "The build name you want to use to name your test runs",
10098
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
@@ -117,10 +115,15 @@ const cliMessages = {
117115
USERNAME: "Your BrowserStack username",
118116
ACCESS_KEY: "Your BrowserStack access key",
119117
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty",
118+
CONFIG_DEMAND: "config file is required",
119+
CONFIG_FILE_PATH: "Path to BrowserStack config",
120120
},
121121
GENERATE_REPORT: {
122122
INFO: "Generates the build report"
123123
},
124+
GENERATE_DOWNLOADS: {
125+
INFO: "Downloads the build artifacts"
126+
},
124127
};
125128

126129
const messageTypes = {

bin/helpers/utils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,11 +736,11 @@ exports.setCypressConfigs = (bsConfig, args) => {
736736

737737
exports.getCypressJSON = (bsConfig) => {
738738
if (
739-
bsConfig.runSettings.cypress_config_file &&
740-
bsConfig.runSettings.cypress_config_filename !== 'false'
739+
bsConfig.run_settings.cypress_config_file &&
740+
bsConfig.run_settings.cypress_config_filename !== 'false'
741741
) {
742742
let cypressJSON = JSON.parse(
743-
fs.readFileSync(bsConfig.runSettings.cypressConfigFilePath)
743+
fs.readFileSync(bsConfig.run_settings.cypressConfigFilePath)
744744
);
745745
return cypressJSON;
746746
}

0 commit comments

Comments
 (0)