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
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ jobs:
if: steps.version_check.outputs.new_version
run: |
VERSION="${{ steps.version_check.outputs.new_version }}"
git archive --prefix "vip-governance/" HEAD -o "vip-governance-${VERSION}.zip"
npm run release:zip
mv vip-governance.zip "vip-governance-${VERSION}.zip"

- name: Create Release
if: steps.version_check.outputs.new_version
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrency:

jobs:
lint-js:
name: JavaScript linting
name: Frontend linting and type checking
runs-on: ubuntu-latest

strategy:
Expand All @@ -28,15 +28,22 @@ jobs:
node-version: '24'
cache: npm

- name: Build the plugin
- name: Install dependencies
run: npm ci

- name: Verify production bundles
run: |
npm ci
npm run build
git diff --exit-code -- build

- name: Lint JS files
run: npm run lint:js

- name: Type check frontend files
run: npm run typecheck

unit-js:
name: JavaScript Unit Tests
name: Frontend Unit Tests
runs-on: ubuntu-latest

strategy:
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ vendor/*
/playwright/.cache/
/artifacts

# Map file which is generated by webpack
build/index.js.map
# Development-only source maps generated by webpack.
build/*.js.map
35 changes: 18 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The plugin uses a JSON-based rules system (`governance-rules.json`) with support
### Tech Stack

- **PHP 8.2+** — Backend logic, rule parsing, REST API, settings panel
- **JavaScript/JSX** — Block editor integration via WordPress filters
- **TypeScript/TSX** — Block editor integration via WordPress filters
- **WordPress 6.8+** — Target platform
- **Webpack** — Build system (via `@wordpress/scripts`)
- **Composer** — PHP dependency management
Expand All @@ -39,13 +39,14 @@ governance/
settings/
settings.php # Admin settings page registration
settings-view.php # Settings page HTML template
settings.js # Settings page frontend logic
settings.css # Settings page styles
src/
index.js # JS entry point — block editor filter setup
block-utils.js # Block name matching, hierarchy validation
block-locking.jsx # React UI for block locking
nested-governance-loader.js # Loads nested governance settings
index.ts # Frontend entry point
editor.ts # Block editor filter setup
block-utils.ts # Block name matching, hierarchy validation
block-locking.tsx # React UI for block locking
nested-settings-filter.ts # Resolves nested governance settings
settings/ # Settings page frontend logic
bin/release # Creates and commits major/minor/patch release branches
build/ # Compiled JS output (do not edit directly)
tests/
Expand All @@ -67,7 +68,7 @@ WPCOMVIP__GOVERNANCE__RULES_REST_ROUTE // 'vip-governance/v1'
WPCOMVIP_GOVERNANCE_RULES_FILENAME // 'governance-rules.json'
```

### JavaScript Global
### Frontend Global

The plugin exposes `VIP_GOVERNANCE` to the block editor with:

Expand Down Expand Up @@ -181,7 +182,7 @@ npm run test # Runs both PHP and JS unit tests
### Code Standards

- **PHP**: WordPress-VIP-Go + WordPress-Extra via PHPCS
- **JS**: `@automattic/eslint-plugin-wpvip`
- **TypeScript/JavaScript**: `@automattic/eslint-plugin-wpvip`
- **Formatting**: Prettier with `@automattic/eslint-plugin-wpvip/prettierrc`

### CI Matrix (GitHub Actions)
Expand Down Expand Up @@ -219,17 +220,17 @@ class MyNewTest extends TestCase {
}
```

### JS Unit Tests (Jest)
### Frontend Unit Tests (Jest)

- **Location**: Co-located with source as `src/foo.test.js` next to `src/foo.js`
- **Location**: Co-located with source as `src/foo.test.ts` or `src/foo.test.tsx`
- **Framework**: Jest with `@wordpress/jest-preset-default`
- **WordPress mocks**: Mock `@wordpress/hooks`, `@wordpress/data`, etc. via `jest.mock()`
- **Style**: `describe` / `it` blocks
- **Run one file**: `npx jest src/block-utils.test.js`
- **Run one file**: `npx jest src/block-utils.test.ts`

Example structure:

```js
```ts
import { myFunction } from './my-module';

describe( 'myFunction', () => {
Expand All @@ -241,16 +242,16 @@ describe( 'myFunction', () => {

### E2E Tests (Playwright)

- **Location**: `tests/e2e/*.spec.js`
- **Location**: `tests/e2e/*.spec.ts`
- **Framework**: Playwright with `@wordpress/e2e-test-utils-playwright`
- **Global setup**: `tests/e2e/globalSetup.js` — authenticates as admin, resets posts/blocks/preferences
- **Global setup**: `tests/e2e/globalSetup.ts` — authenticates as admin, resets posts/blocks/preferences
- **Auth state**: Saved to `artifacts/storage-states/admin.json`
- **Fixtures**: Uses WordPress `admin`, `editor`, and `page` fixtures from `@wordpress/e2e-test-utils-playwright`
- **Run one file**: `npx playwright test tests/e2e/my-test.spec.js`
- **Run one file**: `npx playwright test tests/e2e/my-test.spec.ts`

Example structure:

```js
```ts
import { expect, test } from '@wordpress/e2e-test-utils-playwright';

test.describe( 'My Feature', () => {
Expand Down Expand Up @@ -288,7 +289,7 @@ test.describe( 'My Feature', () => {

- **Rules not applying?** Check that `governance-rules.json` is in the private directory and validates against the schema. Use the admin settings page to verify.
- **Block still visible?** Starting from WordPress 6.8, the block inserter shows all blocks — disallowed ones trigger a snackbar on insert attempt.
- **JS not updating?** Run `npm run build` or `npm run dev` (watch mode). Check that `build/index.js` was regenerated.
- **Frontend not updating?** Run `npm run build` or `npm run dev` (watch mode). Check that `build/index.js` was regenerated.
- **PHP changes not reflecting?** Ensure `wp-env` is running. No build step needed for PHP.
- **Test failures in CI?** Check the CI matrix — tests run against PHP 8.2–8.5 and WP 6.8/latest. Failures may be version-specific.
- **Unexpected vendor changes?** Composer regenerates tracked metadata under `vendor/composer`. Only commit those changes when intentionally updating the production dependency bundle.
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ With this rule set, the following rules will apply:

- Support for `color.duotone` has not been implemented.
- Currently, the plugin is restricted to the post editor only and won't work on other pages like site-editor, widgets, etc.
- Starting from WordPress 6.8, the block inserter sidebar will show all the blocks regardless of the ability to insert them or not. Upon attempting to insert a block that isn't allowed, a snackbar will show up in the lower left corner to highlight that this isn't possible. The regular `/blockname` approach will work just fine, and would be the recommended way of inserting blocks when using this plugin.
- In WordPress 6.8 and 6.9, the main block inserter can show blocks that governance will not allow. Attempting to insert one is still rejected and displays a snackbar notice. WordPress 7.0 and later filter those unavailable blocks from the inserter again, following the [Gutenberg 22.4 inserter fix][gutenberg-22-4].

## Code Filters

Expand Down Expand Up @@ -855,7 +855,7 @@ The npm `postinstall` script installs production Composer dependencies, and the

### Tests

The PHP, JavaScript, and end-to-end tests can be run locally with [`wp-env`][wp-env] and Docker.
The PHP, TypeScript, and end-to-end tests can be run locally with [`wp-env`][wp-env] and Docker.

The default configuration starts a development site at `http://localhost:8888`. Automated tests use an isolated configuration at `http://localhost:8889`, which mounts the governance fixture from `tests/private` without affecting the development site.

Expand All @@ -866,7 +866,7 @@ npx wp-env start --config=.wp-env.test.json
composer run test
```

For the JS unit tests:
For the frontend unit tests:

```
npm run test:js
Expand All @@ -882,7 +882,7 @@ npm run test:e2e

Run multisite PHP coverage with `composer run test-multisite`. Playwright uses the isolated test site at `http://localhost:8889`, with `admin` / `password` as the default credentials.

Run both PHP and JavaScript unit tests with `npm test` after the isolated test environment is running.
Run both PHP and TypeScript unit tests with `npm test` after the isolated test environment is running.

<!-- Links -->

Expand All @@ -892,6 +892,7 @@ Run both PHP and JavaScript unit tests with `npm test` after the isolated test e
[repo-governance-file-location]: governance-rules.json
[repo-schema-location]: governance-schema.json
[gutenberg-block-settings]: https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/#settings
[gutenberg-22-4]: https://make.wordpress.org/core/2026/01/22/whats-new-in-gutenberg-22-4-20-january/
[repo-analytics]: governance/analytics.php
[repo-releases]: https://github.com/automattic/vip-governance-plugin/releases
[vip-go-mu-plugins]: https://github.com/Automattic/vip-go-mu-plugins/
Expand Down
2 changes: 1 addition & 1 deletion build/index.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-hooks', 'wp-i18n', 'wp-notices'), 'version' => '06926ed746d6307eb9a6');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices'), 'version' => '26c4d053b38ba922995b');
3 changes: 1 addition & 2 deletions build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/settings.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('wp-api-fetch'), 'version' => 'f88a32824cccaaaaee1c');
Loading