Skip to content

Commit

Permalink
Build/Test Tools: Parallelise the performance tests.
Browse files Browse the repository at this point in the history
This change introduces a job matrix for the "current", "before", and "base" performance tests to replace the current behaviour of running them sequentially in a single job. This speeds up the overall performance testing workflow and also reduces the chance of any given test interfering with another, for example by making a change to data in the database that affects a subsequent test.

Props johnbillion, swissspidy, dmsnell, joemcgill.

See #62221

git-svn-id: https://develop.svn.wordpress.org/trunk@59749 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
johnbillion committed Feb 1, 2025
1 parent bb07250 commit 1111166
Show file tree
Hide file tree
Showing 3 changed files with 449 additions and 3 deletions.
68 changes: 65 additions & 3 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ on:
# Confirm any changes to relevant workflow files.
- '.github/workflows/performance.yml'
- '.github/workflows/reusable-performance.yml'
- '.github/workflows/reusable-performance-*.yml'
workflow_dispatch:

# Cancels all previous workflow runs for pull requests that have not completed.
Expand All @@ -47,21 +48,82 @@ concurrency:
permissions: {}

jobs:
determine-matrix:
name: Determine Matrix
runs-on: ubuntu-24.04
if: ${{ ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) && ! contains( github.event.before, '00000000' ) }}
permissions: {}
env:
TARGET_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
outputs:
subjects: ${{ steps.set-subjects.outputs.result }}
target_sha: ${{ env.TARGET_SHA }}
steps:
# The `workflow_dispatch` event is the only one missing the needed SHA to target.
- name: Retrieve previous commit SHA (if necessary)
if: ${{ github.event_name == 'workflow_dispatch' }}
run: echo "TARGET_SHA=$(git rev-parse HEAD^1)" >> "$GITHUB_ENV"

- name: Set subjects
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: set-subjects
with:
script: |
const artifacts = await github.rest.actions.listArtifactsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'wordpress-build-' + process.env.TARGET_SHA,
});
const has_previous_build = !! artifacts.data.artifacts[0];
const subjects = [
'current',
];
if ( context.eventName === 'push' && context.ref === 'refs/heads/trunk' ) {
subjects.push( 'base' );
} else if ( has_previous_build ) {
subjects.push( 'before' );
}
return subjects;
# Runs the performance test suite.
performance:
name: ${{ matrix.multisite && 'Multisite' || 'Single site' }}
uses: ./.github/workflows/reusable-performance.yml
name: ${{ matrix.multisite && 'Multisite' || 'Single Site' }} ${{ matrix.memcached && 'Memcached' || 'Default' }}
uses: ./.github/workflows/reusable-performance-test-v2.yml
needs: [ determine-matrix ]
permissions:
contents: read
strategy:
fail-fast: false
matrix:
memcached: [ true, false ]
multisite: [ true, false ]
subject: ${{ fromJson( needs.determine-matrix.outputs.subjects ) }}
with:
memcached: ${{ matrix.memcached }}
multisite: ${{ matrix.multisite }}
subject: ${{ matrix.subject }}
TARGET_SHA: ${{ needs.determine-matrix.outputs.target_sha }}

compare:
name: ${{ matrix.label }}
uses: ./.github/workflows/reusable-performance-report-v2.yml
needs: [ determine-matrix, performance ]
permissions:
contents: read
if: ${{ ( github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' ) }}
strategy:
fail-fast: false
matrix:
memcached: [ true, false ]
multisite: [ true, false ]
label: [ Compare ]
with:
memcached: ${{ matrix.memcached }}
multisite: ${{ matrix.multisite }}
BASE_TAG: ${{ needs.performance.outputs.BASE_TAG }}
publish: ${{ contains( fromJson( needs.determine-matrix.outputs.subjects ), 'base' ) && ! matrix.memcached && ! matrix.multisite }}
secrets:
CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }}

Expand Down
114 changes: 114 additions & 0 deletions .github/workflows/reusable-performance-report-v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
##
# A reusable workflow that compares and publishes the performance tests.
##
name: Compare and publish performance Tests

on:
workflow_call:
inputs:
BASE_TAG:
description: 'The version being used for baseline measurements.'
required: true
type: string
memcached:
description: 'Whether to enable memcached.'
required: false
type: boolean
default: false
multisite:
description: 'Whether to use Multisite.'
required: false
type: boolean
default: false
publish:
description: 'Whether to publish the results to Code Vitals.'
required: false
type: boolean
default: false
secrets:
CODEVITALS_PROJECT_TOKEN:
description: 'The authorization token for https://www.codevitals.run/project/wordpress.'
required: false

env:
BASE_TAG: ${{ inputs.BASE_TAG }}

# Disable permissions for all available scopes by default.
# Any needed permissions should be configured at the job level.
permissions: {}

jobs:
# Performs the following steps:
# - Checkout repository.
# - Set up Node.js.
# - Download the relevant performance test artifacts.
# - List the downloaded files for debugging.
# - Compare results.
# - Add workflow summary.
# - Determine the sha of the baseline tag if necessary.
# - Publish performance results if necessary.
compare:
name: ${{ inputs.multisite && 'Multisite' || 'Single Site' }} ${{ inputs.memcached && 'Memcached' || 'Default' }} ${{ inputs.publish && '(Publishes)' || '' }}
runs-on: ubuntu-24.04
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
fetch-depth: ${{ github.event_name == 'workflow_dispatch' && '2' || '1' }}
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version-file: '.nvmrc'
cache: npm

- name: Download artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
pattern: performance-${{ inputs.multisite && 'multisite' || 'single' }}-${{ inputs.memcached && 'memcached' || 'default' }}-*
path: artifacts
merge-multiple: true

- name: List files
run: tree artifacts

- name: Compare results
run: node ./tests/performance/compare-results.js "${RUNNER_TEMP}/summary.md"

- name: Add workflow summary
run: cat "${RUNNER_TEMP}/summary.md" >> "$GITHUB_STEP_SUMMARY"

- name: Set the base sha
# Only needed when publishing results.
if: ${{ inputs.publish }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: base-sha
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const baseRef = await github.rest.git.getRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'tags/' + process.env.BASE_TAG,
});
return baseRef.data.object.sha;
- name: Publish performance results
if: ${{ inputs.publish }}
env:
BASE_SHA: ${{ steps.base-sha.outputs.result }}
CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }}
HOST_NAME: www.codevitals.run
run: |
if [ -z "$CODEVITALS_PROJECT_TOKEN" ]; then
echo "Performance results could not be published. 'CODEVITALS_PROJECT_TOKEN' is not set"
exit 1
fi
COMMITTED_AT="$(git show -s "$GITHUB_SHA" --format='%cI')"
node ./tests/performance/log-results.js "$CODEVITALS_PROJECT_TOKEN" trunk "$GITHUB_SHA" "$BASE_SHA" "$COMMITTED_AT" "$HOST_NAME"
Loading

0 comments on commit 1111166

Please sign in to comment.