Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 core **`@browserstack/wdio-browserstack-service`** is in `ignore` (see
`config.json`) — it is versioned and published separately by the SDK team and is never
touched by this pipeline.
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",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we re-use the existing yml file-based approach for this repo as well for maintaining consistency across the SDK repositories.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd lean toward keeping Changesets for this package. It's @wdio-scoped and the upstream WebdriverIO project releases with Changesets, so matching that keeps us consistent with the org we're co-publishing under. The OIDC release.yml is also built around changeset version / changeset publish — it drives the per-branch dist-tag and the "Version Packages" PR flow — so switching to the internal yml approach would mean reworking that pipeline and re-deriving the OIDC wiring.

So here it's consistency-with-wdio vs consistency-with-other-SDK-repos, and for a @wdio/* package I'd favor the former. Happy to discuss if the team feels strongly.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, happy to discuss this over a call.

"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@browserstack/wdio-browserstack-service"]
}
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@v4

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

- name: Install
run: npm ci

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v8 requries --legacy-peer-deps flag along with the npm i command. So, for v8 we would need npm ci --legacy-peer-deps. For main branch, normal npm i would suffice.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and it's intentional per-line. main/v9 uses plain npm ci — verified: the v9 peer graph resolves cleanly. Adding --legacy-peer-deps here would actually suppress the peerDependency closure and reintroduce the exact npm ci lockfile mismatch that was just fixed on this branch, so it must stay off for v9.

The v8 branch (created later) will set npm ci --legacy-peer-deps in its own ci.yml, since v8's peer ranges need it. No change needed on this (v9) branch.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small correction, if we re-use pnpm used in WDIO v9, then it'd be changed to pnpm ci here for v9 as well

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagging a small correctness point on this: pnpm ci isn't actually a pnpm command — it errors with ERR_PNPM_CI_NOT_IMPLEMENTED. The frozen-lockfile equivalent is pnpm install --frozen-lockfile (which pnpm does by default in CI when a lockfile is present).

That said — per the package-manager thread, we're staying on npm for v9 (OIDC publish-path risk, not capability), so this line stays npm ci for now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


- name: Build (core + service)
run: npm run build

- name: Test
run: npm test
75 changes: 75 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
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.
Comment on lines +3 to +10

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to handle publishing via GitHub CI? It'd be better to use minion for this if feasible.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping the publish step on GitHub Actions by design. The pipeline uses npm OIDC trusted publishing (id-token: write, no NPM_TOKEN) for build provenance and to avoid a long-lived npm automation token — a condition from the @wdio org for taking over @wdio/browserstack-service.

npm Trusted Publishing currently only recognizes GitHub Actions and GitLab CI/CD as trusted publishers, so minion can't be registered as one — publishing from minion would mean falling back to a classic NPM_TOKEN secret and losing provenance. Given the OIDC/provenance requirement, the npm publish needs to live here. (Build/test can still be mirrored to minion if useful — it's specifically the publish step that's constrained.)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AakashHotchandani
We'd need EM Approval for this. None of the other SDKs are published to npm using Github Actions.

#
# The gRPC core (@browserstack/wdio-browserstack-service) is in .changeset ignore,
# so this workflow never versions or publishes it.

on:
push:
branches:
- main # v9 line -> dist-tag "latest"
- v8 # v8 line -> dist-tag "v8" (from publishConfig.tag on the v8 branch)

# 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.
# (Follow-up to consider: split changesets/action so publish runs as its own
# top-level step — further de-risks OIDC. Tracked, not done here.)
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

- name: Create Release PR or publish to npm
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
with:
version: npm run version # changeset version (opens the "Version Packages" PR)
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'
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.*
134 changes: 33 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,51 @@
# @browserstack/wdio-browserstack-service
# wdio-browserstack-service

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be reviewed by @browserstack/sdk-product

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — the README content should get a @browserstack/sdk-product sign-off before merge. We'll route it to that team separately; it isn't blocking the code review here.


![npm](https://img.shields.io/npm/v/@browserstack/wdio-browserstack-service)
![License: MIT](https://img.shields.io/badge/license-MIT-blue)
Monorepo for 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']`. |
| [`packages/core`](./packages/core) | [`@browserstack/wdio-browserstack-service`](https://www.npmjs.com/package/@browserstack/wdio-browserstack-service) | gRPC/protobuf core SDK consumed by the service. |

## 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.

# Compile to JS and declaration files
npm run build
```sh
npm ci # install all packages
npm run build # build core then service
npm test # run the service test suite
```

Generated files appear under `dist/` and should be published to npm.
- `npm run build:core` / `npm run build:service` build a single package.
- The service is bundled with esbuild (deps kept external) and ships TypeScript declarations from `tsc`.

## 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 core
`@browserstack/wdio-browserstack-service` is released separately by the SDK team and is excluded from the
Changesets pipeline (see [`.changeset/config.json`](./.changeset/config.json)).
Loading
Loading