-
Notifications
You must be signed in to change notification settings - Fork 7
feat: monorepo conversion — add @wdio/browserstack-service alongside the gRPC core #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
46ee119
8505f85
52767e8
67b9cef
254a69d
f935a52
47a1c8f
068e2b5
ad2648f
40411cc
7c949da
041a4c4
65d7c33
db30ba0
1c6a95f
e4cf295
62223e6
a56cd70
c9f1ed8
9629eec
bf66b27
7d6f822
7306121
bf5de42
2ad7617
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", | ||
| "changelog": "@changesets/cli/changelog", | ||
| "commit": false, | ||
| "fixed": [], | ||
| "linked": [], | ||
| "access": "public", | ||
| "baseBranch": "main", | ||
| "updateInternalDependencies": "patch", | ||
| "ignore": [], | ||
| "snapshot": { | ||
| "useCalculatedVersion": true | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@wdio/browserstack-service": patch | ||
| --- | ||
|
|
||
| Declare `webdriverio` as a dependency instead of a peerDependency, matching the package published from the WebdriverIO monorepo. The extraction had moved `webdriverio` into `peerDependencies` (`^9.0.0`); npm then forced the consumer's `webdriverio` to `^9`, which conflicts with any project that also depends on a package peering `webdriverio@"^7 || ^8"` (e.g. `wdio-chromedriver-service@^8`) and surfaced as an `npm ERESOLVE` on install — a failure the monorepo-published package never had. Restores install parity with the upstream package; no user-facing API change. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@wdio/browserstack-service": patch | ||
| --- | ||
|
|
||
| Port the 2026-07-10 monorepo accessibility/CLI fixes to keep the standalone at parity (webdriverio/webdriverio#15380, #15383, #15382, #15381, #15376): skip the accessibility scan for BiDi `window`/`context` commands, route WDIO CLI-flow App Automate sessions to app-accessibility, finalize orphaned test runs on an interrupted exit, coerce stringified boolean accessibility options, and report mocha hooks in the CLI/testHub flow. No user-facing API change. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@wdio/browserstack-service": minor | ||
| --- | ||
|
|
||
| Publish from the standalone `browserstack/wdio-browserstack-service` repo, at parity with the WebdriverIO monorepo. Includes Load Testing Service (LTS) support, one-to-many Test-Case-ID tagging (`setCustomTestCaseId`), correct test/hook finish on mocha timeouts, per-batch failure isolation in the request queue, accessibility Browser type augmentations, and `yauzl` upgraded to `^3.4.0`. No user-facing API change. |
| 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. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| /** @type {import('eslint').Linter.Config} */ | ||
| // Ported from the WebdriverIO monorepo (.eslintrc.cjs) so the standalone repo lints | ||
| // @wdio/browserstack-service with the same rules it had upstream. ignorePatterns adds the | ||
| // build output and the buf-generated gRPC stubs (src/grpc/generated), which are not authored here. | ||
| const config = { | ||
| root: true, | ||
| parser: '@typescript-eslint/parser', | ||
| plugins: ['@typescript-eslint', 'unicorn', 'import'], | ||
| extends: ['eslint:recommended'], | ||
| env: { | ||
| node: true, | ||
| es6: true, | ||
| }, | ||
| parserOptions: { | ||
| ecmaVersion: 2020, | ||
| sourceType: 'module', | ||
| }, | ||
| ignorePatterns: [ | ||
| '**/node_modules/**', | ||
| '**/build/**', | ||
| '**/generated/**', | ||
| '**/*.d.ts', | ||
| ], | ||
| rules: { | ||
| quotes: ['error', 'single', { avoidEscape: true }], | ||
| camelcase: ['error', { properties: 'never' }], | ||
| semi: ['error', 'never'], | ||
| indent: [2, 4], | ||
| eqeqeq: ['error', 'always'], | ||
|
|
||
| 'prefer-const': 'error', | ||
| 'no-multiple-empty-lines': [2, { max: 1, maxEOF: 1 }], | ||
| 'array-bracket-spacing': ['error', 'never'], | ||
| 'brace-style': ['error', '1tbs', { allowSingleLine: true }], | ||
| 'comma-spacing': ['error', { before: false, after: true }], | ||
| 'no-lonely-if': 'error', | ||
| 'dot-notation': 'error', | ||
| 'no-else-return': 'error', | ||
| 'no-tabs': 'error', | ||
| 'no-trailing-spaces': [ | ||
| 'error', | ||
| { | ||
| skipBlankLines: false, | ||
| ignoreComments: false, | ||
| }, | ||
| ], | ||
| 'no-var': 'error', | ||
| 'unicode-bom': ['error', 'never'], | ||
| curly: ['error', 'all'], | ||
| 'object-curly-spacing': ['error', 'always'], | ||
| 'keyword-spacing': ['error'], | ||
| 'require-atomic-updates': 0, | ||
| 'linebreak-style': ['error', 'unix'], | ||
| 'unicorn/prefer-node-protocol': ['error'], | ||
| 'import/extensions': ['error', 'ignorePackages'], | ||
| 'no-restricted-syntax': [ | ||
| 'error', | ||
| 'IfStatement > ExpressionStatement > AssignmentExpression', | ||
| ], | ||
| 'unicorn/prefer-ternary': 'error', | ||
| }, | ||
| overrides: [ | ||
| { | ||
| files: ['*.ts'], | ||
| rules: { | ||
| // see https://stackoverflow.com/questions/55280555/typescript-eslint-eslint-plugin-error-route-is-defined-but-never-used-no-un | ||
| 'no-unused-vars': 'off', | ||
| '@typescript-eslint/no-unused-vars': 'error', | ||
| '@typescript-eslint/consistent-type-imports': 'error', | ||
| 'no-undef': 'off', | ||
| // allow overloads | ||
| 'no-redeclare': 'off', | ||
| }, | ||
| }, | ||
| { | ||
| files: ['*.test.ts'], | ||
| rules: { | ||
| 'dot-notation': 'off', | ||
| }, | ||
| }, | ||
| ], | ||
| } | ||
|
|
||
| module.exports = config |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
| - v8 | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| lint: | ||
| name: Lint | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | ||
|
|
||
| - name: Setup Node | ||
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: 'npm' | ||
|
|
||
| - name: Install | ||
| run: npm ci | ||
|
|
||
| - name: Lint | ||
| run: npm run lint | ||
|
|
||
| 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 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. v8 requries
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, and it's intentional per-line. main/v9 uses plain The v8 branch (created later) will set
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small correction, if we re-use
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flagging a small correctness point on this: That said — per the package-manager thread, we're staying on npm for v9 (OIDC publish-path risk, not capability), so this line stays
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| - name: Build | ||
| run: npm run build | ||
|
|
||
| - name: Test | ||
| run: npm test | ||
| 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. | ||
|
Comment on lines
+3
to
+10
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ( 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AakashHotchandani |
||
| # | ||
| # 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' | ||
| 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.* |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 OIDCrelease.ymlis also built aroundchangeset 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.There was a problem hiding this comment.
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.