Skip to content
Merged
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
31 changes: 0 additions & 31 deletions .eslintrc.json

This file was deleted.

104 changes: 104 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: CI

on:
push:
branches: ['main']
pull_request:
branches: ['main']

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

# CI only reads the checkout; nothing here writes to the repository, so the
# GITHUB_TOKEN is scoped down from the repository default for every job.
permissions:
contents: read

jobs:
validate:
name: Typecheck, lint and unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3'

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Type-check
run: bun run type-check

- name: Lint
run: bun run lint:check

- name: Check formatting
run: bun run format:check

- name: Unit tests
run: bun run test

build:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: Build ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: chromium-mv3
script: deploy-v3
- target: firefox-mv2
script: deploy-v2
steps:
- uses: actions/checkout@v7

- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3'

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build
run: bun run ${{ matrix.script }}

- name: Verify the built manifest
run: bun ./tools/verifyBuild.js

- name: Package
run: bun run package

- uses: actions/upload-artifact@v7
with:
name: bquery-devtools-${{ matrix.target }}
path: artifacts/*.zip
if-no-files-found: error

e2e:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: E2E smoke test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3'

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Install Playwright browser
run: bun x playwright install --with-deps chromium

- name: Run E2E tests
run: bun run test:e2e

- uses: actions/upload-artifact@v7
if: failure()
with:
name: playwright-traces
path: test-results/
retention-days: 7
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
110 changes: 110 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Release

on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (defaults to the current ref)'
required: false

permissions:
contents: write
# Required by actions/attest-build-provenance to mint a Sigstore signing
# certificate and record the attestation.
id-token: write
attestations: write

jobs:
release:
name: Build and publish store artifacts
runs-on: ubuntu-latest
env:
# Present only when the repository has AMO credentials configured; the
# signing step is skipped rather than failed when they are absent.
AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }}
AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3'

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Validate
run: bun run validate

- name: Build Chromium (MV3)
run: bun run deploy-v3

- name: Verify and package Chromium (MV3)
run: |
bun ./tools/verifyBuild.js
bun run package

- name: Build Firefox (MV2)
run: bun run deploy-v2

- name: Verify and package Firefox (MV2)
run: |
bun ./tools/verifyBuild.js
bun run package

# AMO is the only party that can produce a signed, installable Firefox
# artifact: signing is a service, not a local key operation. Without
# credentials the release still ships the unsigned zip for manual upload.
- name: Sign the Firefox build (AMO)
if: env.AMO_JWT_ISSUER != '' && env.AMO_JWT_SECRET != ''
run: |
bunx web-ext@8 sign \
--source-dir dist \
--artifacts-dir artifacts \
--channel unlisted \
--api-key "$AMO_JWT_ISSUER" \
--api-secret "$AMO_JWT_SECRET"

# The .xpi exists only when AMO signing ran, so every consumer of the
# artifact list has to tolerate its absence.
- name: Collect artifacts
id: artifacts
run: |
shopt -s nullglob
cd artifacts
sha256sum *.zip *.xpi | tee SHA256SUMS.txt
cd ..
{
echo 'paths<<ARTIFACT_PATHS'
for artifact in artifacts/*.zip artifacts/*.xpi; do echo "$artifact"; done
echo ARTIFACT_PATHS
} >> "$GITHUB_OUTPUT"

# Signed build provenance, verifiable with:
# gh attestation verify <file> --repo bQuery/devtools-extension
# This proves which workflow, commit and runner produced each artifact —
# the property that matters for an extension users install from a store.
- name: Attest build provenance
uses: actions/attest-build-provenance@v2
with:
subject-path: ${{ steps.artifacts.outputs.paths }}

- uses: actions/upload-artifact@v7
with:
name: store-artifacts
path: artifacts/

- name: Attach artifacts to the release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/*.zip
artifacts/*.xpi
artifacts/SHA256SUMS.txt
draft: true
generate_release_notes: true
11 changes: 7 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,11 @@ FodyWeavers.xsd

dist

tools/syncConfig.js
tools/parse.js
tools/v2.js
tools/clean.js
# Compiled output of tools/*.ts (produced by `bun run build-tooling`).
# A glob rather than a list: enumerating them meant every new tool needed a
# matching entry, and tools/verifyBuild.js was committed when one was missed.
tools/*.js
artifacts/
test-results/
playwright-report/
package-lock.json
55 changes: 55 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

The extension versions independently of `@bquery/bquery`; the bridge protocol
version is what ties the two together.

## [Unreleased]

## [1.0.0]

First release as a standalone repository, rebuilt on
[BrowserExtensionTemplate](https://github.com/JosunLP/BrowserExtensionTemplate).
It replaces the untyped reference scaffold that used to live in the framework's
`extension/` folder.

### Added

- Typed bridge client for protocol **v1** with handshake retry, capability
negotiation, request/response correlation, per-request timeouts and
reconnection.
- Component tree with search over tags and attributes, and click-to-reveal in
the Elements panel.
- Signals and stores inspector with lazy drill-down into nested values.
- Timeline with a configurable ring buffer, type filter chips, free-text
search, pause and clear.
- Time travel: replay signal and store state as of any recorded event,
reconstructed from the connect-time snapshot.
- Graceful degradation against partially implemented bQuery apps: capabilities
advertised in the handshake are a hint, and every section is graded on what
the page actually answers. Sections load independently, a capability the page
never advertised is probed once, a snapshot that omits a collection reads as
"not reported" rather than empty, a missing `getComponentTree` falls back to
the flat component registry, and a page speaking a newer protocol version is
named as incompatible instead of leaving the panel waiting.
- Two transports behind one interface — a permission-free
`inspectedWindow.eval` poller (default) and an opt-in push transport over an
injected content script — so the extension ships with **no host permissions**.
- Background router with per-tab isolation and session-token checks.
- Options page for buffer size, poll interval and the live-streaming
preference.
- Chromium (MV3) and Firefox (MV2) build targets, a build verifier, and store
packaging.
- Signed releases: Sigstore build-provenance attestation for every artifact
(verifiable with `gh attestation verify`), plus an optional AMO-signed `.xpi`
when `AMO_JWT_ISSUER` / `AMO_JWT_SECRET` are configured.
- Unit tests (`bun test`) and Playwright E2E smoke tests, both run in CI along
with type-check, lint, format check and both build targets.
- Documentation: README, contributing guide, architecture notes and publishing
guide.

[Unreleased]: https://github.com/bQuery/devtools-extension/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/bQuery/devtools-extension/releases/tag/v1.0.0
75 changes: 75 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Contributing

Thanks for helping out. This repository holds the bQuery DevTools browser
extension; the framework itself lives in
[bQuery/bQuery](https://github.com/bQuery/bQuery).

## Setup

```bash
bun install # Bun 1.3+, see mise.toml
bun run dev # rebuild dist/ on change
```

Load `dist/` as an unpacked extension (see the README) and reload it from the
browser's extension page after a rebuild.

## Before you push

```bash
bun run validate # type-check + lint + unit tests
bun run format # prettier
bun run test:e2e # Playwright smoke tests (builds dist/ first)
```

CI runs the same checks plus both build targets, so a green `validate` is
usually enough to predict a green pipeline.

If your environment already ships a Chromium that does not match the pinned
Playwright version, point the tests at it:

```bash
PLAYWRIGHT_CHROMIUM_EXECUTABLE=/path/to/chromium bun run test:e2e
```

## House rules

- **TypeScript, strict.** `tsconfig.json` runs with `noUncheckedIndexedAccess`,
`exactOptionalPropertyTypes` and friends. Please don't loosen it locally.
- **The page is untrusted.** Anything crossing the bridge is validated before
use, and rendered through text sinks — never `innerHTML`. New views should
build DOM through `panel/dom.ts`.
- **Layering.** Views read `PanelState`; state talks to `BridgeClient`; the
client drives a `BridgeTransport`. Please don't shortcut across layers.
- **Protocol changes belong upstream.** The wire contract is owned by
`@bquery/bquery/devtools`. This repository consumes it and pins the version
through a type query, so a protocol bump shows up here as a compile error —
handle it deliberately rather than by widening a type.
- **Permissions.** The extension declares no host permissions. A change that
needs static site access needs a discussion first; `tools/verifyBuild.ts`
fails the build if `host_permissions` reappears.

## Tests

- **Unit tests** (`bun test`, files in `tests/unit/`) cover the protocol,
transports, router and panel logic. These modules are deliberately free of
DOM dependencies so they can be tested directly.
- **E2E tests** (`tests/e2e/`) serve the built `dist/` over http and drive the
real panel bundle with a mocked `chrome` API and a fixture page that speaks
protocol v1. Playwright cannot open a real DevTools panel, so this is how the
UI is covered end to end.

New behaviour needs a test. Bug fixes need the test that would have caught the
bug.

## Commits and pull requests

- Conventional-commit style subjects (`feat:`, `fix:`, `docs:`, `chore:`) keep
the changelog readable.
- Describe user-visible changes in `CHANGELOG.md` under *Unreleased*.
- Keep pull requests focused; a protocol change and a UI redesign are two pull
requests.

## Releasing

See [docs/PUBLISHING.md](./docs/PUBLISHING.md).
Loading