Skip to content

Commit 3e4181e

Browse files
Merge pull request #53 from browserstack/Env_Var_Support
Environment variables support for better CI/CD integration
2 parents 356d9ce + 799922e commit 3e4181e

File tree

4 files changed

+270
-33
lines changed

4 files changed

+270
-33
lines changed

bin/commands/runs.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@ module.exports = function run(args) {
1717
return utils.validateBstackJson(bsConfigPath).then(function (bsConfig) {
1818
utils.setUsageReportingFlag(bsConfig, args.disableUsageReporting);
1919

20-
// accept the username from command line if provided
20+
// accept the username from command line or env variable if provided
2121
utils.setUsername(bsConfig, args);
2222

23-
// accept the access key from command line if provided
23+
// accept the access key from command line or env variable if provided
2424
utils.setAccessKey(bsConfig, args);
2525

2626
// accept the build name from command line if provided
2727
utils.setBuildName(bsConfig, args);
2828

29+
//accept the local from env variable if provided
30+
utils.setLocal(bsConfig);
31+
32+
//accept the local identifier from env variable if provided
33+
utils.setLocalIdentifier(bsConfig);
34+
2935
// Validate browserstack.json values and parallels specified via arguments
3036
return capabilityHelper.validate(bsConfig, args).then(function (validated) {
3137
logger.info(validated);
@@ -48,8 +54,8 @@ module.exports = function run(args) {
4854
logger.warn(Constants.userMessages.NO_PARALLELS);
4955
}
5056

51-
if(!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
52-
57+
if (!args.disableNpmWarning && bsConfig.run_settings.npm_dependencies && Object.keys(bsConfig.run_settings.npm_dependencies).length <= 0) logger.warn(Constants.userMessages.NO_NPM_DEPENDENCIES);
58+
5359
logger.info(message);
5460
logger.info(dashboardLink);
5561
utils.sendUsageReport(bsConfig, args, `${message}\n${dashboardLink}`, Constants.messageTypes.SUCCESS, null);

bin/helpers/utils.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ const os = require("os");
33
const path = require("path");
44
const fs = require("fs");
55

6-
const usageReporting = require('./usageReporting'),
6+
const usageReporting = require('./usageReporting'),
77
logger = require('./logger').winstonLogger,
88
Constants = require('./constants');
99

1010
exports.validateBstackJson = (bsConfigPath) => {
11-
return new Promise(function(resolve, reject){
11+
return new Promise(function (resolve, reject) {
1212
try {
1313
logger.info(`Reading config from ${bsConfigPath}`);
1414
let bsConfig = require(bsConfigPath);
1515
resolve(bsConfig);
1616
}
1717
catch (e) {
18-
reject("Couldn't find the browserstack.json file at \""+ bsConfigPath +"\". Please use --config-file <path to browserstack.json>.");
18+
reject("Couldn't find the browserstack.json file at \"" + bsConfigPath + "\". Please use --config-file <path to browserstack.json>.");
1919
}
2020
});
2121
}
@@ -51,7 +51,7 @@ exports.getErrorCodeFromMsg = (errMsg) => {
5151
errorCode = "invalid_directory_structure";
5252
break;
5353
}
54-
if(errMsg.includes("Please use --config-file <path to browserstack.json>.")){
54+
if (errMsg.includes("Please use --config-file <path to browserstack.json>.")) {
5555
errorCode = "bstack_json_path_invalid";
5656
}
5757
return errorCode;
@@ -96,12 +96,18 @@ exports.setParallels = (bsConfig, args) => {
9696
exports.setUsername = (bsConfig, args) => {
9797
if (!this.isUndefined(args.username)) {
9898
bsConfig['auth']['username'] = args.username;
99+
} else if (!this.isUndefined(process.env.BROWSERSTACK_USERNAME)) {
100+
bsConfig['auth']['username'] = process.env.BROWSERSTACK_USERNAME;
101+
logger.info("Reading username from the environment variable BROWSERSTACK_USERNAME");
99102
}
100103
}
101104

102105
exports.setAccessKey = (bsConfig, args) => {
103106
if (!this.isUndefined(args.key)) {
104107
bsConfig['auth']['access_key'] = args.key;
108+
} else if (!this.isUndefined(process.env.BROWSERSTACK_ACCESS_KEY)) {
109+
bsConfig['auth']['access_key'] = process.env.BROWSERSTACK_ACCESS_KEY;
110+
logger.info("Reading access key from the environment variable BROWSERSTACK_ACCESS_KEY");
105111
}
106112
}
107113

@@ -116,14 +122,14 @@ exports.isUndefined = value => (value === undefined || value === null);
116122
exports.isFloat = value => (Number(value) && Number(value) % 1 !== 0);
117123

118124
exports.isParallelValid = (value) => {
119-
return this.isUndefined(value) || !(isNaN(value) || this.isFloat(value) || parseInt(value, 10) === 0 || parseInt(value, 10) < -1 ) || value === Constants.constants.DEFAULT_PARALLEL_MESSAGE;
125+
return this.isUndefined(value) || !(isNaN(value) || this.isFloat(value) || parseInt(value, 10) === 0 || parseInt(value, 10) < -1) || value === Constants.constants.DEFAULT_PARALLEL_MESSAGE;
120126
}
121127

122128
exports.getUserAgent = () => {
123129
return `BStack-Cypress-CLI/1.3.0 (${os.arch()}/${os.platform()}/${os.release()})`;
124130
}
125131

126-
exports.isAbsolute = (configPath) => {
132+
exports.isAbsolute = (configPath) => {
127133
return path.isAbsolute(configPath)
128134
}
129135

@@ -138,25 +144,25 @@ exports.configCreated = (args) => {
138144
}
139145

140146
exports.exportResults = (buildId, buildUrl) => {
141-
let data = "BUILD_ID=" + buildId + "\nBUILD_URL="+buildUrl;
142-
fs.writeFileSync("log/build_results.txt", data , function(err){
143-
if(err) {
147+
let data = "BUILD_ID=" + buildId + "\nBUILD_URL=" + buildUrl;
148+
fs.writeFileSync("log/build_results.txt", data, function (err) {
149+
if (err) {
144150
logger.warn(`Couldn't write BUILD_ID with value: ${buildId} to browserstack/build_results.txt`);
145151
logger.warn(`Couldn't write BUILD_URL with value: ${buildUrl} to browserstack/build_results.txt`);
146152
}
147153
});
148154
}
149155

150156
exports.deleteResults = () => {
151-
fs.unlink("log/build_results.txt", function (err){
157+
fs.unlink("log/build_results.txt", function (err) {
152158
});
153159
}
154160

155161
exports.isCypressProjDirValid = (cypressDir, cypressProjDir) => {
156162
// Getting absolute path
157163
cypressDir = path.resolve(cypressDir);
158164
cypressProjDir = path.resolve(cypressProjDir);
159-
if(cypressProjDir === cypressDir) return true;
165+
if (cypressProjDir === cypressDir) return true;
160166
let parentTokens = cypressDir.split('/').filter(i => i.length);
161167
let childTokens = cypressProjDir.split('/').filter(i => i.length);
162168
return parentTokens.every((t, i) => childTokens[i] === t);
@@ -165,3 +171,19 @@ exports.isCypressProjDirValid = (cypressDir, cypressProjDir) => {
165171
exports.getLocalFlag = (connectionSettings) => {
166172
return !this.isUndefined(connectionSettings) && !this.isUndefined(connectionSettings.local) && connectionSettings.local
167173
}
174+
175+
exports.setLocal = (bsConfig) => {
176+
if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL)) {
177+
let local = false;
178+
if (String(process.env.BROWSERSTACK_LOCAL).toLowerCase() === "true") local = true;
179+
bsConfig['connection_settings']['local'] = local;
180+
logger.info("Reading local setting from the environment variable BROWSERSTACK_LOCAL");
181+
}
182+
}
183+
184+
exports.setLocalIdentifier = (bsConfig) => {
185+
if (!this.isUndefined(process.env.BROWSERSTACK_LOCAL_IDENTIFIER)) {
186+
bsConfig['connection_settings']['local_identifier'] = process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
187+
logger.info("Reading local identifier from the environment variable BROWSERSTACK_LOCAL_IDENTIFIER");
188+
}
189+
}

test/unit/bin/commands/runs.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe("runs", () => {
5151
},
5252
});
5353

54-
validateBstackJsonStub.returns(Promise.reject({message: "random-error"}));
54+
validateBstackJsonStub.returns(Promise.reject({ message: "random-error" }));
5555

5656
return runs(args)
5757
.then(function (_bsConfig) {
@@ -92,6 +92,8 @@ describe("runs", () => {
9292
});
9393
getErrorCodeFromMsgStub = sandbox.stub().returns("random-error-code");
9494
capabilityValidatorStub = sandbox.stub();
95+
setLocalStub = sandbox.stub();
96+
setLocalIdentifierStub = sandbox.stub();
9597
deleteResultsStub = sandbox.stub();
9698
});
9799

@@ -115,6 +117,8 @@ describe("runs", () => {
115117
setAccessKey: setAccessKeyStub,
116118
setBuildName: setBuildNameStub,
117119
getConfigPath: getConfigPathStub,
120+
setLocal: setLocalStub,
121+
setLocalIdentifier: setLocalIdentifierStub,
118122
deleteResults: deleteResultsStub
119123
},
120124
"../helpers/capabilityHelper": {
@@ -136,6 +140,8 @@ describe("runs", () => {
136140
sinon.assert.calledOnce(capabilityValidatorStub);
137141
sinon.assert.calledOnce(setUsageReportingFlagStub);
138142
sinon.assert.calledOnce(getErrorCodeFromMsgStub);
143+
sinon.assert.calledOnce(setLocalStub);
144+
sinon.assert.calledOnce(setLocalIdentifierStub);
139145
sinon.assert.calledOnce(deleteResultsStub);
140146
sinon.assert.calledOnceWithExactly(
141147
sendUsageReportStub,
@@ -167,6 +173,8 @@ describe("runs", () => {
167173
capabilityValidatorStub = sandbox.stub();
168174
archiverStub = sandbox.stub();
169175
deleteZipStub = sandbox.stub();
176+
setLocalStub = sandbox.stub();
177+
setLocalIdentifierStub = sandbox.stub();
170178
deleteResultsStub = sandbox.stub();
171179
});
172180

@@ -190,6 +198,8 @@ describe("runs", () => {
190198
setBuildName: setBuildNameStub,
191199
setUsageReportingFlag: setUsageReportingFlagStub,
192200
getConfigPath: getConfigPathStub,
201+
setLocal: setLocalStub,
202+
setLocalIdentifier: setLocalIdentifierStub,
193203
deleteResults: deleteResultsStub
194204
},
195205
"../helpers/capabilityHelper": {
@@ -214,7 +224,9 @@ describe("runs", () => {
214224
.catch((error) => {
215225
sinon.assert.calledOnce(getConfigPathStub);
216226
sinon.assert.calledOnce(getConfigPathStub);
217-
sinon.assert.calledOnce(setParallelsStub)
227+
sinon.assert.calledOnce(setParallelsStub);
228+
sinon.assert.calledOnce(setLocalStub);
229+
sinon.assert.calledOnce(setLocalIdentifierStub);
218230
sinon.assert.calledOnce(validateBstackJsonStub);
219231
sinon.assert.calledOnce(capabilityValidatorStub);
220232
sinon.assert.calledOnce(archiverStub);
@@ -252,6 +264,8 @@ describe("runs", () => {
252264
archiverStub = sandbox.stub();
253265
zipUploadStub = sandbox.stub();
254266
deleteZipStub = sandbox.stub();
267+
setLocalStub = sandbox.stub();
268+
setLocalIdentifierStub = sandbox.stub();
255269
deleteResultsStub = sandbox.stub();
256270
});
257271

@@ -275,6 +289,8 @@ describe("runs", () => {
275289
setBuildName: setBuildNameStub,
276290
setUsageReportingFlag: setUsageReportingFlagStub,
277291
getConfigPath: getConfigPathStub,
292+
setLocal: setLocalStub,
293+
setLocalIdentifier: setLocalIdentifierStub,
278294
deleteResults: deleteResultsStub
279295
},
280296
"../helpers/capabilityHelper": {
@@ -304,6 +320,8 @@ describe("runs", () => {
304320
sinon.assert.calledOnce(getConfigPathStub);
305321
sinon.assert.calledOnce(getConfigPathStub);
306322
sinon.assert.calledOnce(setParallelsStub);
323+
sinon.assert.calledOnce(setLocalStub);
324+
sinon.assert.calledOnce(setLocalIdentifierStub);
307325
sinon.assert.calledOnce(validateBstackJsonStub);
308326
sinon.assert.calledOnce(capabilityValidatorStub);
309327
sinon.assert.calledOnce(archiverStub);
@@ -345,6 +363,8 @@ describe("runs", () => {
345363
zipUploadStub = sandbox.stub();
346364
createBuildStub = sandbox.stub();
347365
deleteZipStub = sandbox.stub();
366+
setLocalStub = sandbox.stub();
367+
setLocalIdentifierStub = sandbox.stub();
348368
deleteResultsStub = sandbox.stub();
349369
});
350370

@@ -368,6 +388,8 @@ describe("runs", () => {
368388
setBuildName: setBuildNameStub,
369389
setUsageReportingFlag: setUsageReportingFlagStub,
370390
getConfigPath: getConfigPathStub,
391+
setLocal: setLocalStub,
392+
setLocalIdentifier: setLocalIdentifierStub,
371393
deleteResults: deleteResultsStub
372394
},
373395
"../helpers/capabilityHelper": {
@@ -405,6 +427,8 @@ describe("runs", () => {
405427
sinon.assert.calledOnce(validateBstackJsonStub);
406428
sinon.assert.calledOnce(capabilityValidatorStub);
407429
sinon.assert.calledOnce(setParallelsStub);
430+
sinon.assert.calledOnce(setLocalStub);
431+
sinon.assert.calledOnce(setLocalIdentifierStub);
408432
sinon.assert.calledOnce(archiverStub);
409433
sinon.assert.calledOnce(setUsageReportingFlagStub);
410434
sinon.assert.calledOnce(zipUploadStub);
@@ -453,6 +477,8 @@ describe("runs", () => {
453477
exportResultsStub = sandbox.stub();
454478
deleteResultsStub = sandbox.stub();
455479
isUndefinedStub = sandbox.stub();
480+
setLocalStub = sandbox.stub();
481+
setLocalIdentifierStub = sandbox.stub();
456482
});
457483

458484
afterEach(() => {
@@ -476,6 +502,8 @@ describe("runs", () => {
476502
setUsageReportingFlag: setUsageReportingFlagStub,
477503
setParallels: setParallelsStub,
478504
getConfigPath: getConfigPathStub,
505+
setLocal: setLocalStub,
506+
setLocalIdentifier: setLocalIdentifierStub,
479507
exportResults: exportResultsStub,
480508
deleteResults: deleteResultsStub,
481509
isUndefined: isUndefinedStub
@@ -518,6 +546,8 @@ describe("runs", () => {
518546
sinon.assert.calledOnce(validateBstackJsonStub);
519547
sinon.assert.calledOnce(capabilityValidatorStub);
520548
sinon.assert.calledOnce(setParallelsStub);
549+
sinon.assert.calledOnce(setLocalStub);
550+
sinon.assert.calledOnce(setLocalIdentifierStub);
521551
sinon.assert.calledOnce(archiverStub);
522552
sinon.assert.calledOnce(setUsageReportingFlagStub);
523553
sinon.assert.calledOnce(zipUploadStub);

0 commit comments

Comments
 (0)