Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
46ee119
feat: convert to npm workspace; add @wdio/browserstack-service alongs…
AakashHotchandani Jun 13, 2026
8505f85
fix(ci): regenerate package-lock.json to match workspace package.json
AakashHotchandani Jun 15, 2026
52767e8
fix(ci): regenerate package-lock.json via a clean full resolution
AakashHotchandani Jun 15, 2026
67b9cef
fix(ci): include peerDependency closure in lockfile (npm default peer…
AakashHotchandani Jun 15, 2026
254a69d
fix(node18): make telemetry fail-safe + openAsBlob fallback + scope f…
AakashHotchandani Jun 15, 2026
f935a52
chore(review): SHA-pin publish actions, fix core npm metadata, drop i…
AakashHotchandani Jun 15, 2026
47a1c8f
chore(review): SHA-pin publish-workflow actions + correct core npm me…
AakashHotchandani Jun 15, 2026
068e2b5
fix(release): drop setup-node registry-url so it can't shadow OIDC token
AakashHotchandani Jun 15, 2026
7d90b13
wip(v8): extract v8 service into standalone v8 branch (mirror v9)
AakashHotchandani Jun 15, 2026
b234493
wip(v8): partial teardown cleanup (timer restore + observer disconnect)
AakashHotchandani Jun 16, 2026
bda3277
test(v8): fix standalone test suite — reporter mock cycle, util emit …
AakashHotchandani Jun 16, 2026
dddc424
refactor(v8): flatten gRPC core into the service package (inline proto)
AakashHotchandani Jun 17, 2026
43e8030
fix(ci): peer-inclusive lockfile + @types/node override (v8)
AakashHotchandani Jun 18, 2026
29be3ed
feat(v8): port SDK-6277 screenshot-on-failure over gRPC in the CLI fl…
AakashHotchandani Jul 11, 2026
3d0d0ec
chore(v8): release enablement — peer->dep alignment + manual/hybrid r…
AakashHotchandani Jul 11, 2026
4d40118
fix(v8 ci): make per-file test runner CI-proof (strip ANSI/disable co…
AakashHotchandani Jul 11, 2026
6dedffb
fix(v8): resolve semgrep/CodeQL findings — non-literal RegExp → endsW…
AakashHotchandani Jul 11, 2026
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
12 changes: 12 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changesets

This repo uses [Changesets](https://github.com/changesets/changesets) to version and publish
**`@wdio/browserstack-service`** on BrowserStack's own cadence (independent of WebdriverIO's
release schedule).

- Add a changeset for any user-facing change: `npm run changeset` (pick patch/minor/major).
- On merge to `main` (the v9 line) or `v8` (the v8 line), the Release workflow opens a
"Version Packages" PR; merging that PR publishes to npm via OIDC trusted publishing.
- The gRPC/protobuf client is generated inline from the bundled `.proto` files at build time
(`buf generate`) — it is no longer a separate workspace package, so `config.json` `ignore` is
empty and there is nothing extra for this pipeline to skip.
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "v8",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/port-screenshot-on-failure-v8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wdio/browserstack-service": patch
---

Port SDK-6277 (upstream webdriverio/webdriverio#15330): in the CLI/binary (v8) flow, forward screenshot-on-failure to the binary over gRPC as a `TEST_SCREENSHOT` log (the binary uploads it via its own authorized testhub session) instead of the direct-HTTP `onScreenshot` path, which 401s under the worker's binary-issued JWT. Also registers the command/result listeners in CLI mode so the user's `saveScreenshot()`/`takeScreenshot()` result is captured, and honors the incoming log `kind` in the mocha CLI framework so screenshots route correctly. Keeps the standalone v8 line at parity with the monorepo.
8 changes: 8 additions & 0 deletions .changeset/take-over-publishing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@wdio/browserstack-service": minor
---

BrowserStack now publishes `@wdio/browserstack-service` from its own repository
(`browserstack/wdio-browserstack-service`) on an independent release cadence, using npm OIDC
trusted publishing. No change for end users — same package name and the same
`services: ['browserstack']` configuration continue to work unchanged.
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CI

on:
pull_request:
push:
branches:
- main
- v8

permissions:
contents: read

jobs:
build-test:
name: Build & test (node ${{ matrix.node-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ['18.20', '20', '22']
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install
run: npm ci

- name: Build
run: npm run build

- name: Test
run: npm test
121 changes: 121 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Release

# Publishes @wdio/browserstack-service to npm via OIDC Trusted Publishing
# (no long-lived NPM_TOKEN). One-time setup by an @wdio npm org admin on npmjs.com:
# @wdio/browserstack-service -> Settings -> Trusted Publisher -> GitHub Actions
# Organization/user: browserstack
# Repository: wdio-browserstack-service
# Workflow filename: release.yml
# Environment: (leave empty)
# Requires: PUBLIC repo (for provenance), npm >= 11.5.1, Node >= 22.14.0.
#
# The gRPC/protobuf client is generated inline at build time (buf generate); there is no
# separate core package for this workflow to version or publish.
#
# Release model (publishing is MANUAL):
# * push to main / v8 -> opens/updates the "Version Packages" PR only. NEVER publishes;
# merging that PR does NOT publish either.
# * Run workflow (publish) -> publishes the merged version to npm (main -> `latest`,
# v8 -> `v8`) with git tag + GitHub release + provenance.
# * Run workflow (canary) -> snapshot prerelease to the npm `canary` dist-tag.

on:
push:
branches:
- main # v9 line -> opens Version PR (publish target: dist-tag "latest")
- v8 # v8 line -> opens Version PR (publish target: dist-tag "v8" via publishConfig.tag)
workflow_dispatch:
inputs:
publish:
description: 'Publish the merged version to npm (main -> `latest`, v8 -> `v8`). Merge the "Version Packages" PR first so there are no pending changesets.'
type: boolean
default: false
canary:
description: 'Publish a canary prerelease to the npm `canary` dist-tag (validates OIDC + provenance end-to-end; never touches `latest`). Requires at least one pending changeset.'
type: boolean
default: false

# Never run main and v8 releases on top of each other.
concurrency: release-${{ github.ref }}

permissions:
contents: write # commit the "Version Packages" PR + create git tags
pull-requests: write # open the "Version Packages" PR
id-token: write # OIDC for npm trusted publishing + provenance

jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # Changesets needs full history/tags

- name: Setup Node
# NOTE: intentionally NO `registry-url:` here. setup-node's registry-url writes
# `//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}` into ~/.npmrc; with no
# NODE_AUTH_TOKEN that becomes an empty token line that can shadow OIDC Trusted
# Publishing at `npm publish` time. npm already defaults to registry.npmjs.org and
# publishConfig.access=public handles the scoped publish, so the line isn't needed.
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22 # resolves to >= 22.14 on the runner (OIDC floor)
cache: 'npm'

# Trusted Publishing needs npm >= 11.5.1. Pin to the 11.x line so a future
# npm major can never silently change publish behaviour.
- name: Upgrade npm to an OIDC-capable version
run: npm install -g npm@11

- name: Install
run: npm ci

- name: Build
run: npm run build

- name: Test
run: npm test

# Version PR (push to main / v8): run changesets in VERSION-ONLY mode — open or update the
# "Version Packages" PR (version bump + CHANGELOG). This step NEVER publishes: with no
# `publish:` input, once the Version PR is merged (a push with no pending changesets) the
# action simply no-ops. Publishing is the separate, manual step below.
- name: Open/update the "Version Packages" PR
if: github.event_name == 'push'
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
with:
version: npm run version # changeset version — manages the Version PR only
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Publish (manual, workflow_dispatch with publish=true): publish the already-versioned
# package to npm — main -> `latest`, v8 -> `v8` (via publishConfig.tag) — with git tag,
# GitHub release, and provenance, over the OIDC trusted publisher (no NPM_TOKEN).
# Merge the "Version Packages" PR first: this publishes only when there are no pending
# changesets. If any remain, the action safely opens/updates the Version PR instead.
- name: Publish to npm
if: github.event_name == 'workflow_dispatch' && inputs.publish
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
with:
publish: npm run release # changeset publish (honors publishConfig.tag per branch)
createGithubReleases: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# No NPM_TOKEN: auth is OIDC via id-token: write above.
NPM_CONFIG_PROVENANCE: 'true'

# Canary (manual, workflow_dispatch with canary=true): snapshot-version the pending
# changesets and publish a prerelease to the `canary` dist-tag via the SAME OIDC trusted
# publisher. Validates OIDC + provenance end-to-end without touching `latest`.
# snapshot.useCalculatedVersion=true in .changeset/config.json makes the version
# <next>-canary-<datetime> (e.g. 9.30.0-canary-...). Requires >=1 pending changeset.
- name: Canary publish to `canary` dist-tag
if: github.event_name == 'workflow_dispatch' && inputs.canary
run: |
npx changeset version --snapshot canary
npx changeset publish --no-git-tag --tag canary
env:
NPM_CONFIG_PROVENANCE: 'true'
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
node_modules

# build outputs
dist
generated
build
src/generated
packages/*/dist
packages/*/build
packages/*/src/generated

# test/coverage
coverage
packages/*/coverage

# packed tarballs & logs
*.tgz
*.log
logs

# local/editor
.DS_Store
.env
.env.*
133 changes: 32 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,50 @@
# @browserstack/wdio-browserstack-service
# wdio-browserstack-service

![npm](https://img.shields.io/npm/v/@browserstack/wdio-browserstack-service)
![License: MIT](https://img.shields.io/badge/license-MIT-blue)
Home of [`@wdio/browserstack-service`](https://www.npmjs.com/package/@wdio/browserstack-service) — the BrowserStack WebdriverIO integration, maintained by BrowserStack.

Core SDK for BrowserStack integration used by the WebdriverIO BrowserStack Service.
For user configuration and service options, see the official service README:
[https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-browserstack-service/README.md](https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-browserstack-service/README.md)
| Package | npm | What it is |
|---|---|---|
| [`packages/browserstack-service`](./packages/browserstack-service) | [`@wdio/browserstack-service`](https://www.npmjs.com/package/@wdio/browserstack-service) | The WebdriverIO service users add via `services: ['browserstack']`. Its gRPC/protobuf client is generated from the bundled `.proto` files at build time. |

## Table of Contents
1. [Overview](#overview)
2. [Code Generation](#code-generation)
3. [Development](#development)
4. [Contributing](#contributing)
5. [License](#license)
## Usage (for end users)

## Overview
This package provides the TypeScript-based gRPC client and Protobuf definitions
used internally by the `@wdio/browserstack-service` plugin for WebdriverIO.
It includes:
- Generated TypeScript types and clients from Protobuf definitions.
- Message factory constructors for backward compatibility.
Nothing changes — install the service and add it to your WebdriverIO config:

## Installation
This module is included as a dependency of the `@wdio/browserstack-service` package.
Users should install and configure the service as documented in the linked README above.

## Setup & Configuration
Add the service to your WebdriverIO configuration (`wdio.conf.js`):
<!-- Usage is provided by @wdio/browserstack-service. -->
```
export BROWSERSTACK_USERNAME=your_username
export BROWSERSTACK_ACCESS_KEY=your_access_key
```sh
npm i -D @wdio/browserstack-service
```

## Usage
Import and use the gRPC client and message constructors:
```ts
import { SDKClient, StartBinSessionRequestConstructor } from '@browserstack/wdio-browserstack-service';
import path from 'path';
import process from 'process';
import { CLIUtils } from '@browserstack/cli-utils'; // example import, adjust if needed
import { version as packageVersion } from './package.json'; // adjust to your setup

// Initialize the client (uses default insecure credentials unless overridden)
const client = new SDKClient('grpc.browserstack.com:443');

// Collect framework details
const automationFrameworkDetail = CLIUtils.getAutomationFrameworkDetail();
const testFrameworkDetail = CLIUtils.getTestFrameworkDetail();

const frameworkVersions = {
...automationFrameworkDetail.version,
...testFrameworkDetail.version
};

// Build StartBinSessionRequest
const startReq = StartBinSessionRequestConstructor.create({
binSessionId: 'your-session-id', // replace with actual session id
sdkLanguage: CLIUtils.getSdkLanguage(),
sdkVersion: packageVersion,
pathProject: process.cwd(),
pathConfig: path.resolve(process.cwd(), 'browserstack.yml'),
cliArgs: process.argv.slice(2),
frameworks: [automationFrameworkDetail.name, testFrameworkDetail.name],
frameworkVersions,
language: CLIUtils.getSdkLanguage(),
testFramework: testFrameworkDetail.name,
wdioConfig: {}, // provide your WDIO config if applicable
});

// Start a session
client.startBinSession(startReq).then(response => {
console.log('Started session:', response.binSessionId);
}).catch(err => {
console.error('Failed to start session:', err);
});
```js
// wdio.conf.js
export const config = {
services: ['browserstack'],
// ...
}
```

## Code Generation
This project uses [Buf](https://docs.buf.build/) and `ts-proto` to
generate TypeScript code from Protobuf definitions.

### Prerequisites
- [Buf CLI](https://docs.buf.build/installation)
- Node.js ≥16
See the [service README](./packages/browserstack-service/README.md) for full configuration.

### Generate & Build
```bash
# Clean previously generated files
npm run clean
## Development

# Generate from .proto files
npm run generate
This is an npm workspace with a single published package.

# Compile to JS and declaration files
npm run build
```sh
npm ci # install
npm run build # generate the gRPC client from proto, then compile
npm test # run the service test suite
```

Generated files appear under `dist/` and should be published to npm.
- `npm run generate` (inside the package) runs `buf generate` to emit the gRPC/protobuf client into `src/grpc/generated` from the `.proto` files under `src/proto`. `npm run build` runs this automatically before compiling, so the generated code is never committed.
- The service is compiled with `tsc` (TypeScript declarations included).

## Development
Clone the repository and install dependencies:
```bash
git clone https://github.com/browserstack/wdio-browserstack-service.git
cd wdio-browserstack-service
npm install
```
## Releases

Run generation and build:
```bash
npm run build
```
`@wdio/browserstack-service` is versioned and published with [Changesets](https://github.com/changesets/changesets)
on BrowserStack's own cadence (independent of WebdriverIO core's release schedule):

## Contributing
Contributions are welcome! Please open issues or pull requests in the [GitHub repository](https://github.com/browserstack/wdio-browserstack-service).
- `main` → `latest` dist-tag (v9 line)
- `v8` branch → `v8` dist-tag (v8 line)

## License
MIT © BrowserStack
Publishing uses **npm OIDC trusted publishing** (no long-lived token; provenance-signed). The gRPC/protobuf
client is generated inline at build time from the `.proto` files in this repo — there is no separately
published core package.
Loading
Loading