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
42 changes: 42 additions & 0 deletions .changeset/v1-stability-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
"extforge": major
---

**ExtForge 1.0 — the API is now a stability contract.**

There are no breaking changes from `0.6.x`. No config field was renamed, no
export was removed, no CLI flag changed. What changes is the promise: the
surface documented in [API stability](https://extforge.arshadshah.com/reference/stability/)
is frozen for the life of v1, and breaking any of it now requires a major release.

- **Every export, command, flag and config field is assigned a tier** —
Stable, Experimental, or Internal. Internal symbols carry an `@internal`
JSDoc tag at their definition, so your editor warns you before you depend on
one. `createBuildContext`, `classifyChange`, `generateHMRClientCode`,
`writeManifest` and `PluginRunner` are tagged internal: they are exported
because the CLI needs them across module boundaries, not as API.
- **`extforge/testing` and `extforge/testing/vitest` ship as experimental.**
The Chrome API fakes mirror a surface MV3 itself keeps extending, so they
need room to move in minor releases. Everything else in the package is stable.
- **The plugin API is stable.** It already carries an `apiVersion: 1`
discriminator, so a future incompatible plugin API can ship as `apiVersion: 2`
alongside it rather than breaking existing plugins.
- **HMR globals are split.** `globalThis.__EXTFORGE_HMR_QUIET__` is a public,
documented opt-out and is stable. `globalThis.__EXTFORGE_HMR__` is the
binding target the dev-mode transform emits against — internal, and it moves
with the wire protocol.
- **Node policy is written down.** ExtForge requires Node >= 22.12 and supports
releases while they are in Active or Maintenance LTS. Dropping an
end-of-life Node major is a *minor* release: holding the floor down until the
next major would mean shipping against an unpatched runtime.

Also in this release:

- **Cross-browser build gate in CI.** A new `pnpm check:cross-browser` builds
every example for Chrome, Firefox, Edge and Safari and asserts each emitted
manifest carries that browser's shape. Live-browser e2e remains Chromium-only.
- **New docs**: [API stability](https://extforge.arshadshah.com/reference/stability/)
and [Upgrading to v1](https://extforge.arshadshah.com/guides/migration-v1/).
- **`CHANGELOG.md` no longer carries a stale `[Unreleased]` section.** Its
contents (HMR v3, SWC + React Fast Refresh, content-script HMR scaffolding,
centralized logging) all shipped in `0.3.0` and `0.4.0`.
9 changes: 2 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@ updates:
typescript:
patterns:
- "typescript"
- "@typescript-eslint/*"
- "typescript-eslint"
- "tsup"
- "tsx"
- "ts-morph"
eslint:
biome:
patterns:
- "eslint"
- "eslint-*"
- "@eslint/*"
- "globals"
- "@biomejs/*"
vitest:
patterns:
- "vitest"
Expand Down
38 changes: 29 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ jobs:
matrix:
node: ['22', '24']
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node }}
cache: 'pnpm'
Expand All @@ -54,18 +54,38 @@ jobs:
name: Production audit (must be 0 vulns)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: pnpm audit --prod
run: pnpm audit --prod

cross-browser:
name: Cross-browser build (chrome/firefox/edge/safari)
runs-on: ubuntu-latest
needs: unit
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
# Builds every example for all four targets and asserts each emitted
# manifest carries that browser's shape. The Playwright suite below
# exercises live-browser behaviour, but only on Chromium.
- run: pnpm check:cross-browser

e2e:
name: E2E (${{ matrix.os }})
runs-on: ${{ matrix.os }}
Expand All @@ -75,11 +95,11 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ jobs:
matrix:
language: ['javascript-typescript']
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
category: "/language:${{ matrix.language }}"
6 changes: 3 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
# pnpm version comes from package.json `packageManager` — single source
# of truth shared with Cloudflare Pages (Corepack-style).
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: 'pnpm'
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ jobs:
id-token: write
if: ${{ github.repository == 'arshad-shah/extforge' && (github.event_name == 'release' || github.event.inputs.registry == 'github' || github.event.inputs.registry == 'both') }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
Expand All @@ -65,11 +65,11 @@ jobs:
if: ${{ github.repository == 'arshad-shah/extforge' && (github.event.inputs.registry == 'npm' || github.event.inputs.registry == 'both') }}
environment: npm-publish
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ jobs:
id-token: write
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false

- uses: pnpm/action-setup@a15d269cd4658e1107c09f1fabf4cbd7bd1f308a # v4.4.0
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'pnpm'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
contents: read
actions: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Run analysis
Expand All @@ -38,6 +38,6 @@ jobs:
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
sarif_file: results.sarif
Loading