Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WordPress build] Only build the latest patch version of WordPress #1955

Merged
15 changes: 9 additions & 6 deletions .github/workflows/refresh-wordpress-major-and-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ on:
- cron: '*/20 * * * *'

jobs:
build_and_deploy:
# Only run this workflow from the trunk branch and when it's triggered by dmsnell OR adamziel
build_wordpress_major_and_beta_push_to_github_and_deploy_website:
# Only run this workflow from the trunk branch and when it's triggered by a maintainer listed below
if: >
github.ref == 'refs/heads/trunk' && (
github.actor == 'adamziel' ||
Expand All @@ -39,22 +39,25 @@ jobs:
curl -fsSL https://bun.sh/install | bash
- uses: ./.github/actions/prepare-playground
- name: 'Recompile WordPress'
id: build
shell: bash
env:
FORCE_REBUILD: ${{ github.event.inputs.force_rebuild }}
run: PATH="${PATH}:${HOME}/.bun/bin" npx nx bundle-wordpress:major-and-beta playground-wordpress-builds
- name: Check for uncommitted changes
# Prevent commit if the build failed to avoid polluting the commit history
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
if: steps.build.outcome == 'success'
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
id: changes
run: |
if [ -z "$(git status --porcelain)" ]; then
echo "No changes"
echo 'CHANGES=0' >> $GITHUB_OUTPUT
echo 'COMMIT_CHANGES=0' >> $GITHUB_OUTPUT
else
echo "Changes detected"
echo 'CHANGES=1' >> $GITHUB_OUTPUT
echo 'COMMIT_CHANGES=1' >> $GITHUB_OUTPUT
fi
- name: Push rebuilt WordPress to GitHub
if: steps.changes.outputs.CHANGES == '1'
if: steps.changes.outputs.COMMIT_CHANGES == '1'
run: |
git config --global user.name "deployment_bot"
git config --global user.email "deployment_bot@users.noreply.github.com"
Expand All @@ -67,7 +70,7 @@ jobs:
git push origin HEAD:trunk
fi;
- name: Deploy website
if: steps.changes.outputs.CHANGES == '1'
if: steps.changes.outputs.COMMIT_CHANGES == '1'
uses: benc-uk/workflow-dispatch@v1
with:
workflow: build-website.yml
Expand Down
72 changes: 56 additions & 16 deletions packages/playground/wordpress-builds/build/build.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import path, { join } from 'path';
import { spawn } from 'child_process';
import yargs from 'yargs';
import { promises as fs, statSync } from 'fs';
import semver from 'semver';

const parser = yargs(process.argv.slice(2))
.usage('Usage: $0 [options]')
Expand All @@ -25,27 +25,57 @@ const parser = yargs(process.argv.slice(2))
},
force: {
type: 'boolean',
description: 'Force rebuild even if the version is already downloaded',
description:
'Force rebuild even if the version is already downloaded',
default: process.env.FORCE_REBUILD === 'true',
},
});

const args = parser.argv;

let latestVersions = await fetch('https://api.wordpress.org/core/version-check/1.7/?channel=beta')
.then((res) => res.json())
let wpVersions = await fetch(
'https://api.wordpress.org/core/version-check/1.7/?channel=beta'
).then((res) => res.json());

latestVersions = latestVersions
.offers
.filter((v) => v.response === 'autoupdate')
wpVersions = wpVersions.offers.filter((v) => v.response === 'autoupdate');

let beta = null;
if (latestVersions[0].current.includes('beta') || latestVersions[0].current.toLowerCase().includes('rc')) {
beta = latestVersions[0];
latestVersions = latestVersions.slice(1);
if (
wpVersions[0].current.includes('beta') ||
wpVersions[0].current.toLowerCase().includes('rc')
) {
beta = wpVersions[0];
wpVersions = wpVersions.slice(1);
}

function toVersionInfo(apiVersion, slug=null) {
/**
* Create a list of the latest patch versions for each major.minor version.
*
* Sometimes the API may include multiple patch versions for the same major.minor version.
* Playground builds only the latest patch version.
*/
const latestVersions = wpVersions.reduce((versionAccumulator, wpVersion) => {
const [major, minor] = wpVersion.version.split('.');
const majorMinor = `${major}.${minor}`;

const existingVersion = versionAccumulator.find((v) =>
v.version.startsWith(majorMinor)
);
if (
!existingVersion ||
semver.gt(wpVersion.version, existingVersion.version)
) {
return [
...versionAccumulator.filter(
(v) => !v.version.startsWith(majorMinor)
),
wpVersion,
];
}
return versionAccumulator;
}, []);

function toVersionInfo(apiVersion, slug = null) {
if (!apiVersion) {
return {};
}
Expand All @@ -61,7 +91,11 @@ let versionInfo = {};
if (args.wpVersion === 'nightly') {
versionInfo.url =
'https://wordpress.org/nightly-builds/wordpress-latest.zip';
versionInfo.version = 'nightly';
/**
* Nightly versions don't have a version number, so we use the date instead.
* This allows us to determine if the nightly version was already built.
*/
versionInfo.version = `nightly-${new Date().toISOString().split('T')[0]}`;
versionInfo.majorVersion = 'nightly';
versionInfo.slug = 'nightly';
} else if (args.wpVersion === 'beta') {
Expand All @@ -75,11 +109,13 @@ if (args.wpVersion === 'nightly') {
}[args.wpVersion];
versionInfo = toVersionInfo(relevantApiVersion);
} else if (args.wpVersion.match(/\d\.\d/)) {
const relevantApiVersion = latestVersions.find((v) => v.version.startsWith(args.wpVersion));
const relevantApiVersion = latestVersions.find((v) =>
v.version.startsWith(args.wpVersion)
);
versionInfo = toVersionInfo(relevantApiVersion);
}

if(!versionInfo.url) {
if (!versionInfo.url) {
process.stdout.write(`WP version ${args.wpVersion} is not supported\n`);
process.stdout.write(await parser.getHelp());
process.exit(1);
Expand All @@ -101,7 +137,11 @@ try {
versions = {};
}

if (!args.force && versionInfo.slug !== 'nightly' && versions[versionInfo.slug] === versionInfo.version) {
if (
!args.force &&
versionInfo.slug !== 'nightly' &&
versions[versionInfo.slug] === versionInfo.version
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this issue. If we want to prevent ni0ghtly rebuilds from rerunning, we could store the nightly version as nighty-YEAR-MONTH-DATE instead nightly. This would prevent a rebuild if a nightly version was already built.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could have the logged nightly version track the latest commit on WP trunk or something similar and only rebuild if that has changed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would we pull this data from? In GitHub WordPress just keeps pushing commits through the day.

Are there any disadvantages to using a date?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I should've voiced my thoughts about the date suggestion. Sorry about that. It looks like we run nightly once a day at the 9th hour, so avoiding rebuilds within the same day didn't seem helpful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! It sounds like the current nightly implementation is ok as is.

) {
process.stdout.write(
`The requested version was ${args.wpVersion}, but its latest release (${versionInfo.version}) is already downloaded\n`
);
Expand All @@ -124,7 +164,7 @@ try {
'../../cli/src/cli.ts',
'run-blueprint',
`--wp=${versionInfo.url}`,
`--mount-before-install=${wordpressDir}:/wordpress`
`--mount-before-install=${wordpressDir}:/wordpress`,
],
{ cwd: sourceDir, stdio: 'inherit' }
);
Expand Down
Loading