Commit a9710e0ac36 for woocommerce

commit a9710e0ac3646ae7ddf89a322fc18f2197b2b7ea
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date:   Wed Jul 15 17:11:43 2026 +0300

    [e2e] Stop Core E2E jobs for Blocks-owned specs (#66626)

    * perf(ci): skip Core E2E jobs for Blocks specs

    Context: Core and Blocks E2E projects share the WooCommerce package CI configuration, while Core projects exclude the Blocks spec tree.

    Problem: A Blocks-spec-only pull request matched the broad Core selectors and launched 18 irrelevant Core matrix jobs that could not collect those specs.

    Solution: Narrow the ten pull-request Core selectors to exclude only the Blocks spec tree and cover the production configuration with a regression test. External Blocks helpers, fixtures, setup, themes, and test plugins remain Core triggers.

    * chore: add changelog for Core E2E selector

    Context: The Core E2E selector change modifies WooCommerce package CI behavior.

    Problem: WooCommerce package changes require an explicit changelog entry, including development-facing CI improvements.

    Solution: Record the avoided Core E2E fan-out as a patch-level development change.

    * test(ci): strengthen E2E selector inventory checks

    Context: The real-config selector regression partitions WooCommerce pull-request E2E jobs into generic Core, specialized Core, and Blocks groups.

    Problem: Dynamic discovery alone allowed missing or renamed jobs to disappear silently, while partial PayPal selector profiles still passed the behavior probes.

    Solution: Assert explicit sorted job inventories and the specialized PayPal row's complete compiled selector profile while continuing to exercise path behavior over dynamically discovered groups.

    * test(ci): focus extglob selector coverage

    The selector regression test loaded WooCommerce's live CI configuration and hardcoded its current job catalog. That made monorepo-utils tests drift with downstream configuration while a duplicated matcher could still diverge from production behavior.

    Replace it with parser-owned behavior coverage for extglob negation. Existing job-processing tests cover production matching, so each package now tests its stable boundary without duplicating selection logic.

diff --git a/plugins/woocommerce/changelog/dev-core-e2e-blocks-spec-selector b/plugins/woocommerce/changelog/dev-core-e2e-blocks-spec-selector
new file mode 100644
index 00000000000..d2690cc94fc
--- /dev/null
+++ b/plugins/woocommerce/changelog/dev-core-e2e-blocks-spec-selector
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Stop Core E2E jobs from running for changes limited to Blocks-owned E2E specs.
diff --git a/plugins/woocommerce/package.json b/plugins/woocommerce/package.json
index 869bb49d1db..a02a447687f 100644
--- a/plugins/woocommerce/package.json
+++ b/plugins/woocommerce/package.json
@@ -259,7 +259,7 @@
 						"patterns/**/*.php",
 						"src/**/*.php",
 						"templates/**/*.php",
-						"tests/e2e/**",
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}",
 						".wp-env.e2e.json",
 						"woocommerce.php",
 						"uninstall.php"
@@ -297,7 +297,7 @@
 						"patterns/**/*.php",
 						"src/**/*.php",
 						"templates/**/*.php",
-						"tests/e2e/**",
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}",
 						".wp-env.e2e.json",
 						"woocommerce.php",
 						"uninstall.php"
@@ -324,7 +324,7 @@
 					"command": "test:e2e:gb-stable",
 					"shardingArguments": [],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -377,7 +377,7 @@
 					"command": "test:e2e:hpos-off",
 					"shardingArguments": [],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -407,7 +407,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -440,7 +440,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -473,7 +473,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -506,7 +506,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -540,7 +540,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
@@ -574,7 +574,7 @@
 						"--shard=2/2"
 					],
 					"changes": [
-						"tests/e2e/**"
+						"tests/e2e/{*,!(tests)/**,tests/{*,!(blocks)/**}}"
 					],
 					"onlyForDependencies": [
 						"@woocommerce/e2e-utils-playwright"
diff --git a/tools/monorepo-utils/src/ci-jobs/lib/__tests__/config.spec.ts b/tools/monorepo-utils/src/ci-jobs/lib/__tests__/config.spec.ts
index 825c60da0a7..d956dc60cc6 100644
--- a/tools/monorepo-utils/src/ci-jobs/lib/__tests__/config.spec.ts
+++ b/tools/monorepo-utils/src/ci-jobs/lib/__tests__/config.spec.ts
@@ -149,6 +149,32 @@ describe( 'Config', () => {
 			} );
 		} );

+		it( 'should support extglob negation in changes patterns', () => {
+			const parsed = parseCIConfig( {
+				name: 'foo',
+				config: {
+					ci: {
+						tests: [
+							{
+								name: 'default',
+								changes: 'foo/{*,!(bar)/**}',
+								command: 'foo',
+							},
+						],
+					},
+				},
+			} );
+
+			// changes[ 0 ] is the implicit `package.json` glob.
+			const changes = parsed.jobs[ 0 ].changes[ 1 ];
+
+			expect( changes.test( 'foo/file.ts' ) ).toBe( true );
+			expect( changes.test( 'foo/baz/file.ts' ) ).toBe( true );
+			expect( changes.test( 'foo/baz/deep/file.ts' ) ).toBe( true );
+			expect( changes.test( 'foo/bar/file.ts' ) ).toBe( false );
+			expect( changes.test( 'foo/bar/deep/file.ts' ) ).toBe( false );
+		} );
+
 		it( 'should parse test config with environment', () => {
 			const parsed = parseCIConfig( {
 				name: 'foo',