Skip to content

Commit 8b87783

Browse files
authored
Merge pull request #742 from 07souravkunda/update_o11y_stability_improvements
Update o11y stability improvements
2 parents 5f2a9f8 + 90dfac5 commit 8b87783

File tree

5 files changed

+148
-11
lines changed

5 files changed

+148
-11
lines changed

bin/commands/runs.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ module.exports = function run(args, rawArgs) {
111111
/*
112112
Send build start to Observability
113113
*/
114-
if(isTestObservabilitySession) await launchTestSession(bsConfig, bsConfigPath);
114+
if(isTestObservabilitySession) {
115+
await launchTestSession(bsConfig, bsConfigPath);
116+
utils.setO11yProcessHooks(null, bsConfig, args, null, buildReportData);
117+
}
115118

116119
// accept the system env list from bsconf and set it
117120
utils.setSystemEnvs(bsConfig);
@@ -264,6 +267,9 @@ module.exports = function run(args, rawArgs) {
264267
markBlockEnd('createBuild');
265268
markBlockEnd('total');
266269
utils.setProcessHooks(data.build_id, bsConfig, bs_local, args, buildReportData);
270+
if(isTestObservabilitySession) {
271+
utils.setO11yProcessHooks(data.build_id, bsConfig, bs_local, args, buildReportData);
272+
}
267273
let message = `${data.message}! ${Constants.userMessages.BUILD_CREATED} with build id: ${data.build_id}`;
268274
let dashboardLink = `${Constants.userMessages.VISIT_DASHBOARD} ${data.dashboard_url}`;
269275
buildReportData = { 'build_id': data.build_id, 'parallels': userSpecifiedParallels, ...buildReportData }

bin/helpers/utils.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const usageReporting = require("./usageReporting"),
2222
config = require("../helpers/config"),
2323
pkg = require('../../package.json'),
2424
transports = require('./logger').transports,
25-
{ findGitConfig, printBuildLink, isTestObservabilitySession, isBrowserstackInfra, shouldReRunObservabilityTests } = require('../testObservability/helper/helper'),
25+
o11yHelpers = require('../testObservability/helper/helper'),
2626
{ OBSERVABILITY_ENV_VARS, TEST_OBSERVABILITY_REPORTER } = require('../testObservability/helper/constants');
2727

2828
const request = require('request');
@@ -480,7 +480,7 @@ exports.setNodeVersion = (bsConfig, args) => {
480480
// specs can be passed via command line args as a string
481481
// command line args takes precedence over config
482482
exports.setUserSpecs = (bsConfig, args) => {
483-
if(isBrowserstackInfra() && isTestObservabilitySession() && shouldReRunObservabilityTests()) {
483+
if(o11yHelpers.isBrowserstackInfra() && o11yHelpers.isTestObservabilitySession() && o11yHelpers.shouldReRunObservabilityTests()) {
484484
bsConfig.run_settings.specs = process.env.BROWSERSTACK_RERUN_TESTS;
485485
return;
486486
}
@@ -580,8 +580,8 @@ exports.setSystemEnvs = (bsConfig) => {
580580
envKeys[key] = process.env[key];
581581
});
582582

583-
let gitConfigPath = findGitConfig(process.cwd());
584-
if(!isBrowserstackInfra()) process.env.OBSERVABILITY_GIT_CONFIG_PATH_LOCAL = gitConfigPath;
583+
let gitConfigPath = o11yHelpers.findGitConfig(process.cwd());
584+
if(!o11yHelpers.isBrowserstackInfra()) process.env.OBSERVABILITY_GIT_CONFIG_PATH_LOCAL = gitConfigPath;
585585
if(gitConfigPath) {
586586
const relativePathFromGitConfig = path.relative(gitConfigPath, process.cwd());
587587
envKeys["OBSERVABILITY_GIT_CONFIG_PATH"] = relativePathFromGitConfig ? relativePathFromGitConfig : 'DEFAULT';
@@ -1184,8 +1184,8 @@ exports.handleSyncExit = (exitCode, dashboard_url) => {
11841184
syncCliLogger.info(Constants.userMessages.BUILD_REPORT_MESSAGE);
11851185
syncCliLogger.info(dashboard_url);
11861186
}
1187-
if(isTestObservabilitySession()) {
1188-
printBuildLink(true, exitCode);
1187+
if(o11yHelpers.isTestObservabilitySession()) {
1188+
o11yHelpers.printBuildLink(true, exitCode);
11891189
} else {
11901190
process.exit(exitCode);
11911191
}
@@ -1288,7 +1288,7 @@ exports.setConfig = (bsConfig, args) => {
12881288

12891289
// blindly send other passed configs with run_settings and handle at backend
12901290
exports.setOtherConfigs = (bsConfig, args) => {
1291-
if(isTestObservabilitySession() && process.env.BS_TESTOPS_JWT) {
1291+
if(o11yHelpers.isTestObservabilitySession() && process.env.BS_TESTOPS_JWT) {
12921292
bsConfig["run_settings"]["reporter"] = TEST_OBSERVABILITY_REPORTER;
12931293
return;
12941294
}
@@ -1453,14 +1453,37 @@ exports.setProcessHooks = (buildId, bsConfig, bsLocal, args, buildReportData) =>
14531453
process.on('uncaughtException', processExitHandler.bind(this, bindData));
14541454
}
14551455

1456+
exports.setO11yProcessHooks = (() => {
1457+
let bindData = {};
1458+
let handlerAdded = false;
1459+
return (buildId, bsConfig, bsLocal, args, buildReportData) => {
1460+
bindData.buildId = buildId;
1461+
bindData.bsConfig = bsConfig;
1462+
bindData.bsLocal = bsLocal;
1463+
bindData.args = args;
1464+
bindData.buildReportData = buildReportData;
1465+
if (handlerAdded) return;
1466+
handlerAdded = true;
1467+
process.on('beforeExit', processO11yExitHandler.bind(this, bindData));
1468+
}
1469+
})()
1470+
14561471
async function processExitHandler(exitData){
14571472
logger.warn(Constants.userMessages.PROCESS_KILL_MESSAGE);
14581473
await this.stopBrowserStackBuild(exitData.bsConfig, exitData.args, exitData.buildId, null, exitData.buildReportData);
14591474
await this.stopLocalBinary(exitData.bsConfig, exitData.bsLocalInstance, exitData.args, null, exitData.buildReportData);
1460-
await printBuildLink(true);
1475+
await o11yHelpers.printBuildLink(true);
14611476
process.exit(0);
14621477
}
14631478

1479+
async function processO11yExitHandler(exitData){
1480+
if (exitData.buildId) {
1481+
await o11yHelpers.printBuildLink(false);
1482+
} else {
1483+
await o11yHelpers.printBuildLink(true);
1484+
}
1485+
}
1486+
14641487
exports.fetchZipSize = (fileName) => {
14651488
try {
14661489
let stats = fs.statSync(fileName)

bin/testObservability/helper/helper.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ const supportFileCleanup = () => {
6464
});
6565
}
6666

67+
exports.buildStopped = false;
68+
6769
exports.printBuildLink = async (shouldStopSession, exitCode = null) => {
68-
if(!this.isTestObservabilitySession()) return;
70+
if(!this.isTestObservabilitySession() || exports.buildStopped) return;
71+
exports.buildStopped = true;
6972
try {
7073
if(shouldStopSession) {
7174
supportFileCleanup();

bin/testObservability/reporter/index.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class MyReporter {
7171
this._paths = new PathHelper({ cwd: process.cwd() }, this._testEnv.location_prefix);
7272
this.currentTestSteps = [];
7373
this.currentTestCucumberSteps = [];
74+
this.hooksStarted = {};
7475
this.beforeHooks = [];
7576
this.platformDetailsMap = {};
7677
this.runStatusMarkedHash = {};
@@ -110,6 +111,9 @@ class MyReporter {
110111
} else {
111112
this.runStatusMarkedHash[hook.hookAnalyticsId] = true;
112113
}
114+
115+
// Remove hooks added at hook start
116+
delete this.hooksStarted[hook.hookAnalyticsId];
113117
await this.sendTestRunEvent(hook,undefined,false,"HookRunFinished");
114118
}
115119
}
@@ -152,12 +156,14 @@ class MyReporter {
152156
})
153157

154158
.on(EVENT_TEST_BEGIN, async (test) => {
159+
if (test.isSkipped) return;
155160
if(this.testObservability == true) {
156161
await this.testStarted(test);
157162
}
158163
})
159164

160165
.on(EVENT_TEST_END, async (test) => {
166+
if (test.isSkipped) return;
161167
if(this.testObservability == true) {
162168
if(!this.runStatusMarkedHash[test.testAnalyticsId]) {
163169
if(test.testAnalyticsId) this.runStatusMarkedHash[test.testAnalyticsId] = true;
@@ -435,6 +441,38 @@ class MyReporter {
435441
};
436442
await uploadEventData(buildUpdateData);
437443
}
444+
445+
// Add started hooks to the hash
446+
if(eventType === 'HookRunStarted' && ['BEFORE_EACH', 'AFTER_EACH', 'BEFORE_ALL'].includes(testData['hook_type'])) {
447+
this.hooksStarted[testData.uuid] = uploadData;
448+
}
449+
450+
// Send pending hook finsihed events for hook starts
451+
if (eventType === 'TestRunFinished') {
452+
Object.values(this.hooksStarted).forEach(async hookData => {
453+
hookData['event_type'] = 'HookRunFinished';
454+
hookData['hook_run'] = {
455+
...hookData['hook_run'],
456+
result: uploadData['test_run'].result,
457+
failure: uploadData['test_run'].failure,
458+
failure_type: uploadData['test_run'].failure_type,
459+
failure_reason: uploadData['test_run'].failure_reason,
460+
failure_reason_expanded: uploadData['test_run'].failure_reason_expanded,
461+
failure_backtrace: uploadData['test_run'].failure_backtrace
462+
463+
}
464+
465+
if (hookData['hook_run']['hook_type'] === 'BEFORE_ALL') {
466+
hookData['hook_run'].finished_at = uploadData['test_run'].finished_at;
467+
hookData['hook_run'].duration_in_ms = new Date(hookData['hook_run'].finished_at).getTime() - new Date(hookData['hook_run'].started_at).getTime();
468+
} else {
469+
hookData['hook_run'].finished_at = hookData['hook_run'].started_at;
470+
hookData['hook_run'].duration_in_ms = 0;
471+
}
472+
await uploadEventData(hookData);
473+
})
474+
this.hooksStarted = {};
475+
}
438476
} catch(error) {
439477
debug(`Exception in populating test data for event ${eventType} with error : ${error}`, true, error);
440478
}

test/unit/bin/helpers/utils.js

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const utils = require('../../../../bin/helpers/utils'),
2121
fileHelpers = require('../../../../bin/helpers/fileHelpers'),
2222
testObjects = require('../../support/fixtures/testObjects'),
2323
syncLogger = require('../../../../bin/helpers/logger').syncCliLogger,
24-
Contants = require('../../../../bin/helpers/constants');
24+
Contants = require('../../../../bin/helpers/constants'),
25+
o11yHelpers = require('../../../../bin/testObservability/helper/helper');
2526
const browserstack = require('browserstack-local');
2627
const { CYPRESS_V10_AND_ABOVE_TYPE, CYPRESS_V9_AND_OLDER_TYPE } = require('../../../../bin/helpers/constants');
2728
const { winstonLogger, syncCliLogger } = require('../../../../bin/helpers/logger');
@@ -3396,6 +3397,72 @@ describe('utils', () => {
33963397
});
33973398
});
33983399

3400+
describe('setO11yProcessHooks', () => {
3401+
it('should handle multiple calls', (done) => {
3402+
let buildId = null;
3403+
let bsConfig = testObjects.sampleBsConfig;
3404+
let bsLocalStub = sinon.stub();
3405+
let args= {};
3406+
3407+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3408+
let processOnSpy = sinon.spy(process, 'on');
3409+
3410+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3411+
sinon.assert.calledOnce(processOnSpy);
3412+
processOnSpy.restore();
3413+
processOnSpy = sinon.spy(process, 'on');
3414+
utils.setO11yProcessHooks('build_id', bsConfig, bsLocalStub, args);
3415+
sinon.assert.notCalled(processOnSpy);
3416+
processOnSpy.restore();
3417+
process.on('beforeExit', () => {
3418+
sinon.assert.calledOnce(printBuildLinkStub);
3419+
sinon.assert.calledWith(printBuildLinkStub, false);
3420+
done();
3421+
});
3422+
process.emit('beforeExit');
3423+
printBuildLinkStub.restore();
3424+
sinon.stub.restore();
3425+
});
3426+
3427+
it('should handle "beforeExit" event, with build id', (done) => {
3428+
let buildId = 'build_id';
3429+
let bsConfig = testObjects.sampleBsConfig;
3430+
let bsLocalStub = sinon.stub();
3431+
let args= {};
3432+
3433+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3434+
3435+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3436+
process.on('beforeExit', () => {
3437+
sinon.assert.calledOnce(printBuildLinkStub);
3438+
sinon.assert.calledWith(printBuildLinkStub, false);
3439+
done();
3440+
});
3441+
process.emit('beforeExit');
3442+
printBuildLinkStub.restore();
3443+
sinon.stub.restore();
3444+
});
3445+
3446+
it('should handle "beforeExit" event, without build id', (done) => {
3447+
let buildId = null;
3448+
let bsConfig = testObjects.sampleBsConfig;
3449+
let bsLocalStub = sinon.stub();
3450+
let args= {};
3451+
3452+
let printBuildLinkStub = sinon.stub(o11yHelpers, 'printBuildLink').returns(Promise.resolve(true));
3453+
3454+
utils.setO11yProcessHooks(buildId, bsConfig, bsLocalStub, args);
3455+
process.on('beforeExit', () => {
3456+
sinon.assert.calledOnce(printBuildLinkStub);
3457+
sinon.assert.calledWith(printBuildLinkStub, true);
3458+
done();
3459+
});
3460+
process.emit('beforeExit');
3461+
printBuildLinkStub.restore();
3462+
sinon.stub.restore();
3463+
});
3464+
});
3465+
33993466
describe('fetchZipSize', () => {
34003467
it('should return size in bytes if file is present', () => {
34013468
sinon.stub(fs, 'statSync').returns({size: 123});

0 commit comments

Comments
 (0)