From eb3aac1729d07b3abd7496523402589d2aadafc0 Mon Sep 17 00:00:00 2001 From: Kamalpreet Kaur Date: Mon, 5 Oct 2026 12:57:26 +0530 Subject: [PATCH 1/2] fix(percy): skip launcher Percy setup when the BrowserStack CLI is running The CLI's PercyModule already downloads and runs the Percy CLI from ~/.browserstack/percy. The launcher's setupPercy downloaded a second copy into the same path while that executable was running, which fails with ETXTBSY on Linux and crashes the run. The launcher's Percy is unused in the CLI flow, so skip it there. Co-Authored-By: Claude Opus 5.5 (1M context) --- packages/browserstack-service/src/launcher.ts | 15 +++++++---- .../tests/launcher.test.ts | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/browserstack-service/src/launcher.ts b/packages/browserstack-service/src/launcher.ts index a5829bc..d9c95f0 100644 --- a/packages/browserstack-service/src/launcher.ts +++ b/packages/browserstack-service/src/launcher.ts @@ -515,11 +515,16 @@ export default class BrowserstackLauncherService implements Services.ServiceInst try { const bestPlatformPercyCaps = getBestPlatformForPercySnapshot(capabilities as Capabilities.TestrunnerCapabilities) this._percyBestPlatformCaps = bestPlatformPercyCaps as WebdriverIO.Capabilities - process.env[BROWSERSTACK_PERCY] = 'false' - await this.setupPercy(this._options, this._config, { - projectName: this._projectName - }) - this._updateBrowserStackPercyConfig() + // The CLI runs Percy from the same path; re-downloading over the running executable fails with ETXTBSY on Linux. + if (BrowserstackCLI.getInstance().isRunning()) { + PercyLogger.debug('Percy is managed by the BrowserStack CLI, skipping service-side Percy setup') + } else { + process.env[BROWSERSTACK_PERCY] = 'false' + await this.setupPercy(this._options, this._config, { + projectName: this._projectName + }) + this._updateBrowserStackPercyConfig() + } } catch (err) { PercyLogger.error(`Error while setting up Percy ${err}`) } diff --git a/packages/browserstack-service/tests/launcher.test.ts b/packages/browserstack-service/tests/launcher.test.ts index 9bbb24a..f6216c7 100644 --- a/packages/browserstack-service/tests/launcher.test.ts +++ b/packages/browserstack-service/tests/launcher.test.ts @@ -151,6 +151,32 @@ describe('onPrepare', () => { expect(service.browserstackLocal).toBeUndefined() }) + it('does not start a service-side Percy when the CLI is running', async () => { + const isRunningSpy = vi.spyOn(BrowserstackCLI.getInstance(), 'isRunning').mockReturnValue(true) + const service = new BrowserstackLauncher({ testObservability: false, percy: true } as any, caps, config) + const setupPercySpy = vi.spyOn(service, 'setupPercy').mockResolvedValue(undefined) + try { + await service.onPrepare(config, caps) + } finally { + isRunningSpy.mockRestore() + } + + expect(setupPercySpy).not.toHaveBeenCalled() + }) + + it('starts a service-side Percy when the CLI is not running', async () => { + const isRunningSpy = vi.spyOn(BrowserstackCLI.getInstance(), 'isRunning').mockReturnValue(false) + const service = new BrowserstackLauncher({ testObservability: false, percy: true } as any, caps, config) + const setupPercySpy = vi.spyOn(service, 'setupPercy').mockResolvedValue(undefined) + try { + await service.onPrepare(config, caps) + } finally { + isRunningSpy.mockRestore() + } + + expect(setupPercySpy).toHaveBeenCalledTimes(1) + }) + it('should add the "app" property to a multiremote capability if no "bstack:options"', async () => { const options: BrowserstackConfig = { app: 'bs://' } const service = new BrowserstackLauncher(options as any, caps, config) From 7ed97bcfce30958e0bf93c1c11f1abee0c398976 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 07:32:44 +0000 Subject: [PATCH 2/2] chore(changeset): auto-generate from PR template (patch) --- .changeset/pr-263.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/pr-263.md diff --git a/.changeset/pr-263.md b/.changeset/pr-263.md new file mode 100644 index 0000000..9769006 --- /dev/null +++ b/.changeset/pr-263.md @@ -0,0 +1,5 @@ +--- +"@wdio/browserstack-service": patch +--- + +- Fixed `ETXTBSY: text file is busy, open '~/.browserstack/percy'` crashes on Linux when Percy is enabled.