import { getErrorString, stopBuildUpstream } from './util.js'
import { BStackLogger } from './bstackLogger.js'
import fs from 'node:fs'
import util from 'node:util'
import { fireFunnelRequest } from './instrumentation/funnelInstrumentation.js'
import { BROWSERSTACK_TESTHUB_UUID, BROWSERSTACK_TESTHUB_JWT, BROWSERSTACK_OBSERVABILITY } from './constants.js'
import type { FunnelData } from './types.js'
import PerformanceTester from './instrumentation/performance/performance-tester.js'
export default class BStackCleanup {
static async startCleanup() {
try {
const funnelDataCleanup = process.argv.includes('--funnelData')
let funnelData: FunnelData | null = null
if (funnelDataCleanup) {
const index = process.argv.indexOf('--funnelData')
const filePath = process.argv[index + 1]
funnelData = BStackCleanup.getFunnelDataFromFile(filePath)
}
if (process.argv.includes('--observability') && funnelData) {
await this.executeObservabilityCleanup(funnelData)
}
if (funnelDataCleanup && funnelData) {
await this.sendFunnelData(funnelData)
}
} catch (err) {
const error = err as string
BStackLogger.error(error)
}
try {
if (process.argv.includes('--performanceData')) {
await PerformanceTester.uploadEventsData()
}
} catch (er) {
BStackLogger.debug(`Error in sending events data ${util.format(er)}`)
}
}
static async executeObservabilityCleanup(funnelData: FunnelData) {
if (!process.env[BROWSERSTACK_TESTHUB_JWT]) {
return
}
BStackLogger.debug('Executing observability cleanup')
try {
const result = await stopBuildUpstream()
if (process.env[BROWSERSTACK_OBSERVABILITY] && process.env[BROWSERSTACK_TESTHUB_UUID]) {
BStackLogger.info(`\nVisit https://observability.browserstack.com/builds/${process.env[BROWSERSTACK_TESTHUB_UUID]} to view build report, insights, and many more debugging information all at one place!\n`)
}
const status = (result && result.status) || 'failed'
const message = (result && result.message)
this.updateO11yStopData(funnelData, status, status === 'failed' ? message : undefined)
} catch (e: unknown) {
BStackLogger.error('Error in stopping Observability build: ' + e)
this.updateO11yStopData(funnelData, 'failed', e)
}
}
static updateO11yStopData(funnelData: FunnelData, status: string, error: unknown = undefined) {
const toData = funnelData?.event_properties?.productUsage?.testObservability
if (!toData) {
return
}
let existingStopData = toData.events.buildEvents.finished
existingStopData = existingStopData || {}
existingStopData = {
...existingStopData,
status,
error: getErrorString(error),
stoppedFrom: 'exitHook'
}
toData.events.buildEvents.finished = existingStopData
}
static async sendFunnelData(funnelData: FunnelData) {
try {
await fireFunnelRequest(funnelData)
BStackLogger.debug('Funnel data sent successfully from cleanup')
} catch (e: unknown) {
BStackLogger.error('Error in sending funnel data: ' + e)
}
}
static getFunnelDataFromFile(filePath: string) {
if (!filePath) {
return null
}
const content = fs.readFileSync(filePath, 'utf8')
const data = JSON.parse(content)
this.removeFunnelDataFile(filePath)
return data
}
static removeFunnelDataFile(filePath?: string) {
if (!filePath) {
return
}
fs.rmSync(filePath, { force: true })
}
}
await BStackCleanup.startCleanup()