From 974ef750cfef7d2c7aae1e4030edf28ec6932a8b Mon Sep 17 00:00:00 2001
From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com>
Date: Tue, 17 Mar 2026 20:41:14 -0400
Subject: [PATCH 1/5] Add workflow to compare PR with the build server.
---
.github/workflows/check-built-files.yml | 19 ++-
.github/workflows/pull-request-comments.yml | 146 +++++++++++++++++-
.../workflows/reusable-check-built-files.yml | 8 +-
.../reusable-compare-built-files-v1.yml | 109 +++++++++++++
4 files changed, 272 insertions(+), 10 deletions(-)
create mode 100644 .github/workflows/reusable-compare-built-files-v1.yml
diff --git a/.github/workflows/check-built-files.yml b/.github/workflows/check-built-files.yml
index 5f62f825c243e..bb21adf729c46 100644
--- a/.github/workflows/check-built-files.yml
+++ b/.github/workflows/check-built-files.yml
@@ -1,4 +1,4 @@
-# Checks for uncommitted changes to built files in pull requests.
+# Checks for uncommitted or unexpected changes to built files within pull requests.
name: Check Built Files (PRs)
on:
@@ -23,11 +23,13 @@ on:
- '.nvmrc'
- 'Gruntfile.js'
- 'webpack.config.js'
- - 'tools/webpack/**'
+ - 'tools/**'
# These files configure Composer. Changes could affect the outcome.
- 'composer.*'
# Confirm any changes to relevant workflow files.
- '.github/workflows/check-built-files.yml'
+ - '.github/workflows/reusable-check-built-files.yml'
+ - '.github/workflows/reusable-compare-built-files-*.yml'
# Changes to the default themes should be handled by the themes workflows.
- '!src/wp-content/themes/twenty**'
@@ -43,9 +45,18 @@ concurrency:
permissions: {}
jobs:
+ # Checks built files for uncommitted changes.
check-for-built-file-changes:
- name: Check built files
- if: ${{ github.repository == 'wordpress/wordpress-develop' }}
+ name: Check for uncommitted changes
+ if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
uses: ./.github/workflows/reusable-check-built-files.yml
permissions:
contents: read
+
+ # Compares the build directory with the WordPress/WordPress repository.
+ compare-with-build-server:
+ name: Compare built files to WordPress/WordPress
+ uses: ./.github/workflows/reusable-compare-built-files-v1.yml
+ permissions:
+ contents: read
+ if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
diff --git a/.github/workflows/pull-request-comments.yml b/.github/workflows/pull-request-comments.yml
index da30e2feb7f11..8e2cba4bfd766 100644
--- a/.github/workflows/pull-request-comments.yml
+++ b/.github/workflows/pull-request-comments.yml
@@ -5,7 +5,7 @@ on:
pull_request_target:
types: [ 'opened', 'synchronize', 'reopened', 'edited' ]
workflow_run:
- workflows: [ 'Test Build Processes' ]
+ workflows: [ 'Check Built Files (PRs)', 'Test Build Processes' ]
types:
- completed
@@ -22,6 +22,7 @@ permissions: {}
jobs:
# Comments on a pull request when the author is a first time contributor.
post-welcome-message:
+ name: Contributor welcome message
runs-on: ubuntu-24.04
permissions:
issues: write
@@ -79,7 +80,7 @@ jobs:
# Leaves a comment on a pull request with a link to test the changes in a WordPress Playground instance.
playground-details:
- name: Comment on a pull request with Playground details
+ name: Leave Playground testing details
runs-on: ubuntu-24.04
permissions:
issues: write
@@ -87,6 +88,7 @@ jobs:
if: >
github.repository == 'WordPress/wordpress-develop' &&
github.event.workflow_run.event == 'pull_request' &&
+ github.event.workflow_run.name == 'Test Build Processes' &&
github.event.workflow_run.conclusion == 'success'
steps:
- name: Download artifact
@@ -180,6 +182,146 @@ jobs:
github.rest.issues.createComment( commentInfo );
+ # Leaves a comment on a pull request noting differences between the PR and the build server.
+ build-server-comparison:
+ name: Note differences with the build server
+ runs-on: ubuntu-24.04
+ permissions:
+ issues: write
+ pull-requests: write
+ if: >
+ github.repository == 'WordPress/wordpress-develop' &&
+ github.event.workflow_run.event == 'pull_request' &&
+ github.event.workflow_run.name == 'Check Built Files (PRs)' &&
+ github.event.workflow_run.conclusion == 'success'
+ steps:
+ - name: Download artifact
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ env:
+ RUN_ID: ${{ github.event.workflow_run.id }}
+ with:
+ script: |
+ const artifacts = await github.rest.actions.listWorkflowRunArtifacts( {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: process.env.RUN_ID,
+ } );
+
+ const matchArtifact = artifacts.data.artifacts.filter( ( artifact ) => {
+ return artifact.name === 'build-server-comparison'
+ } )[0];
+
+ if ( ! matchArtifact ) {
+ core.setFailed( 'No artifact found!' );
+ return;
+ }
+
+ const download = await github.rest.actions.downloadArtifact( {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ artifact_id: matchArtifact.id,
+ archive_format: 'zip',
+ } );
+
+ const fs = require( 'fs' );
+ fs.writeFileSync( '${{github.workspace}}/build-server-comparison.zip', Buffer.from( download.data ) )
+
+ - name: Unzip the artifact containing the comparison info
+ run: unzip build-server-comparison.zip
+
+ - name: Leave a comment with any differences noticed
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ with:
+ script: |
+ const fs = require( 'fs' );
+ const issue_number = Number( fs.readFileSync( './NR' ) );
+ const fileChanges = fs.readFileSync( './file-changes.txt', 'utf8' );
+ const diffContents = fs.readFileSync( './changes.diff', 'utf8' );
+ const MAX_DIFF_LENGTH = 50000; // GitHub has a 65,536 character limit for comments.
+
+ core.info( `Checking pull request #${issue_number}.` );
+
+ // Confirm that the pull request is still open before leaving a comment.
+ const pr = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: issue_number,
+ });
+
+ if ( pr.data.state !== 'open' ) {
+ core.info( 'The pull request has been closed. No comment will be left.' );
+ return;
+ }
+
+ // Comments are only added after the first successful build. Check for the presence of a comment and bail early.
+ const commentInfo = {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number,
+ };
+
+ const comments = ( await github.rest.issues.listComments( commentInfo ) ).data;
+
+ for ( const currentComment of comments ) {
+ if ( currentComment.user.type === 'Bot' && currentComment.body.includes( 'Build Script Results Comparison' ) ) {
+ commentInfo.comment_id = currentComment.id;
+ break;
+ }
+ };
+
+ commentInfo.body = '## Build Server Comparison';
+
+ // Post or update the comment.
+ if ( fileChanges.trim() === '' ) {
+ commentInfo.body += 'The contents of the `build` directory after running `npm run build` matches the contents of the WordPress/WordPress repository. No differences were found.';
+ } else {
+ commentInfo.body += 'The contents of the `build` directory after running `npm run build` has been compared with the contents of the WordPress/WordPress repository.
+
+ **Review these differences carefully for any unexpected results.**
+
+ ### List of Modified Files
+
+ \`\`\`
+ ${ fileChanges }
+ \`\`\`
+
+ ### Full Diff File
+ `;
+
+ if ( diffContents.length > MAX_DIFF_LENGTH ) {
+ const cutoff = diffContents.lastIndexOf( '\n', MAX_DIFF_LENGTH );
+ const truncated = diffContents.substring( 0, cutoff );
+
+ commentInfo.body += `
+ Click to expand (truncated)
+
+ \`\`\`diff
+ ${ truncated }
+ \`\`\`
+
+ ⚠️ The diff was too large to display in full.
+
+ `;
+ } else {
+ commentInfo.body += `
+ Click to expand
+
+ \`\`\`diff
+ ${ diffContents }
+ \`\`\`
+
+ `;
+ }
+
+ commentInfo.body += `[Download the complete .diff file from the workflow run](https://github.com/${ context.repo.owner }/${ context.repo.repo }/actions/runs/${ process.env.RUN_ID }).`;
+ }
+
+ if ( commentInfo.comment_id ) {
+ github.rest.issues.updateComment( commentInfo );
+ } else {
+ github.rest.issues.createComment( commentInfo );
+ }
+
# Manages comments reminding contributors to include a Trac ticket link when opening a pull request.
trac-ticket-check:
name: Manage Trac ticket reminders for pull requests
diff --git a/.github/workflows/reusable-check-built-files.yml b/.github/workflows/reusable-check-built-files.yml
index 11d97639a30fc..30bb3ed5021b4 100644
--- a/.github/workflows/reusable-check-built-files.yml
+++ b/.github/workflows/reusable-check-built-files.yml
@@ -1,7 +1,7 @@
##
# A reusable workflow that checks for uncommitted changes to built files in pull requests.
##
-name: Check Built Files (PRs)
+name: Check for Changes to Versioned Files (reusable)
on:
workflow_call:
@@ -9,7 +9,7 @@ on:
permissions: {}
jobs:
- # Checks a PR for uncommitted changes to built files.
+ # Checks a PR for uncommitted changes to versioned files.
#
# When changes are detected, the patch is stored as an artifact for processing by the Commit Built File Changes
# workflow.
@@ -29,8 +29,8 @@ jobs:
# - Displays the result of git diff for debugging purposes.
# - Saves the diff to a patch file.
# - Uploads the patch file as an artifact.
- update-built-files:
- name: Check and update built files
+ check-versioned-files:
+ name: Check for changes
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
diff --git a/.github/workflows/reusable-compare-built-files-v1.yml b/.github/workflows/reusable-compare-built-files-v1.yml
new file mode 100644
index 0000000000000..94debf8a47a23
--- /dev/null
+++ b/.github/workflows/reusable-compare-built-files-v1.yml
@@ -0,0 +1,109 @@
+##
+# A reusable workflow that compares the results of the build script with the most recent commit to WordPress/WordPress.
+##
+name: Compare Built Files (reusable)
+
+on:
+ workflow_call:
+
+# Disable permissions for all available scopes by default.
+# Any needed permissions should be configured at the job level.
+permissions: {}
+
+jobs:
+ # Runs the PHP coding standards checks.
+ #
+ # Violations are reported inline with annotations.
+ #
+ # Performs the following steps:
+ # - Checks out the repository.
+ # - Sets up Node.js.
+ # - Sets up PHP.
+ # - Installs Composer dependencies.
+ # - Logs debug information about the GitHub Action runner.
+ # - Installs npm dependencies.
+ # - Builds WordPress to run from the build directory.
+ # - Ensures version-controlled files are not modified or deleted.
+ # - Checks out the WordPress/WordPress repository.
+ # - Creates a directory for text files to be uploaded as an artifact.
+ # - Stores a list of files that differ in the build directory from WordPress/WordPress.
+ # - Stores a diff file comparing the build directory to WordPress/WordPress.
+ # - Saves the pull request number to a text file.
+ # - Uploads the generated files as an artifact.
+ compare-built-files:
+ name: Compare built files to WordPress/WordPress
+ runs-on: ubuntu-24.04
+ permissions:
+ contents: read
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
+ persist-credentials: false
+
+ - name: Set up Node.js
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
+ with:
+ node-version-file: '.nvmrc'
+ cache: npm
+
+ - name: Set up PHP
+ uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
+ with:
+ php-version: '8.4'
+ coverage: none
+
+ # Since Composer dependencies are installed using `composer update` and no lock file is in version control,
+ # passing a custom cache suffix ensures that the cache is flushed at least once per week.
+ - name: Install Composer dependencies
+ uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # v4.0.0
+ with:
+ custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F")
+
+ - name: Log debug information
+ run: |
+ npm --version
+ node --version
+ git --version
+
+ - name: Install npm Dependencies
+ run: npm ci
+
+ - name: Build WordPress to run from build directory
+ run: npm run build
+
+ - name: Ensure version-controlled files are not modified or deleted
+ run: git diff --exit-code
+
+ - name: Checkout WordPress/WordPress
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ repository: 'WordPress/WordPress'
+ path: ${{ github.workspace }}/build-server
+ show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
+ persist-credentials: false
+
+ - name: Create directory for artifacts
+ run: mkdir artifacts
+
+ - name: Create a list of files that have changed
+ run: diff -rq ${{ github.workspace }}/build ${{ github.workspace }}/build-server | sed "s|${{ github.workspace }}/||g" > artifacts/file-changes.txt
+
+ - name: Create a list of files that have changed
+ run: diff -r ${{ github.workspace }}/build ${{ github.workspace }}/build-server | sed "s|${{ github.workspace }}/||g" > artifacts/changes.diff
+
+ - name: Save PR number
+ run: echo "${EVENT_NUMBER}" > ./artifacts/NR
+ env:
+ EVENT_NUMBER: ${{ github.event.number }}
+
+ # Uploads the associated text files as an artifact.
+ - name: Upload comparison results as an artifact
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name == 'pull_request' }}
+ with:
+ name: build-server-comparison
+ path: artifacts/
From f66cdb3c737f3877cda0670246cc8fff6ae0ab21 Mon Sep 17 00:00:00 2001
From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com>
Date: Tue, 17 Mar 2026 23:22:36 -0400
Subject: [PATCH 2/5] Account for differences in branch names.
---
.github/workflows/reusable-compare-built-files-v1.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/reusable-compare-built-files-v1.yml b/.github/workflows/reusable-compare-built-files-v1.yml
index 94debf8a47a23..59fa79dc5e111 100644
--- a/.github/workflows/reusable-compare-built-files-v1.yml
+++ b/.github/workflows/reusable-compare-built-files-v1.yml
@@ -82,6 +82,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: 'WordPress/WordPress'
+ ref: ${{ github.base_ref == 'trunk' && 'master' || format( '{0}-branch', github.base_ref ) }}
path: ${{ github.workspace }}/build-server
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
persist-credentials: false
From bbe7bd725bdad656dd48c4d5bfbe526cd4309008 Mon Sep 17 00:00:00 2001
From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com>
Date: Wed, 18 Mar 2026 00:49:51 -0400
Subject: [PATCH 3/5] Bug fixes to the commenting workflow.
---
.github/workflows/pull-request-comments.yml | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/pull-request-comments.yml b/.github/workflows/pull-request-comments.yml
index 8e2cba4bfd766..70ef650b001e8 100644
--- a/.github/workflows/pull-request-comments.yml
+++ b/.github/workflows/pull-request-comments.yml
@@ -231,6 +231,9 @@ jobs:
- name: Leave a comment with any differences noticed
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ env:
+ RUN_ID:
+ ${{ github.event.workflow_run.id }}
with:
script: |
const fs = require( 'fs' );
@@ -263,19 +266,19 @@ jobs:
const comments = ( await github.rest.issues.listComments( commentInfo ) ).data;
for ( const currentComment of comments ) {
- if ( currentComment.user.type === 'Bot' && currentComment.body.includes( 'Build Script Results Comparison' ) ) {
+ if ( currentComment.user.type === 'Bot' && currentComment.body.includes( 'Build Server Comparison' ) ) {
commentInfo.comment_id = currentComment.id;
break;
}
};
- commentInfo.body = '## Build Server Comparison';
+ commentInfo.body = "## Build Server Comparison\n\n";
// Post or update the comment.
if ( fileChanges.trim() === '' ) {
commentInfo.body += 'The contents of the `build` directory after running `npm run build` matches the contents of the WordPress/WordPress repository. No differences were found.';
} else {
- commentInfo.body += 'The contents of the `build` directory after running `npm run build` has been compared with the contents of the WordPress/WordPress repository.
+ commentInfo.body += `The contents of the \`build\` directory after running \`npm run build\` has been compared with the contents of the WordPress/WordPress repository.
**Review these differences carefully for any unexpected results.**
From 82d2d648e90a79defb4a42f864641320d13a1387 Mon Sep 17 00:00:00 2001
From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com>
Date: Wed, 18 Mar 2026 13:52:45 -0400
Subject: [PATCH 4/5] Include adjustments from testing branch.
---
.github/workflows/pull-request-comments.yml | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/pull-request-comments.yml b/.github/workflows/pull-request-comments.yml
index 70ef650b001e8..ec657bd310f25 100644
--- a/.github/workflows/pull-request-comments.yml
+++ b/.github/workflows/pull-request-comments.yml
@@ -93,6 +93,8 @@ jobs:
steps:
- name: Download artifact
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
+ env:
+ RUN_ID: ${{ github.event.workflow_run.id }}
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts( {
@@ -119,8 +121,6 @@ jobs:
const fs = require( 'fs' );
fs.writeFileSync( '${{github.workspace}}/pr-number.zip', Buffer.from( download.data ) )
- env:
- RUN_ID: ${{ github.event.workflow_run.id }}
- name: Unzip the artifact containing the PR number
run: unzip pr-number.zip
@@ -231,9 +231,6 @@ jobs:
- name: Leave a comment with any differences noticed
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
- env:
- RUN_ID:
- ${{ github.event.workflow_run.id }}
with:
script: |
const fs = require( 'fs' );
@@ -316,7 +313,7 @@ jobs:
`;
}
- commentInfo.body += `[Download the complete .diff file from the workflow run](https://github.com/${ context.repo.owner }/${ context.repo.repo }/actions/runs/${ process.env.RUN_ID }).`;
+ commentInfo.body += `\n\n[Download the complete .diff file from the workflow run](https://github.com/${ context.repo.owner }/${ context.repo.repo }/actions/runs/${ context.payload.workflow_run.id }).`;
}
if ( commentInfo.comment_id ) {
From 6b5a3276ad28f7b437755f41b2456f9065557a71 Mon Sep 17 00:00:00 2001
From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com>
Date: Wed, 18 Mar 2026 14:06:48 -0400
Subject: [PATCH 5/5] Add contextual links in the comment.
---
.github/workflows/pull-request-comments.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/pull-request-comments.yml b/.github/workflows/pull-request-comments.yml
index ec657bd310f25..b8c9593cdce28 100644
--- a/.github/workflows/pull-request-comments.yml
+++ b/.github/workflows/pull-request-comments.yml
@@ -313,6 +313,8 @@ jobs:
`;
}
+ const sha = context.payload.workflow_run.head_sha;
+ commentInfo.body += `\n\n_Comment updated using [${ sha.slice( 0, 7 ) }](https://github.com/${ context.repo.owner }/${ context.repo.repo }/commit/${ sha })._ ([commenting workflow run](https://github.com/${ context.repo.owner }/${ context.repo.repo }/actions/runs/${ context.runId })).`;
commentInfo.body += `\n\n[Download the complete .diff file from the workflow run](https://github.com/${ context.repo.owner }/${ context.repo.repo }/actions/runs/${ context.payload.workflow_run.id }).`;
}