Skip to content
Open
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
19 changes: 15 additions & 4 deletions .github/workflows/check-built-files.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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**'

Expand All @@ -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' }}
152 changes: 148 additions & 4 deletions .github/workflows/pull-request-comments.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -79,18 +80,21 @@ 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
pull-requests: write
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
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( {
Expand All @@ -117,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
Expand Down Expand Up @@ -180,6 +182,148 @@ 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 Server Comparison' ) ) {
commentInfo.comment_id = currentComment.id;
break;
}
};

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.

**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 += `<details>
<summary>Click to expand (truncated)</summary>

\`\`\`diff
${ truncated }
\`\`\`

⚠️ The diff was too large to display in full.

</details>`;
} else {
commentInfo.body += `<details>
<summary>Click to expand</summary>

\`\`\`diff
${ diffContents }
\`\`\`

</details>`;
}

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 }).`;
}

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
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/reusable-check-built-files.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
##
# 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:

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.
Expand All @@ -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:
Expand Down
110 changes: 110 additions & 0 deletions .github/workflows/reusable-compare-built-files-v1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
##
# 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'
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

- 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/
Loading