From 61664eea066f306015743a0f5b0578cf3f01bc5b Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Mon, 18 May 2026 08:35:28 -0400 Subject: [PATCH 01/18] Ensure new and binary files are detected. This adjusts the GitHub Actions workflow code to account for new and/or binary files when checking for changes to files subject to version control. --- .../workflows/reusable-check-built-files.yml | 10 ++++--- .../workflows/test-and-zip-default-themes.yml | 27 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/.github/workflows/reusable-check-built-files.yml b/.github/workflows/reusable-check-built-files.yml index 033b2a46ac3e9..076e153c0c477 100644 --- a/.github/workflows/reusable-check-built-files.yml +++ b/.github/workflows/reusable-check-built-files.yml @@ -81,19 +81,23 @@ jobs: - name: Check for changes to versioned files id: built-file-check run: | - if git diff --quiet; then + if [ -z "$(git status --porcelain)" ]; then echo "uncommitted_changes=false" >> "$GITHUB_OUTPUT" else echo "uncommitted_changes=true" >> "$GITHUB_OUTPUT" fi + - name: Stage all changes for diff generation + if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} + run: git add -A + - name: Display changes to versioned files if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff + run: git diff --cached - name: Save diff to a file if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff > ./changes.diff + run: git diff --cached --binary > ./changes.diff # Uploads the diff file as an artifact. - name: Upload diff file as artifact diff --git a/.github/workflows/test-and-zip-default-themes.yml b/.github/workflows/test-and-zip-default-themes.yml index 1a44a8ff12e3a..8118d0228fcdc 100644 --- a/.github/workflows/test-and-zip-default-themes.yml +++ b/.github/workflows/test-and-zip-default-themes.yml @@ -112,7 +112,12 @@ jobs: # - Sets up Node.js. # - Installs npm dependencies. # - Runs the theme build script. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for uncommitted changes. + # - Stages all uncommitted changes and adds any unversioned files. + # - Displays a diff of all staged changes. + # - Saves staged changes to a .diff file. + # - Uploads the diff file as an artifact. + # - Fails the job when uncommitted changes are detected. test-build-scripts: name: Test ${{ matrix.theme }} build script runs-on: ubuntu-24.04 @@ -160,19 +165,23 @@ jobs: id: built-file-check if: ${{ github.event_name == 'pull_request' }} run: | - if git diff --quiet; then + if [ -z "$(git status --porcelain)" ]; then echo "uncommitted_changes=false" >> "$GITHUB_OUTPUT" else echo "uncommitted_changes=true" >> "$GITHUB_OUTPUT" fi + - name: Stage all changes for diff generation + if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} + run: git add -A + - name: Display changes to versioned files if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff + run: git diff --cached - name: Save diff to a file if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} - run: git diff > ./changes.diff + run: git diff --cached --binary > ./changes.diff # Uploads the diff file as an artifact. - name: Upload diff file as artifact @@ -183,12 +192,20 @@ jobs: path: src/wp-content/themes/${{ matrix.theme }}/changes.diff - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected after build:" + git status --porcelain + exit 1 + fi # Prepares bundled themes for release. # # Performs the following steps: # - Checks out the repository. + # - Sets up Node.js. + # - Installs npm dependencies. + # - Runs the theme build script. # - Uploads the theme files as a workflow artifact (files uploaded as an artifact are automatically zipped). bundle-theme: name: Create ${{ matrix.theme }} ZIP file From f1c3a76f51566ee48a4fb584ac074babdbb507d6 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Wed, 27 May 2026 15:17:06 -0400 Subject: [PATCH 02/18] Bump `gutenberg.sha` to version `23.2.2`. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 430efdd2fba85..bbe002da7d1e8 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "url": "https://develop.svn.wordpress.org/trunk" }, "gutenberg": { - "sha": "a2a354cf35e5b69c3330d6c1cfd42d8dc2efb9fd", + "sha": "218238c46b9161375b1969989cb750038d44355d", "ghcrRepo": "WordPress/gutenberg/gutenberg-wp-develop-build" }, "engines": { From 693ac35bc6b850791e8870273a79aa5cfa236a61 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Wed, 27 May 2026 15:55:31 -0400 Subject: [PATCH 03/18] Check for new files everywhere. --- .../workflows/reusable-check-built-files.yml | 11 +++++----- .../reusable-coding-standards-javascript.yml | 11 +++++++--- .../reusable-coding-standards-php.yml | 11 +++++++--- .../workflows/reusable-end-to-end-tests.yml | 11 +++++++--- .../workflows/reusable-javascript-tests.yml | 11 +++++++--- .../reusable-javascript-type-checking-v1.yml | 11 +++++++--- .../reusable-performance-test-v2.yml | 11 +++++++--- .../workflows/reusable-php-compatibility.yml | 11 +++++++--- .../reusable-phpstan-static-analysis-v1.yml | 11 +++++++--- .../workflows/reusable-phpunit-tests-v2.yml | 11 +++++++--- .../workflows/reusable-phpunit-tests-v3.yml | 11 +++++++--- .../reusable-test-core-build-process.yml | 22 ++++++++++++++----- .../reusable-test-gutenberg-build-process.yml | 11 +++++++--- ...sable-test-local-docker-environment-v1.yml | 11 +++++++--- .../workflows/test-and-zip-default-themes.yml | 4 ++-- 15 files changed, 120 insertions(+), 49 deletions(-) diff --git a/.github/workflows/reusable-check-built-files.yml b/.github/workflows/reusable-check-built-files.yml index 076e153c0c477..5a673bf496ace 100644 --- a/.github/workflows/reusable-check-built-files.yml +++ b/.github/workflows/reusable-check-built-files.yml @@ -24,9 +24,10 @@ jobs: # - Builds Emoji files. # - Builds bundled Root Certificate files. # - Builds WordPress. - # - Checks for changes to versioned files. - # - Displays the result of git diff for debugging purposes. - # - Saves the diff to a patch file. + # - Checks for uncommitted changes. + # - Stages all uncommitted changes and adds any unversioned files. + # - Displays a diff of all staged changes. + # - Saves staged changes to a .diff file. # - Uploads the patch file as an artifact. update-built-files: name: Check and update built files @@ -78,7 +79,7 @@ jobs: - name: Build WordPress run: npm run build:dev - - name: Check for changes to versioned files + - name: Check for uncommitted changes id: built-file-check run: | if [ -z "$(git status --porcelain)" ]; then @@ -91,7 +92,7 @@ jobs: if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} run: git add -A - - name: Display changes to versioned files + - name: Display all uncommitted changes if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} run: git diff --cached diff --git a/.github/workflows/reusable-coding-standards-javascript.yml b/.github/workflows/reusable-coding-standards-javascript.yml index eac5bbdc352f2..b15a5bacf6d46 100644 --- a/.github/workflows/reusable-coding-standards-javascript.yml +++ b/.github/workflows/reusable-coding-standards-javascript.yml @@ -24,7 +24,7 @@ jobs: # - Logs debug information about the GitHub Action runner. # - Installs npm dependencies. # - Run the WordPress JSHint checks. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. jshint: name: JavaScript checks runs-on: ubuntu-24.04 @@ -57,5 +57,10 @@ jobs: - name: Run JSHint run: npm run grunt jshint - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-coding-standards-php.yml b/.github/workflows/reusable-coding-standards-php.yml index 709c598872b23..bff2282fb1296 100644 --- a/.github/workflows/reusable-coding-standards-php.yml +++ b/.github/workflows/reusable-coding-standards-php.yml @@ -36,7 +36,7 @@ jobs: # - Generate a report for displaying issues as pull request annotations. # - Runs PHPCS on the `tests` directory without (warnings included). # - Generate a report for displaying `test` directory issues as pull request annotations. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. phpcs: name: PHP checks runs-on: ubuntu-24.04 @@ -104,5 +104,10 @@ jobs: if: ${{ inputs.old-branch }} run: phpcbf - - name: Ensure version-controlled files are not modified during the tests - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-end-to-end-tests.yml b/.github/workflows/reusable-end-to-end-tests.yml index 87f90f1b53039..c39e03a6c0ab0 100644 --- a/.github/workflows/reusable-end-to-end-tests.yml +++ b/.github/workflows/reusable-end-to-end-tests.yml @@ -61,7 +61,7 @@ jobs: # - Install additional languages. # - Run the E2E tests. # - Uploads screenshots and HTML snapshots as an artifact. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. e2e-tests: name: SCRIPT_DEBUG ${{ inputs.LOCAL_SCRIPT_DEBUG && 'enabled' || 'disabled' }} runs-on: ubuntu-24.04 @@ -153,5 +153,10 @@ jobs: if-no-files-found: ignore include-hidden-files: true - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-javascript-tests.yml b/.github/workflows/reusable-javascript-tests.yml index 3988ec9d6b055..d260dd71c4c11 100644 --- a/.github/workflows/reusable-javascript-tests.yml +++ b/.github/workflows/reusable-javascript-tests.yml @@ -25,7 +25,7 @@ jobs: # - Logs debug information about the GitHub Action runner. # - Installs npm dependencies. # - Run the WordPress QUnit tests. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. test-js: name: Run QUnit tests runs-on: ubuntu-24.04 @@ -67,5 +67,10 @@ jobs: - name: Run QUnit tests run: npm run grunt qunit:compiled - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-javascript-type-checking-v1.yml b/.github/workflows/reusable-javascript-type-checking-v1.yml index 9dabd01e27fa0..d1f484c39c36c 100644 --- a/.github/workflows/reusable-javascript-type-checking-v1.yml +++ b/.github/workflows/reusable-javascript-type-checking-v1.yml @@ -23,7 +23,7 @@ jobs: # - Configures caching for TypeScript build info. # - Runs JavaScript type checking. # - Saves the TypeScript build info. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. typecheck: name: Run JavaScript type checking runs-on: ubuntu-24.04 @@ -72,5 +72,10 @@ jobs: *.tsbuildinfo key: "ts-build-info-${{ github.run_id }}" - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-performance-test-v2.yml b/.github/workflows/reusable-performance-test-v2.yml index c0279c37fe64b..7bafb8fff4894 100644 --- a/.github/workflows/reusable-performance-test-v2.yml +++ b/.github/workflows/reusable-performance-test-v2.yml @@ -102,7 +102,7 @@ jobs: # - Install MU plugin. # - Run performance tests. # - Archive artifacts. - # - Ensure version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. performance: name: Test ${{ inputs.subject == 'base' && inputs.BASE_TAG || inputs.subject }} runs-on: ubuntu-24.04 @@ -272,5 +272,10 @@ jobs: if-no-files-found: error include-hidden-files: true - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-php-compatibility.yml b/.github/workflows/reusable-php-compatibility.yml index 7756330282e6f..ed7cf3abbfae2 100644 --- a/.github/workflows/reusable-php-compatibility.yml +++ b/.github/workflows/reusable-php-compatibility.yml @@ -30,7 +30,7 @@ jobs: # - Make Composer packages available globally. # - Runs the PHP compatibility tests. # - Generate a report for displaying issues as pull request annotations. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. php-compatibility: name: Run compatibility checks runs-on: ubuntu-24.04 @@ -86,5 +86,10 @@ jobs: if: ${{ always() && steps.phpcs.outcome == 'failure' }} run: cs2pr ./.cache/phpcs-compat-report.xml - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-phpstan-static-analysis-v1.yml b/.github/workflows/reusable-phpstan-static-analysis-v1.yml index 745e789580d8f..5fee27c7ab4ab 100644 --- a/.github/workflows/reusable-phpstan-static-analysis-v1.yml +++ b/.github/workflows/reusable-phpstan-static-analysis-v1.yml @@ -30,7 +30,7 @@ jobs: # - Make Composer packages available globally. # - Runs PHPStan static analysis (with Pull Request annotations). # - Saves the PHPStan result cache. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. phpstan: name: Run PHP static analysis runs-on: ubuntu-24.04 @@ -99,5 +99,10 @@ jobs: path: .cache key: "phpstan-result-cache-${{ github.run_id }}" - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-phpunit-tests-v2.yml b/.github/workflows/reusable-phpunit-tests-v2.yml index 5e078b6ef0c2e..21f71546bdb2d 100644 --- a/.github/workflows/reusable-phpunit-tests-v2.yml +++ b/.github/workflows/reusable-phpunit-tests-v2.yml @@ -84,7 +84,7 @@ jobs: # - Logs debug information from inside the WordPress Docker container. # - Install WordPress within the Docker container. # - Run the PHPUnit tests. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. test-php: name: PHP ${{ inputs.php }} / ${{ inputs.multisite && ' Multisite' || 'Single Site' }}${{ inputs.split_slow && ' slow tests' || '' }}${{ inputs.memcached && ' with memcached' || '' }} runs-on: ${{ inputs.os }} @@ -208,5 +208,10 @@ jobs: if: ${{ ! inputs.split_slow }} run: LOCAL_PHP_XDEBUG=true npm run "test:${PHPUNIT_SCRIPT}" -- -v --group xdebug --exclude-group __fakegroup__ - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-phpunit-tests-v3.yml b/.github/workflows/reusable-phpunit-tests-v3.yml index bcad042dfe559..81ce4acd3d54e 100644 --- a/.github/workflows/reusable-phpunit-tests-v3.yml +++ b/.github/workflows/reusable-phpunit-tests-v3.yml @@ -113,7 +113,7 @@ jobs: # - Install WordPress within the Docker container. # - Run the PHPUnit tests. # - Upload the code coverage report to Codecov.io. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. # - Checks out the WordPress Test reporter repository. # - Submit the test results to the WordPress.org host test results. phpunit-tests: @@ -268,8 +268,13 @@ jobs: flags: ${{ inputs.multisite && 'multisite' || 'single' }},php fail_ci_if_error: true - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi - name: Checkout the WordPress Test Reporter if: ${{ github.ref == 'refs/heads/trunk' && inputs.report }} diff --git a/.github/workflows/reusable-test-core-build-process.yml b/.github/workflows/reusable-test-core-build-process.yml index 1566d1583a807..ec702da6df376 100644 --- a/.github/workflows/reusable-test-core-build-process.yml +++ b/.github/workflows/reusable-test-core-build-process.yml @@ -54,10 +54,10 @@ jobs: # - Logs debug information about the GitHub Action runner. # - Installs npm dependencies. # - Builds WordPress to run from the desired location (src or build). - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes after building. # - Creates a ZIP of the built WordPress files (when building to the build directory). # - Cleans up after building WordPress. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes after cleaning. # - Uploads the ZIP as a GitHub Actions artifact (when building to the build directory). # - Saves the pull request number to a text file. # - Uploads the pull request number as an artifact. @@ -119,8 +119,13 @@ jobs: - name: Build WordPress to run from ${{ inputs.directory }} run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }} - - name: Ensure version-controlled files are not modified or deleted during building - run: git diff --exit-code + - name: Check for uncommitted changes after building + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi - name: Create ZIP of built files if: ${{ inputs.directory == 'build' && contains( inputs.os, 'ubuntu-' ) }} @@ -129,8 +134,13 @@ jobs: - name: Clean after building to run from ${{ inputs.directory }} run: npm run grunt ${{ inputs.directory == 'src' && 'clean -- --dev' || 'clean' }} - - name: Ensure version-controlled files are not modified or deleted during cleaning - run: git diff --exit-code + - name: Check for uncommitted changes after cleaning + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi - name: Upload ZIP as a GitHub Actions artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/.github/workflows/reusable-test-gutenberg-build-process.yml b/.github/workflows/reusable-test-gutenberg-build-process.yml index 4a780d08ee07f..635d8dc0c473f 100644 --- a/.github/workflows/reusable-test-gutenberg-build-process.yml +++ b/.github/workflows/reusable-test-gutenberg-build-process.yml @@ -39,7 +39,7 @@ jobs: # - Installs Core npm dependencies. # - Builds WordPress to run from the relevant location (src or build). # - Builds Gutenberg. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes after building. build-process-tests: name: ${{ contains( inputs.os, 'macos-' ) && 'MacOS' || contains( inputs.os, 'windows-' ) && 'Windows' || 'Linux' }} permissions: @@ -96,5 +96,10 @@ jobs: run: npm run build working-directory: ${{ env.GUTENBERG_DIRECTORY }} - - name: Ensure version-controlled files are not modified or deleted during building - run: git diff --exit-code + - name: Check for uncommitted changes after building + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/reusable-test-local-docker-environment-v1.yml b/.github/workflows/reusable-test-local-docker-environment-v1.yml index 8f1a556afa2b4..50118d45045ee 100644 --- a/.github/workflows/reusable-test-local-docker-environment-v1.yml +++ b/.github/workflows/reusable-test-local-docker-environment-v1.yml @@ -71,7 +71,7 @@ jobs: # - Runs a WP CLI command. # - Tests the logs command. # - Tests the reset command. - # - Ensures version-controlled files are not modified or deleted. + # - Checks for any uncommitted changes. local-docker-environment-tests: name: ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.memcached && ' with memcached' || '' }}${{ 'example.org' != inputs.tests-domain && format( ' {0}', inputs.tests-domain ) || '' }} permissions: @@ -166,5 +166,10 @@ jobs: - name: Reset the Docker environment run: npm run env:reset - - name: Ensure version-controlled files are not modified or deleted - run: git diff --exit-code + - name: Check for uncommitted changes + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "Uncommitted changes detected:" + git status --porcelain + exit 1 + fi diff --git a/.github/workflows/test-and-zip-default-themes.yml b/.github/workflows/test-and-zip-default-themes.yml index 8118d0228fcdc..d80a1d9731af2 100644 --- a/.github/workflows/test-and-zip-default-themes.yml +++ b/.github/workflows/test-and-zip-default-themes.yml @@ -161,7 +161,7 @@ jobs: - name: Build theme run: npm run build - - name: Check for changes to versioned files + - name: Check for uncommitted changes id: built-file-check if: ${{ github.event_name == 'pull_request' }} run: | @@ -175,7 +175,7 @@ jobs: if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} run: git add -A - - name: Display changes to versioned files + - name: Display all uncommitted changes if: ${{ steps.built-file-check.outputs.uncommitted_changes == 'true' }} run: git diff --cached From 9db27d8ec54f3f9d1557c30d6a86fdeb9e6aca0f Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Wed, 27 May 2026 16:00:16 -0400 Subject: [PATCH 04/18] Ignore file built by build script testing workflow. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15876fa47fee8..871c49e39ba6a 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ wp-tests-config.php /artifacts /setup.log /coverage +wordpress.zip # Files and folders that get created in wp-content /src/wp-content/blogs.dir From 2e132e81054cd54349b4456d484d6fe3663699ac Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:23:47 +0200 Subject: [PATCH 05/18] Bump hash to latest. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbe002da7d1e8..8cc9c16fcef07 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "url": "https://develop.svn.wordpress.org/trunk" }, "gutenberg": { - "sha": "218238c46b9161375b1969989cb750038d44355d", + "sha": "ac1566bd9ac5a8e4b26e4d2093bea4a5525ae001", "ghcrRepo": "WordPress/gutenberg/gutenberg-wp-develop-build" }, "engines": { From dec4d6ea02830fdac7ef89797241b585df337ef9 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 00:05:31 +0200 Subject: [PATCH 06/18] Add code coverage related files to `.gitignore`. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 871c49e39ba6a..4d91320b53264 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,10 @@ wp-tests-config.php /artifacts /setup.log /coverage +/codecov +codecov.* wordpress.zip +wp-code-coverage-*.xml # Files and folders that get created in wp-content /src/wp-content/blogs.dir From 4766edbcb4fb2be1fa55ce798ee1b234e88bb396 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 00:05:45 +0200 Subject: [PATCH 07/18] Add Performance testing Zip file to `.gitignore`. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4d91320b53264..5a7f9b5aef66e 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ wp-tests-config.php /coverage /codecov codecov.* +before.zip wordpress.zip wp-code-coverage-*.xml From 25b53a78e9a16e2f77dc6a7f75dc913cf03863c2 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 00:31:45 +0200 Subject: [PATCH 08/18] Force `bash` for `windows` runners. --- .github/workflows/reusable-test-core-build-process.yml | 2 ++ .github/workflows/reusable-test-gutenberg-build-process.yml | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/reusable-test-core-build-process.yml b/.github/workflows/reusable-test-core-build-process.yml index ec702da6df376..35fd6c5e699dc 100644 --- a/.github/workflows/reusable-test-core-build-process.yml +++ b/.github/workflows/reusable-test-core-build-process.yml @@ -120,6 +120,7 @@ jobs: run: npm run ${{ inputs.directory == 'src' && 'build:dev' || 'build' }} - name: Check for uncommitted changes after building + shell: bash run: | if [ -n "$(git status --porcelain)" ]; then echo "Uncommitted changes detected:" @@ -135,6 +136,7 @@ jobs: run: npm run grunt ${{ inputs.directory == 'src' && 'clean -- --dev' || 'clean' }} - name: Check for uncommitted changes after cleaning + shell: bash run: | if [ -n "$(git status --porcelain)" ]; then echo "Uncommitted changes detected:" diff --git a/.github/workflows/reusable-test-gutenberg-build-process.yml b/.github/workflows/reusable-test-gutenberg-build-process.yml index 635d8dc0c473f..ae5e4cd74d298 100644 --- a/.github/workflows/reusable-test-gutenberg-build-process.yml +++ b/.github/workflows/reusable-test-gutenberg-build-process.yml @@ -97,6 +97,7 @@ jobs: working-directory: ${{ env.GUTENBERG_DIRECTORY }} - name: Check for uncommitted changes after building + shell: bash run: | if [ -n "$(git status --porcelain)" ]; then echo "Uncommitted changes detected:" From 6142e238523354813f739c851a8f01cd83df1912 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 08:30:30 +0200 Subject: [PATCH 09/18] Prevent Windows from converting to CRLF. --- .github/workflows/reusable-test-core-build-process.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/reusable-test-core-build-process.yml b/.github/workflows/reusable-test-core-build-process.yml index 35fd6c5e699dc..e767f9d80c306 100644 --- a/.github/workflows/reusable-test-core-build-process.yml +++ b/.github/workflows/reusable-test-core-build-process.yml @@ -69,6 +69,14 @@ jobs: timeout-minutes: 20 steps: + # Windows converts LF to CRLF on checkout. This makes every built file appear as modified because the build output + # will be CRLF. + - name: Configure Git line endings on Windows + if: ${{ contains( inputs.os, 'windows-' ) }} + run: | + git config --global core.autocrlf false + git config --global core.eol lf + - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: From d7bdf169d54a468166b56faad415a595917fe964 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:57:20 +0200 Subject: [PATCH 10/18] Include icon library-related files in clean. --- Gruntfile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index 815ccce3af535..128300261120b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -51,6 +51,8 @@ module.exports = function(grunt) { gutenbergFiles = [ 'wp-includes/js/dist', 'wp-includes/css/dist', + 'wp-includes/images/icon-library', + 'wp-includes/assets/icon-library-manifest.php', // Old location kept temporarily to ensure they are cleaned up. 'wp-includes/icons', ], From 59b88f3b9fa1d069464f8a6eb8065ac9b93fd04f Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:57:32 +0200 Subject: [PATCH 11/18] Ensure `clean:gutenberg` runs prior to building. --- Gruntfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Gruntfile.js b/Gruntfile.js index 128300261120b..3601dc13143ab 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2159,6 +2159,7 @@ module.exports = function(grunt) { } ); grunt.registerTask( 'build:gutenberg', [ + 'clean:gutenberg', 'copy:gutenberg-php', 'routes:setup', 'copy:routes', From 25b9b9ebada2ebbe952123e6ecdab06ed79c9dc5 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:28:44 +0200 Subject: [PATCH 12/18] Exclude manifest file. This is meant to include directories. --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 3601dc13143ab..7023edb0f177d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,7 +52,6 @@ module.exports = function(grunt) { 'wp-includes/js/dist', 'wp-includes/css/dist', 'wp-includes/images/icon-library', - 'wp-includes/assets/icon-library-manifest.php', // Old location kept temporarily to ensure they are cleaned up. 'wp-includes/icons', ], From b3341ca6839a8433a72cdfc04cb31baedd1896fd Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:45:43 +0200 Subject: [PATCH 13/18] Reorganize tasks to avoid repetition. --- Gruntfile.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 7023edb0f177d..aa7bb553a1c10 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2158,6 +2158,7 @@ module.exports = function(grunt) { } ); grunt.registerTask( 'build:gutenberg', [ + 'gutenberg:verify', 'clean:gutenberg', 'copy:gutenberg-php', 'routes:setup', @@ -2174,24 +2175,22 @@ module.exports = function(grunt) { grunt.registerTask( 'build', function() { if ( grunt.option( 'dev' ) ) { grunt.task.run( [ - 'gutenberg:verify', + 'build:gutenberg', 'build:js', 'build:css', 'build:codemirror', - 'build:gutenberg', - 'build:certificates' + 'build:certificates', ] ); } else { grunt.task.run( [ - 'gutenberg:verify', - 'build:certificates', + 'build:gutenberg', 'build:files', 'build:js', 'build:css', 'build:codemirror', - 'build:gutenberg', + 'build:certificates', 'replace:source-maps', - 'verify:build' + 'verify:build', ] ); } } ); From 640397bef081aa3d2fdaabc377d25aa9e39b78ab Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 16:21:18 +0200 Subject: [PATCH 14/18] Ensure files deleted in `gutenberg` are removed. --- Gruntfile.js | 52 ++++++++++++++++++++++++++++++----------- tools/gutenberg/copy.js | 19 ++++----------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index aa7bb553a1c10..9034055de5f06 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -47,15 +47,22 @@ module.exports = function(grunt) { 'wp-includes/js/', ], - // All files copied from the Gutenberg repository excluded from version control. + // Unversioned files copied from the Gutenberg repository. gutenbergFiles = [ 'wp-includes/js/dist', 'wp-includes/css/dist', - 'wp-includes/images/icon-library', // Old location kept temporarily to ensure they are cleaned up. 'wp-includes/icons', ], + // Files copied from Gutenberg subject to version control. + gutenbergVersionedFiles = [ + 'wp-includes/images/icon-library', + 'wp-includes/build', + 'wp-includes/blocks/*', + '!wp-includes/blocks/index.php', + ], + // All files built by Webpack, in /src or /build. // Webpack only builds Core-specific media files and development scripts. // Blocks, packages, script modules, and vendors come from the Gutenberg build. @@ -246,6 +253,25 @@ module.exports = function(grunt) { gutenberg: gutenbergFiles.map( function( file ) { return setFilePath( WORKING_DIR, file ); }), + + /* + * Delete directories and files subjet to version control where the contents come from Gutenberg. + * + * This handles instances where a file remains present even after being deleted upstream. + * + * This task is intentionally skipped unless the current task will re-copy the corresponding files. + */ + 'gutenberg-versioned': { + filter: function() { + var allowedTasks = [ 'build', 'build:dev', 'build:gutenberg', 'clean:gutenberg-versioned' ]; + return allowedTasks.some( function( task ) { + return grunt.cli.tasks.indexOf( task ) !== -1; + } ); + }, + src: gutenbergVersionedFiles.map( function( file ) { + return setFilePath( SOURCE_DIR, file ); + } ), + }, dynamic: { dot: true, expand: true, @@ -667,7 +693,7 @@ module.exports = function(grunt) { 'constants.php', 'pages/**/*.php', ], - dest: WORKING_DIR + 'wp-includes/build/', + dest: SOURCE_DIR + 'wp-includes/build/', } ], }, /* @@ -684,7 +710,7 @@ module.exports = function(grunt) { expand: true, cwd: 'gutenberg/build', src: [], - dest: WORKING_DIR + 'wp-includes/build/', + dest: SOURCE_DIR + 'wp-includes/build/', }, 'gutenberg-js': { files: [ { @@ -693,7 +719,7 @@ module.exports = function(grunt) { src: [ 'pages/**/*.js', ], - dest: WORKING_DIR + 'wp-includes/build/', + dest: SOURCE_DIR + 'wp-includes/build/', } ], }, 'gutenberg-modules': { @@ -707,7 +733,7 @@ module.exports = function(grunt) { // with no debugging value over the minified versions. '!vips/!(*.min).js', ], - dest: WORKING_DIR + 'wp-includes/js/dist/script-modules/', + dest: SOURCE_DIR + 'wp-includes/js/dist/script-modules/', } ], }, 'gutenberg-styles': { @@ -720,7 +746,7 @@ module.exports = function(grunt) { // Per-block CSS is copied to wp-includes/blocks/ by tools/gutenberg/copy.js. '!block-library/*/**', ], - dest: WORKING_DIR + 'wp-includes/css/dist/', + dest: SOURCE_DIR + 'wp-includes/css/dist/', } ], }, 'gutenberg-theme-json': { @@ -739,11 +765,11 @@ module.exports = function(grunt) { files: [ { src: 'gutenberg/lib/theme.json', - dest: WORKING_DIR + 'wp-includes/theme.json', + dest: SOURCE_DIR + 'wp-includes/theme.json', }, { src: 'gutenberg/lib/theme-i18n.json', - dest: WORKING_DIR + 'wp-includes/theme-i18n.json', + dest: SOURCE_DIR + 'wp-includes/theme-i18n.json', }, ], }, @@ -752,7 +778,7 @@ module.exports = function(grunt) { expand: true, cwd: 'gutenberg/packages/icons/src/library', src: '*.svg', - dest: WORKING_DIR + 'wp-includes/images/icon-library', + dest: SOURCE_DIR + 'wp-includes/images/icon-library', } ], }, 'icon-library-manifest': { @@ -774,7 +800,7 @@ module.exports = function(grunt) { }, files: [ { src: 'gutenberg/packages/icons/src/manifest.php', - dest: WORKING_DIR + 'wp-includes/assets/icon-library-manifest.php', + dest: SOURCE_DIR + 'wp-includes/assets/icon-library-manifest.php', } ], }, }, @@ -1678,10 +1704,9 @@ module.exports = function(grunt) { grunt.registerTask( 'gutenberg:copy', 'Copies Gutenberg JS packages and block assets to WordPress Core.', function() { const done = this.async(); - const buildDir = grunt.option( 'dev' ) ? 'src' : 'build'; grunt.util.spawn( { cmd: 'node', - args: [ 'tools/gutenberg/copy.js', `--build-dir=${ buildDir }` ], + args: [ 'tools/gutenberg/copy.js' ], opts: { stdio: 'inherit' } }, function( error ) { done( ! error ); @@ -2159,6 +2184,7 @@ module.exports = function(grunt) { grunt.registerTask( 'build:gutenberg', [ 'gutenberg:verify', + 'clean:gutenberg-versioned', 'clean:gutenberg', 'copy:gutenberg-php', 'routes:setup', diff --git a/tools/gutenberg/copy.js b/tools/gutenberg/copy.js index 8589c9581bed1..f6a24d2306db3 100644 --- a/tools/gutenberg/copy.js +++ b/tools/gutenberg/copy.js @@ -19,21 +19,10 @@ const rootDir = path.resolve( __dirname, '../..' ); const gutenbergDir = path.join( rootDir, 'gutenberg' ); const gutenbergBuildDir = path.join( gutenbergDir, 'build' ); -/* - * Determine build target from command line argument (--dev or --build-dir). - * Default to 'src' for development. - */ -const args = process.argv.slice( 2 ); -const buildDirArg = args.find( ( arg ) => arg.startsWith( '--build-dir=' ) ); -const buildTarget = buildDirArg - ? buildDirArg.split( '=' )[ 1 ] - : args.includes( '--dev' ) - ? 'src' - : 'build'; - -const wpIncludesDir = path.join( rootDir, buildTarget, 'wp-includes' ); +// All files handled in this script are subject to version control, so they should always be placed into src/. +const wpIncludesDir = path.join( rootDir, 'src', 'wp-includes' ); -/** +/* * Copy configuration. * Defines what to copy from Gutenberg build and where it goes in Core. */ @@ -508,7 +497,7 @@ function generateBlocksJson() { * Main execution function. */ async function main() { - console.log( `📦 Copying Gutenberg build to ${ buildTarget }/...` ); + console.log( '📦 Copying versioned Gutenberg files to src/...' ); if ( ! fs.existsSync( gutenbergBuildDir ) ) { console.error( '❌ Gutenberg build directory not found' ); From 050b49102e880d18f7e98b26d5568643087e42e7 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:17:40 +0200 Subject: [PATCH 15/18] Undo hash bump. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8cc9c16fcef07..430efdd2fba85 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "url": "https://develop.svn.wordpress.org/trunk" }, "gutenberg": { - "sha": "ac1566bd9ac5a8e4b26e4d2093bea4a5525ae001", + "sha": "a2a354cf35e5b69c3330d6c1cfd42d8dc2efb9fd", "ghcrRepo": "WordPress/gutenberg/gutenberg-wp-develop-build" }, "engines": { From db90b714386a7858a4d1156a5421e3222dda07f8 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:57:20 +0200 Subject: [PATCH 16/18] Include icon library-related files in clean. --- Gruntfile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index 815ccce3af535..128300261120b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -51,6 +51,8 @@ module.exports = function(grunt) { gutenbergFiles = [ 'wp-includes/js/dist', 'wp-includes/css/dist', + 'wp-includes/images/icon-library', + 'wp-includes/assets/icon-library-manifest.php', // Old location kept temporarily to ensure they are cleaned up. 'wp-includes/icons', ], From 2619a7e353323f19e0733b036bf694380e272bde Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:57:32 +0200 Subject: [PATCH 17/18] Ensure `clean:gutenberg` runs prior to building. --- Gruntfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Gruntfile.js b/Gruntfile.js index 128300261120b..3601dc13143ab 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2159,6 +2159,7 @@ module.exports = function(grunt) { } ); grunt.registerTask( 'build:gutenberg', [ + 'clean:gutenberg', 'copy:gutenberg-php', 'routes:setup', 'copy:routes', From 03b18179a7f1e7fb752f63b329343a69d4cf974a Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:28:44 +0200 Subject: [PATCH 18/18] Exclude manifest file. This is meant to include directories. --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 3601dc13143ab..7023edb0f177d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -52,7 +52,6 @@ module.exports = function(grunt) { 'wp-includes/js/dist', 'wp-includes/css/dist', 'wp-includes/images/icon-library', - 'wp-includes/assets/icon-library-manifest.php', // Old location kept temporarily to ensure they are cleaned up. 'wp-includes/icons', ],