Skip to content

Sync cli Implementation #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 50 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2dd0748
Starting off the syn cli changes
suryart Sep 25, 2020
ba1bac8
Adding syncRunner implementation
suryart Sep 25, 2020
b367ec3
Addin table package
suryart Sep 25, 2020
3bb6a6b
Added sync messages in parts
suryart Sep 25, 2020
bf84d46
Adding winston logger for sync cli
suryart Sep 25, 2020
ccd2b86
Updating the logger
suryart Sep 25, 2020
719ac27
Added spec failure/skipped message with table.
suryart Sep 25, 2020
165985e
Left align the content of table as center is messing the structure
suryart Sep 25, 2020
6d8c43d
make changes for --sync
nagpalkaran95 Sep 28, 2020
7e1421f
add unit test cases
nagpalkaran95 Oct 5, 2020
6dfb6ee
Adding basic tests for failedSpecDetails
suryart Oct 6, 2020
f54e33d
Adding missing dependencies
suryart Oct 6, 2020
14e97bf
Added more tests for specific cases and exit code status
suryart Oct 7, 2020
36111bc
Merge branch 'master' into sync-cli
suryart Oct 9, 2020
842f841
Merge branch 'sync-cli' into sync-cli-part-4
suryart Oct 9, 2020
daea598
Merge pull request #62 from browserstack/sync-cli-part-4
suryart Oct 9, 2020
545f7d8
Sync CLI Part 4
suryart Oct 9, 2020
d3e58a6
Moving the method in the promise
suryart Oct 9, 2020
eda59e4
remove bsconf path from param
nagpalkaran95 Oct 12, 2020
f165b56
add test cases for sync Runner
nagpalkaran95 Oct 12, 2020
7d0f551
Merge branch 'sync-cli' of github.com:browserstack/browserstack-cypre…
nagpalkaran95 Oct 12, 2020
b3e3590
change backs runs.js changes for promise handling
nagpalkaran95 Oct 12, 2020
fb15912
change winstonLogger to syncCliLogger in test cases
nagpalkaran95 Oct 12, 2020
9ed42ad
Adding basic structure for sync specs logging
suryart Oct 15, 2020
6c86641
Merge pull request #67 from browserstack/sync-cli-part-3
suryart Oct 15, 2020
231812b
Merge branch 'sync-cli' into CYP_442_sync_cli_part_1
nagpalkaran95 Oct 15, 2020
e616c67
Merge pull request #70 from browserstack/CYP_442_sync_cli_part_1
nagpalkaran95 Oct 15, 2020
d905fcb
Merge branch 'sync-cli' of https://github.com/browserstack/browsersta…
SagarGaniga Oct 16, 2020
037e31e
partial code for polling
SagarGaniga Oct 19, 2020
7867925
finalized the result and summary printing
SagarGaniga Oct 22, 2020
deff51d
clean up some promises
SagarGaniga Oct 22, 2020
1ec2908
Add test cases for part 2
SagarGaniga Oct 23, 2020
37d7936
fix test cases and handle some edge cases
SagarGaniga Oct 23, 2020
0a07c6a
Merge branch 'master' of github.com:browserstack/browserstack-cypress…
karanshah-browserstack Oct 29, 2020
fa323b1
Sync Cli Log Changes
karanshah-browserstack Oct 29, 2020
fa0bff8
Merge branch 'master' of github.com:browserstack/browserstack-cypress…
karanshah-browserstack Oct 29, 2020
fe41c93
Merge pull request #78 from browserstack/sync-cli-part-2
karanshah-browserstack Oct 30, 2020
5cd99f1
Merge branch 'master' of github.com:browserstack/browserstack-cypress…
karanshah-browserstack Oct 30, 2020
f72f28f
Merge branch 'sync-cli' of github.com:browserstack/browserstack-cypre…
karanshah-browserstack Oct 30, 2020
7227e2c
Merge conflict resolve
karanshah-browserstack Oct 30, 2020
b2ff2c1
Merge branch 'sync-cli' of github.com:browserstack/browserstack-cypre…
karanshah-browserstack Oct 30, 2020
d74d8fd
Removing logBuilddetails
karanshah-browserstack Oct 30, 2020
0bcdf1c
Browser List Log Format change
karanshah-browserstack Oct 30, 2020
9dc85c4
Unit test cases fix for cli log changes
karanshah-browserstack Oct 30, 2020
390a491
Modifying table config to set width ot 50
karanshah-browserstack Nov 4, 2020
8b75f38
Merge pull request #82 from browserstack/sync-cli-log-changes
karanshah-browserstack Nov 6, 2020
370db2d
Changes for retrying in case of network issue
SagarGaniga Nov 10, 2020
b4af193
hanndle no internet case
SagarGaniga Nov 11, 2020
7b94fc3
change formatting for error message
SagarGaniga Nov 11, 2020
a13a494
Merge pull request #91 from browserstack/sync-cli-retry-polling
SagarGaniga Nov 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions bin/commands/runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const archiver = require("../helpers/archiver"),
capabilityHelper = require("../helpers/capabilityHelper"),
Constants = require("../helpers/constants"),
utils = require("../helpers/utils"),
fileHelpers = require("../helpers/fileHelpers");
fileHelpers = require("../helpers/fileHelpers"),
syncRunner = require("../helpers/syncRunner");

module.exports = function run(args) {
let bsConfigPath = utils.getConfigPath(args.cf);
Expand Down Expand Up @@ -46,7 +47,6 @@ module.exports = function run(args) {

// Validate browserstack.json values and parallels specified via arguments
return capabilityHelper.validate(bsConfig, args).then(function (validated) {
logger.info(validated);

// accept the number of parallels
utils.setParallels(bsConfig, args);
Expand All @@ -56,20 +56,29 @@ module.exports = function run(args) {

// Uploaded zip file
return zipUploader.zipUpload(bsConfig, config.fileName).then(function (zip) {

// Create build
return build.createBuild(bsConfig, zip).then(function (data) {
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${config.dashboardUrl}${data.build_id}`;
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
utils.exportResults(data.build_id, `${config.dashboardUrl}${data.build_id}`);
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)) {
logger.warn(Constants.userMessages.NO_PARALLELS);
}

if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) {
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES_READ_MORE);
}
if (args.sync) {
syncRunner.pollBuildStatus(bsConfig, data).then((exitCode) => {
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
utils.handleSyncExit(exitCode, data.dashboard_url)
});
}

logger.info(message);
logger.info(dashboardLink);
if(!args.sync) logger.info(Constants.userMessages.EXIT_SYNC_CLI_MESSAGE.replace("<build-id>",data.build_id));
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);
return;
}).catch(function (err) {
Expand All @@ -81,9 +90,8 @@ module.exports = function run(args) {
// Zip Upload failed
logger.error(err);
logger.error(Constants.userMessages.ZIP_UPLOAD_FAILED);
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
}).finally(function () {
fileHelpers.deleteZip();
utils.sendUsageReport(bsConfig, args, `${err}\n${Constants.userMessages.ZIP_UPLOAD_FAILED}`, Constants.messageTypes.ERROR, 'zip_upload_failed');
});
}).catch(function (err) {
// Zipping failed
Expand Down
2 changes: 2 additions & 0 deletions bin/helpers/archiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const archiveSpecs = (runSettings, filePath, excludeFiles) => {

var cypressFolderPath = path.dirname(runSettings.cypressConfigFilePath);

logger.info(`Creating tests.zip with files in ${cypressFolderPath}`);

var archive = archiver('zip', {
zlib: { level: 9 } // Sets the compression level.
});
Expand Down
9 changes: 6 additions & 3 deletions bin/helpers/capabilityHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,32 @@ const caps = (bsConfig, zip) => {

// Browser list
let osBrowserArray = [];
let browsersList = [];
if (bsConfig.browsers) {
bsConfig.browsers.forEach((element) => {
osBrowser = element.os + "-" + element.browser;
osAndBrowser = element.os + " / " + Utils.capitalizeFirstLetter(element.browser);
element.versions.forEach((version) => {
osBrowserArray.push(osBrowser + version);
browsersList.push(`${osAndBrowser} (${version})`);
});
});
}
obj.devices = osBrowserArray;
if (obj.devices.length == 0) reject(Constants.validationMessages.EMPTY_BROWSER_LIST);
logger.info(`Browser list: ${osBrowserArray.toString()}`);
logger.info(`Browsers list: ${browsersList.join(", ")}`);

// Test suite
if (zip.zip_url && zip.zip_url.split("://")[1].length !== 0) {
obj.test_suite = zip.zip_url.split("://")[1];
} else {
reject("Test suite is empty");
}
logger.info(`Test suite: bs://${obj.test_suite}`);

// Local
obj.local = false;
if (bsConfig.connection_settings && bsConfig.connection_settings.local === true) obj.local = true;
logger.info(`Local is set to: ${obj.local}`);
logger.info(`Local is set to: ${obj.local} (${obj.local ? Constants.userMessages.LOCAL_TRUE : Constants.userMessages.LOCAL_FALSE})`);

// Local Identifier
obj.localIdentifier = null;
Expand Down Expand Up @@ -100,6 +102,7 @@ const caps = (bsConfig, zip) => {

const validate = (bsConfig, args) => {
return new Promise(function (resolve, reject) {
logger.info(Constants.userMessages.VALIDATING_CONFIG);
if (!bsConfig) reject(Constants.validationMessages.EMPTY_BROWSERSTACK_JSON);

if (!bsConfig.auth) reject(Constants.validationMessages.INCORRECT_AUTH_PARAMS);
Expand Down
2 changes: 2 additions & 0 deletions bin/helpers/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ config.cypress_v1 = `${config.rails_host}/automate/cypress/v1`;
config.buildUrl = `${config.cypress_v1}/builds/`;
config.buildStopUrl = `${config.cypress_v1}/builds/stop/`;
config.fileName = "tests.zip";
config.retries = 5;
config.networkErrorExitCode = 2;

module.exports = config;
133 changes: 78 additions & 55 deletions bin/helpers/constants.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
let config = require("./config");

const syncCLI = {
FAILED_SPEC_DETAILS_COL_HEADER: ['Spec', 'Status', 'Browser', 'BrowserStack Session ID'],
LOGS: {
INIT_LOG: "All tests:"
},
INITIAL_DELAY_MULTIPLIER: 10
};

const userMessages = {
BUILD_FAILED: "Build creation failed.",
BUILD_CREATED: "Build created",
BUILD_INFO_FAILED: "Failed to get build info.",
BUILD_STOP_FAILED: "Failed to stop build.",
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
ZIP_DELETE_FAILED: "Could not delete local file.",
ZIP_DELETED: "Zip file deleted successfully.",
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
FAILED_TO_ZIP: "Failed to zip files.",
VISIT_DASHBOARD: "Visit the Automate dashboard for test reporting:",
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
NO_PARALLELS: "Your tests will run sequentially. Read more about running your tests in parallel here: https://www.browserstack.com/docs/automate/cypress/run-tests-in-parallel",
NO_NPM_DEPENDENCIES: "No npm dependencies specified. Read more here: https://www.browserstack.com/docs/automate/cypress/npm-packages. You can suppress this warning by using --disable-npm-warning flag."
BUILD_FAILED: "Build creation failed.",
BUILD_CREATED: "Build created",
BUILD_INFO_FAILED: "Failed to get build info.",
BUILD_STOP_FAILED: "Failed to stop build.",
BUILD_REPORT_MESSAGE: "See the entire build report here:",
ZIP_UPLOADER_NOT_REACHABLE: "Could not reach to zip uploader.",
ZIP_UPLOAD_FAILED: "Zip Upload failed.",
CONFIG_FILE_CREATED: "BrowserStack Config File created, you can now run browserstack-cypress --config-file run",
CONFIG_FILE_EXISTS: "File already exists, delete the browserstack.json file manually. skipping...",
DIR_NOT_FOUND: "Given path does not exist. Failed to create browserstack.json in %s",
ZIP_DELETE_FAILED: "Could not delete tests.zip successfully.",
ZIP_DELETED: "Deleted tests.zip successfully.",
API_DEPRECATED: "This version of API is deprecated, please use latest version of API.",
FAILED_TO_ZIP: "Failed to zip files.",
VISIT_DASHBOARD: "Visit the Automate dashboard for real-time test reporting:",
CONFLICTING_INIT_ARGUMENTS: "Conflicting arguments given. You can use --path only with a file name, and not with a file path.",
NO_PARALLELS: "Your specs will run sequentially on a single machine. Read more about running your specs in parallel here: https://www.browserstack.com/docs/automate/cypress/run-tests-in-parallel",
NO_NPM_DEPENDENCIES: "No npm dependencies specified - your specs might fail if they need any packages to be installed before running.",
NO_NPM_DEPENDENCIES_READ_MORE: "Read more about npm dependencies here: https://www.browserstack.com/docs/automate/cypress/npm-packages. You can suppress this warning by using --disable-npm-warning flag.",
VALIDATING_CONFIG: "Validating the config",
UPLOADING_TESTS: "Uploading the tests to BrowserStack",
LOCAL_TRUE: "you will now be able to test localhost / private URLs",
LOCAL_FALSE: "you won't be able to test localhost / private URLs",
EXIT_SYNC_CLI_MESSAGE: "Exiting the CLI, but your build is still running. You can use the --sync option to keep getting test updates. You can also use the build-info <build-id> command now.",
FATAL_NETWORK_ERROR: `fatal: unable to access '${config.buildUrl}': Could not resolve host: ${config.rails_host}`,
RETRY_LIMIT_EXCEEDED: `Max retries exceeded trying to connect to the host (retries: ${config.retries})`,
CHECK_DASHBOARD_AT: "Please check the build status at: "
};

const validationMessages = {
Expand All @@ -39,44 +59,46 @@ const validationMessages = {
};

const cliMessages = {
VERSION: {
INFO: "shows version information",
HELP: "Specify --help for available options",
DEMAND: "Requires init, run or poll argument"
},
INIT: {
INFO: "create a browserstack.json file in the folder specified with the default configuration options.",
DESC: "Init in a specified folder"
},
BUILD: {
INFO: "Check status of your build.",
STOP: "Stop your build.",
DEMAND: "Requires a build id.",
DESC: "Path to BrowserStack config",
CONFIG_DEMAND: "config file is required",
INFO_MESSAGE: "Getting information for buildId ",
STOP_MESSAGE: "Stopping build with given buildId "
},
RUN: {
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
INFO: "Run your tests on BrowserStack.",
DESC: "Path to BrowserStack config",
CYPRESS_DESC: "Path to Cypress config file",
CONFIG_DEMAND: "config file is required",
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
BUILD_NAME: "The build name you want to use to name your test runs",
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
SPECS_DESCRIPTION: 'Specify the spec files to run',
ENV_DESCRIPTION: "Specify the environment variables for your spec files"
},
COMMON: {
DISABLE_USAGE_REPORTING: "Disable usage reporting",
USERNAME: "Your BrowserStack username",
ACCESS_KEY: "Your BrowserStack access key",
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty"
}
}
VERSION: {
INFO: "shows version information",
HELP: "Specify --help for available options",
DEMAND: "Requires init, run or poll argument",
},
INIT: {
INFO: "create a browserstack.json file in the folder specified with the default configuration options.",
DESC: "Init in a specified folder",
},
BUILD: {
INFO: "Check status of your build.",
STOP: "Stop your build.",
DEMAND: "Requires a build id.",
DESC: "Path to BrowserStack config",
CONFIG_DEMAND: "config file is required",
INFO_MESSAGE: "Getting information for buildId ",
STOP_MESSAGE: "Stopping build with given buildId ",
},
RUN: {
PARALLEL_DESC: "The maximum number of parallels to use to run your test suite",
INFO: "Run your tests on BrowserStack.",
DESC: "Path to BrowserStack config",
CYPRESS_DESC: "Path to Cypress config file",
CONFIG_DEMAND: "config file is required",
CYPRESS_CONFIG_DEMAND: "Cypress config file is required",
BUILD_NAME: "The build name you want to use to name your test runs",
EXCLUDE: "Exclude files matching a pattern from zipping and uploading",
DEFAULT_PARALLEL_MESSAGE: "Here goes the number of parallels you want to run",
SPECS_DESCRIPTION: "Specify the spec files to run",
ENV_DESCRIPTION: "Specify the environment variables for your spec files",
SYNC_DESCRIPTION: "Makes the run command in sync",
BUILD_REPORT_MESSAGE: "See the entire build report here",
},
COMMON: {
DISABLE_USAGE_REPORTING: "Disable usage reporting",
USERNAME: "Your BrowserStack username",
ACCESS_KEY: "Your BrowserStack access key",
NO_NPM_WARNING: "No NPM warning if npm_dependencies is empty",
},
};

const messageTypes = {
SUCCESS: "success",
Expand All @@ -92,6 +114,7 @@ const allowedFileTypes = ['js', 'json', 'txt', 'ts', 'feature', 'features', 'pdf
const filesToIgnoreWhileUploading = ['node_modules/**', 'package-lock.json', 'package.json', 'browserstack-package.json', 'tests.zip', 'cypress.json']

module.exports = Object.freeze({
syncCLI,
userMessages,
cliMessages,
validationMessages,
Expand Down
37 changes: 18 additions & 19 deletions bin/helpers/fileHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
const fs = require('fs-extra'),
path = require('path');

const logger = require("./logger").winstonLogger,
Constants = require("../helpers/constants"),
config = require("../helpers/config");
const logger = require('./logger').winstonLogger,
Constants = require('../helpers/constants'),
config = require('../helpers/config');

exports.write = function(f, message, args, cb) {
exports.write = function (f, message, args, cb) {
message = message || 'Creating';
fs.writeFile(f.path, f.file, function() {
logger.info(message + " file: " + f.path);
cb && cb(args)
fs.writeFile(f.path, f.file, function () {
logger.info(message + ' file: ' + f.path);
cb && cb(args);
});
}
};

exports.fileExists = function (filePath, cb) {
fs.access(filePath, fs.F_OK, (err) => {
Expand All @@ -25,21 +25,20 @@ exports.fileExists = function (filePath, cb) {
};

exports.deleteZip = () => {
return fs.unlink(config.fileName, function (err) {
if (err) {
logger.info(Constants.userMessages.ZIP_DELETE_FAILED);
return 1;
} else {
logger.info(Constants.userMessages.ZIP_DELETED);
return 0;
}
});
}
try {
fs.unlinkSync(config.fileName);
logger.info(Constants.userMessages.ZIP_DELETED);
return 0;
} catch (err) {
logger.info(Constants.userMessages.ZIP_DELETE_FAILED);
return 1;
}
};

exports.dirExists = function (filePath, cb) {
let exists = false;
if (fs.existsSync(path.dirname(filePath), cb)) {
exists = true;
}
cb && cb(exists);
}
};
11 changes: 11 additions & 0 deletions bin/helpers/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ const winstonLoggerParams = {
],
};

const winstonSyncCliLoggerParams = {
transports: [
new (winston.transports.Console)({
formatter: (options) => {
return (options.message ? options.message : '');
}
}),
]
}

const winstonFileLoggerParams = {
transports: [
new winston.transports.File({
Expand All @@ -31,3 +41,4 @@ const winstonFileLoggerParams = {

exports.winstonLogger = new winston.Logger(winstonLoggerParams);
exports.fileLogger = new winston.Logger(winstonFileLoggerParams);
exports.syncCliLogger = new winston.Logger(winstonSyncCliLoggerParams);
Loading