Skip to content

feat!: v2 WXT rewrite with professional CI/CD - #4

Merged
karlspace merged 2 commits into
mainfrom
feat/v2-wxt-rewrite
Aug 17, 2026
Merged

karlspace merged 2 commits into
mainfrom
feat/v2-wxt-rewrite

Conversation

@karlspace

Copy link
Copy Markdown
Contributor

Replaces the v1 tsc/MV3 extension with the v2 WXT rewrite and brings the repository onto the BAUER GROUP CI/CD standard.

Why the diff looks like this

The two histories share no common ancestor — git merge-base returns nothing. GitHub cannot render a PR between unrelated histories, so this branch was created from main and the tree replaced wholesale in a single commit. The staged tree was verified byte-identical to the standalone v2 tree (f0bf8cc) before committing.

v1 history stays intact and reachable below the migration commit; git bisect crosses the boundary cleanly. Git detected two renames worth calling out: LICENSE.TXT → LICENSE and resources/IconSourceFile_Transparent.png → src/assets/icon.png (the icon master, carried forward with its history rather than deleted and re-added).

What changed

Extension — ground-up rewrite: WXT 0.21 + React 19 + Tailwind 4 + Radix + Zod, declarativeNetRequest rule generation, enterprise policy via chrome.storage.managed, sharded sync storage with device-local secrets, signed self-hosted CRX channel.

CI/CD — six workflows consuming bauer-group/automation-templates:

Workflow Purpose
ci.yml lint · format · typecheck · tests w/ 80% coverage · npm audit --audit-level=high · 3 browser builds, Node matrix [24, 26]
pr-validation.yml commitlint · secret scan · license check · dependency review
release.yml gate → semantic-release → signed assets → CWS (wired, disabled)
codeql.yml security-extended, weekly + push/PR
ai-issue-summary.yml AI triage
dependabot-maintenance.yml auto-merge behind required checks

release.yml reuses ci.yml via workflow_call rather than a copied with: block, so the pre-merge gate and the release gate are provably the same file.

Versioning — the old pipeline ran npm version patch unconditionally: commitlint enforced Conventional Commits on the way in, and the release step then discarded that information. Every release since the repo began was a patch regardless of what changed. semantic-release now derives it.

Runtime — Node floor raised to 24 (.nvmrc). The previous engines.node: ">=20" was never satisfiable by its own dependency set (lint-staged@17 requires >=22.22.1); Node 20 reached EOL on 2026-04-30.

Security — the 20 open Dependabot advisories on this repository (17 high, 3 moderate) all live in v1's dependency tree and are removed by this PR. v2 reports npm audit clean at --audit-level=high.

Tests — coverage over src/lib went 45.4% → 97.4% statements (38.9% → 91.7% branches). The six modules touching browser APIs were entirely untested; they now use @webext-core/fake-browser via wxt/testing.

Reviewing this

Worth reading closely: .nvmrc, LICENSE, .github/, and docs/superpowers/. src/ is the v2 tree as it stood in the standalone repository, plus the five new test files.

Design and plan travel with the code:

  • docs/superpowers/specs/2026-08-17-cicd-und-remote-migration-design.md
  • docs/superpowers/plans/2026-08-17-cicd-und-remote-migration.md

Merge requirements

Merge with a merge commit — not squash, not rebase. The v2.0.0 baseline tag is pushed at this branch's tip before merging; squash or rebase rewrites the SHA, stranding the tag off main and letting semantic-release baseline off v0.0.24 and cut 1.0.0 over the top.

Deliberately not in this PR

  • Repository visibility flip. The self-hosted CRX channel is inoperative while the repo is private: Chrome fetches updates.xml and the .crx anonymously, so every managed device gets a 404 and silently never updates. A gitleaks scan of both histories (40 commits) found one finding, proven to be the public half of the signing key pair, which is what pins the extension ID and belongs in the tree.
  • Chrome Web Store publishing. Wired but gated behind the PUBLISH_WEB_STORE variable. v1 was never published from this repository and v2 pins a new extension ID, so there is no listing to update in place.

v2 is a ground-up rewrite. It shares the product identity, the
X-BAUERGROUP-Auth header contract and the MIT licence with v1, and
nothing else: v1 was a hand-rolled tsc build with a manual manifest,
v2 is WXT + React 19 + Tailwind 4 + Zod with declarativeNetRequest
rule generation, enterprise policy support via chrome.storage.managed,
sharded sync storage with device-local secrets, and a signed
self-hosted CRX channel.

The two histories share no ancestor, so this commit replaces the tree
wholesale rather than merging. v1 history stays intact and reachable
below this commit, and git bisect crosses the boundary cleanly. The
staged tree was verified byte-identical to the standalone v2 tree
(both hash f0bf8cc) before committing.

Collapsed from thirteen commits in the standalone v2 repository:
  d5ea84d  feat(extension): scaffolded WXT extension foundation
  5503606  feat(ui): added professional popup and options UI
  2d55715  ci(release): added dual-channel release pipeline and docs
  adf8f97  docs(specs): added CI/CD and remote migration design
  cefa862  docs(plans): added the implementation plan
  3f6d663  build(runtime): raised the Node floor to 24, added LICENSE
  317b814  build(deps): updated WXT to 0.21, cleared audit findings
  e1dcb32  test(config): added coverage gating, fixed the include glob
  5c40db4  test(lib): covered the six browser-API modules
  4f8dcc1  fix(release): failed loudly on a missing signing key in CI
  cdbc0e6  ci(config): added CODEOWNERS, Dependabot, release config
  251afcf  ci(gate): added a pre-merge CI gate and PR validation
  664b6fb  ci(release): replaced hand-rolled versioning with semantic-release

BREAKING CHANGE: the extension ID changed from a per-install random
ID to the pinned jncjhkagdjiiohjfmbpmlemdchbkjaib. v1 installations
do not upgrade in place — managed deployments must update their
ExtensionInstallForcelist entry, and manual installs must be
reinstalled. Stored v1 configuration is not migrated.
@github-actions

Copy link
Copy Markdown

🔍 PR Validation Report

Overall Status: ❌ FAILED

Validation Results

Check Status Details
Conventional Commits ⏭️ SKIP failure
Security Scan ⏭️ SKIP Disabled
License Compliance ⏭️ SKIP pass

⚠️ Action needed: Please address the failing checks before this PR can be merged.


Automated validation by Automation Templates

The advanced CodeQL workflow could never have worked here. The
repository already has GitHub's default CodeQL setup configured, and
the two modes are mutually exclusive — the advanced run failed with
"CodeQL analyses from advanced configurations cannot be processed
when the default setup is enabled" while the default setup's own
analysis passed alongside it in the same PR.

Default setup is also the better of the two here:

* It covers actions, javascript, javascript-typescript and
  typescript. The workflow declared javascript-typescript only, so
  adopting it would have LOST scanning of the six GitHub Actions
  workflows this change introduces — exactly the code most worth
  scanning for injection.
* GitHub maintains and updates it; there is no file to drift.
* It matches the estate: of ~200 repos under C:\Projects only
  ResticBackup uses an advanced CodeQL config, plus the vendored
  Zitadel mirror. The modules-codeql.yml module exists but is
  effectively unadopted.

The one thing the workflow offered over default setup was the
security-extended query suite. Raising the default setup to the
extended suite via the API did not take effect (the PATCH returns a
run id but query_suite stays "default" and updated_at is unchanged),
most likely gated on this private repository. Left on the default
suite, which is what the rest of the estate runs; worth revisiting
after the repository goes public.
run: npm run sign:crx

- name: 📎 Attach assets to the release
uses: softprops/action-gh-release@v3
@karlspace
karlspace merged commit 0cc3bc1 into main Aug 17, 2026
10 checks passed
@karlspace
karlspace deleted the feat/v2-wxt-rewrite branch August 17, 2026 10:29
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.1.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants