Skip to content

Commit 974ef75

Browse files
committed
Add workflow to compare PR with the build server.
1 parent 23df713 commit 974ef75

4 files changed

Lines changed: 272 additions & 10 deletions

File tree

.github/workflows/check-built-files.yml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Checks for uncommitted changes to built files in pull requests.
1+
# Checks for uncommitted or unexpected changes to built files within pull requests.
22
name: Check Built Files (PRs)
33

44
on:
@@ -23,11 +23,13 @@ on:
2323
- '.nvmrc'
2424
- 'Gruntfile.js'
2525
- 'webpack.config.js'
26-
- 'tools/webpack/**'
26+
- 'tools/**'
2727
# These files configure Composer. Changes could affect the outcome.
2828
- 'composer.*'
2929
# Confirm any changes to relevant workflow files.
3030
- '.github/workflows/check-built-files.yml'
31+
- '.github/workflows/reusable-check-built-files.yml'
32+
- '.github/workflows/reusable-compare-built-files-*.yml'
3133
# Changes to the default themes should be handled by the themes workflows.
3234
- '!src/wp-content/themes/twenty**'
3335

@@ -43,9 +45,18 @@ concurrency:
4345
permissions: {}
4446

4547
jobs:
48+
# Checks built files for uncommitted changes.
4649
check-for-built-file-changes:
47-
name: Check built files
48-
if: ${{ github.repository == 'wordpress/wordpress-develop' }}
50+
name: Check for uncommitted changes
51+
if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
4952
uses: ./.github/workflows/reusable-check-built-files.yml
5053
permissions:
5154
contents: read
55+
56+
# Compares the build directory with the WordPress/WordPress repository.
57+
compare-with-build-server:
58+
name: Compare built files to WordPress/WordPress
59+
uses: ./.github/workflows/reusable-compare-built-files-v1.yml
60+
permissions:
61+
contents: read
62+
if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}

.github/workflows/pull-request-comments.yml

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
pull_request_target:
66
types: [ 'opened', 'synchronize', 'reopened', 'edited' ]
77
workflow_run:
8-
workflows: [ 'Test Build Processes' ]
8+
workflows: [ 'Check Built Files (PRs)', 'Test Build Processes' ]
99
types:
1010
- completed
1111

@@ -22,6 +22,7 @@ permissions: {}
2222
jobs:
2323
# Comments on a pull request when the author is a first time contributor.
2424
post-welcome-message:
25+
name: Contributor welcome message
2526
runs-on: ubuntu-24.04
2627
permissions:
2728
issues: write
@@ -79,14 +80,15 @@ jobs:
7980
8081
# Leaves a comment on a pull request with a link to test the changes in a WordPress Playground instance.
8182
playground-details:
82-
name: Comment on a pull request with Playground details
83+
name: Leave Playground testing details
8384
runs-on: ubuntu-24.04
8485
permissions:
8586
issues: write
8687
pull-requests: write
8788
if: >
8889
github.repository == 'WordPress/wordpress-develop' &&
8990
github.event.workflow_run.event == 'pull_request' &&
91+
github.event.workflow_run.name == 'Test Build Processes' &&
9092
github.event.workflow_run.conclusion == 'success'
9193
steps:
9294
- name: Download artifact
@@ -180,6 +182,146 @@ jobs:
180182
181183
github.rest.issues.createComment( commentInfo );
182184
185+
# Leaves a comment on a pull request noting differences between the PR and the build server.
186+
build-server-comparison:
187+
name: Note differences with the build server
188+
runs-on: ubuntu-24.04
189+
permissions:
190+
issues: write
191+
pull-requests: write
192+
if: >
193+
github.repository == 'WordPress/wordpress-develop' &&
194+
github.event.workflow_run.event == 'pull_request' &&
195+
github.event.workflow_run.name == 'Check Built Files (PRs)' &&
196+
github.event.workflow_run.conclusion == 'success'
197+
steps:
198+
- name: Download artifact
199+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
200+
env:
201+
RUN_ID: ${{ github.event.workflow_run.id }}
202+
with:
203+
script: |
204+
const artifacts = await github.rest.actions.listWorkflowRunArtifacts( {
205+
owner: context.repo.owner,
206+
repo: context.repo.repo,
207+
run_id: process.env.RUN_ID,
208+
} );
209+
210+
const matchArtifact = artifacts.data.artifacts.filter( ( artifact ) => {
211+
return artifact.name === 'build-server-comparison'
212+
} )[0];
213+
214+
if ( ! matchArtifact ) {
215+
core.setFailed( 'No artifact found!' );
216+
return;
217+
}
218+
219+
const download = await github.rest.actions.downloadArtifact( {
220+
owner: context.repo.owner,
221+
repo: context.repo.repo,
222+
artifact_id: matchArtifact.id,
223+
archive_format: 'zip',
224+
} );
225+
226+
const fs = require( 'fs' );
227+
fs.writeFileSync( '${{github.workspace}}/build-server-comparison.zip', Buffer.from( download.data ) )
228+
229+
- name: Unzip the artifact containing the comparison info
230+
run: unzip build-server-comparison.zip
231+
232+
- name: Leave a comment with any differences noticed
233+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
234+
with:
235+
script: |
236+
const fs = require( 'fs' );
237+
const issue_number = Number( fs.readFileSync( './NR' ) );
238+
const fileChanges = fs.readFileSync( './file-changes.txt', 'utf8' );
239+
const diffContents = fs.readFileSync( './changes.diff', 'utf8' );
240+
const MAX_DIFF_LENGTH = 50000; // GitHub has a 65,536 character limit for comments.
241+
242+
core.info( `Checking pull request #${issue_number}.` );
243+
244+
// Confirm that the pull request is still open before leaving a comment.
245+
const pr = await github.rest.pulls.get({
246+
owner: context.repo.owner,
247+
repo: context.repo.repo,
248+
pull_number: issue_number,
249+
});
250+
251+
if ( pr.data.state !== 'open' ) {
252+
core.info( 'The pull request has been closed. No comment will be left.' );
253+
return;
254+
}
255+
256+
// Comments are only added after the first successful build. Check for the presence of a comment and bail early.
257+
const commentInfo = {
258+
owner: context.repo.owner,
259+
repo: context.repo.repo,
260+
issue_number,
261+
};
262+
263+
const comments = ( await github.rest.issues.listComments( commentInfo ) ).data;
264+
265+
for ( const currentComment of comments ) {
266+
if ( currentComment.user.type === 'Bot' && currentComment.body.includes( 'Build Script Results Comparison' ) ) {
267+
commentInfo.comment_id = currentComment.id;
268+
break;
269+
}
270+
};
271+
272+
commentInfo.body = '## Build Server Comparison';
273+
274+
// Post or update the comment.
275+
if ( fileChanges.trim() === '' ) {
276+
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.';
277+
} else {
278+
commentInfo.body += 'The contents of the `build` directory after running `npm run build` has been compared with the contents of the WordPress/WordPress repository.
279+
280+
**Review these differences carefully for any unexpected results.**
281+
282+
### List of Modified Files
283+
284+
\`\`\`
285+
${ fileChanges }
286+
\`\`\`
287+
288+
### Full Diff File
289+
`;
290+
291+
if ( diffContents.length > MAX_DIFF_LENGTH ) {
292+
const cutoff = diffContents.lastIndexOf( '\n', MAX_DIFF_LENGTH );
293+
const truncated = diffContents.substring( 0, cutoff );
294+
295+
commentInfo.body += `<details>
296+
<summary>Click to expand (truncated)</summary>
297+
298+
\`\`\`diff
299+
${ truncated }
300+
\`\`\`
301+
302+
⚠️ The diff was too large to display in full.
303+
304+
</details>`;
305+
} else {
306+
commentInfo.body += `<details>
307+
<summary>Click to expand</summary>
308+
309+
\`\`\`diff
310+
${ diffContents }
311+
\`\`\`
312+
313+
</details>`;
314+
}
315+
316+
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 }).`;
317+
}
318+
319+
if ( commentInfo.comment_id ) {
320+
github.rest.issues.updateComment( commentInfo );
321+
} else {
322+
github.rest.issues.createComment( commentInfo );
323+
}
324+
183325
# Manages comments reminding contributors to include a Trac ticket link when opening a pull request.
184326
trac-ticket-check:
185327
name: Manage Trac ticket reminders for pull requests

.github/workflows/reusable-check-built-files.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
##
22
# A reusable workflow that checks for uncommitted changes to built files in pull requests.
33
##
4-
name: Check Built Files (PRs)
4+
name: Check for Changes to Versioned Files (reusable)
55

66
on:
77
workflow_call:
88

99
permissions: {}
1010

1111
jobs:
12-
# Checks a PR for uncommitted changes to built files.
12+
# Checks a PR for uncommitted changes to versioned files.
1313
#
1414
# When changes are detected, the patch is stored as an artifact for processing by the Commit Built File Changes
1515
# workflow.
@@ -29,8 +29,8 @@ jobs:
2929
# - Displays the result of git diff for debugging purposes.
3030
# - Saves the diff to a patch file.
3131
# - Uploads the patch file as an artifact.
32-
update-built-files:
33-
name: Check and update built files
32+
check-versioned-files:
33+
name: Check for changes
3434
runs-on: ubuntu-24.04
3535
timeout-minutes: 10
3636
permissions:
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
##
2+
# A reusable workflow that compares the results of the build script with the most recent commit to WordPress/WordPress.
3+
##
4+
name: Compare Built Files (reusable)
5+
6+
on:
7+
workflow_call:
8+
9+
# Disable permissions for all available scopes by default.
10+
# Any needed permissions should be configured at the job level.
11+
permissions: {}
12+
13+
jobs:
14+
# Runs the PHP coding standards checks.
15+
#
16+
# Violations are reported inline with annotations.
17+
#
18+
# Performs the following steps:
19+
# - Checks out the repository.
20+
# - Sets up Node.js.
21+
# - Sets up PHP.
22+
# - Installs Composer dependencies.
23+
# - Logs debug information about the GitHub Action runner.
24+
# - Installs npm dependencies.
25+
# - Builds WordPress to run from the build directory.
26+
# - Ensures version-controlled files are not modified or deleted.
27+
# - Checks out the WordPress/WordPress repository.
28+
# - Creates a directory for text files to be uploaded as an artifact.
29+
# - Stores a list of files that differ in the build directory from WordPress/WordPress.
30+
# - Stores a diff file comparing the build directory to WordPress/WordPress.
31+
# - Saves the pull request number to a text file.
32+
# - Uploads the generated files as an artifact.
33+
compare-built-files:
34+
name: Compare built files to WordPress/WordPress
35+
runs-on: ubuntu-24.04
36+
permissions:
37+
contents: read
38+
timeout-minutes: 10
39+
40+
steps:
41+
- name: Checkout repository
42+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
43+
with:
44+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
45+
persist-credentials: false
46+
47+
- name: Set up Node.js
48+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
49+
with:
50+
node-version-file: '.nvmrc'
51+
cache: npm
52+
53+
- name: Set up PHP
54+
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
55+
with:
56+
php-version: '8.4'
57+
coverage: none
58+
59+
# Since Composer dependencies are installed using `composer update` and no lock file is in version control,
60+
# passing a custom cache suffix ensures that the cache is flushed at least once per week.
61+
- name: Install Composer dependencies
62+
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # v4.0.0
63+
with:
64+
custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F")
65+
66+
- name: Log debug information
67+
run: |
68+
npm --version
69+
node --version
70+
git --version
71+
72+
- name: Install npm Dependencies
73+
run: npm ci
74+
75+
- name: Build WordPress to run from build directory
76+
run: npm run build
77+
78+
- name: Ensure version-controlled files are not modified or deleted
79+
run: git diff --exit-code
80+
81+
- name: Checkout WordPress/WordPress
82+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
83+
with:
84+
repository: 'WordPress/WordPress'
85+
path: ${{ github.workspace }}/build-server
86+
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
87+
persist-credentials: false
88+
89+
- name: Create directory for artifacts
90+
run: mkdir artifacts
91+
92+
- name: Create a list of files that have changed
93+
run: diff -rq ${{ github.workspace }}/build ${{ github.workspace }}/build-server | sed "s|${{ github.workspace }}/||g" > artifacts/file-changes.txt
94+
95+
- name: Create a list of files that have changed
96+
run: diff -r ${{ github.workspace }}/build ${{ github.workspace }}/build-server | sed "s|${{ github.workspace }}/||g" > artifacts/changes.diff
97+
98+
- name: Save PR number
99+
run: echo "${EVENT_NUMBER}" > ./artifacts/NR
100+
env:
101+
EVENT_NUMBER: ${{ github.event.number }}
102+
103+
# Uploads the associated text files as an artifact.
104+
- name: Upload comparison results as an artifact
105+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
106+
if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name == 'pull_request' }}
107+
with:
108+
name: build-server-comparison
109+
path: artifacts/

0 commit comments

Comments
 (0)