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

Conversation

bgrgicak
Copy link
Collaborator

@bgrgicak bgrgicak commented Oct 29, 2024

This PR ensures we always build the latest patch version of each minor WordPress version when running the WordPress build.

Playground supports only the latest patch version of each minor WordPress release (e.g. 6.6, 6.5).
But before this PR, the WordPress build script could include multiple patch versions of WordPress, such as 6.6.2 and 6.6.1.

When this happens the latest version would correctly be the latest minor version (6.6) and point to the latest patch (6.6.2), but the minus one minor version would be the older patch of the latest minor version (6.6.1) instead of the previous minor version (6.5).

This means that a build script like npx nx bundle-wordpress:major-and-beta playground-wordpress-builds would correctly build the latest minor version (6.6) with the code from the latest patch (6.6.2).
After that, instead of building the older minor version (6.5) it would rebuild the latest minor version (6.6) with the code from an older patch (6.6.1).

As a consequence, our git history would be polluted by commits every time this Refresh WordPress Major&Beta workflow runs.

To address this we filter the list of latest versions to include only the latest patch for each minor version. Older patches are excluded from the list.

This PR also prevents the Refresh WordPress Major&Beta workflow from committing changes when the build fails.

Testing Instructions (or ideally a Blueprint)

  • Run npx nx bundle-wordpress:major-and-beta playground-wordpress-builds and confirm there were no changes

@bgrgicak bgrgicak self-assigned this Oct 29, 2024
@bgrgicak bgrgicak force-pushed the fix/refresh-wordpress-to-prevent-commits-on-error branch from 64e9cff to 6ea3c75 Compare October 29, 2024 09:53
@bgrgicak bgrgicak changed the title [CI] Prevent Refresh WordPress Major&Beta workflow from commiting changes when build failed [CI] Prevent Refresh WordPress Major&Beta workflow from committing changes when build failed Oct 29, 2024
@bgrgicak bgrgicak marked this pull request as ready for review October 29, 2024 10:10
@bgrgicak bgrgicak requested a review from a team October 29, 2024 10:10
Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

@bgrgicak, these changes look good to me except that it seems failing build attempts will now be logged as successes. Is that right?

@brandonpayton
Copy link
Member

On further thought, was a failing build really the problem? These three builds all detected changes that needed to be committed, but AFAICT, nothing failed in the build:

It seems like we need to figure out why repeated builds are yielding different results.

@bgrgicak
Copy link
Collaborator Author

it seems failing build attempts will now be logged as successes. Is that right?

That wasn't my intention, I can exit with the same code like Bun to ensure this job fails.

It seems like we need to figure out why repeated builds are yielding different results.

Good question, I'm taking a look at it now.

@bgrgicak
Copy link
Collaborator Author

I ran three builds and pushed them here.
After the first build, the second two builds only have tiny changes. I'm checking now what's different.

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Oct 29, 2024

This is tricky. By default, ZIPs aren't deterministic because they contain metadata like time created.

This article suggests we can make ZIPs deterministic, so I'm trying that now.

Two static asset zips generated from the same data.
Screenshot 2024-10-29 at 15 46 48

@bgrgicak bgrgicak marked this pull request as draft October 29, 2024 15:32
@bgrgicak
Copy link
Collaborator Author

After following this article, ZIP generation is deterministic (implementation isn't final).

But even with that, the wp-version.zip file is still different between builds.

I'm going to take a look at the wp-version.zip files tomorrow and keep searching for the difference.

See all build attempts here https://github.com/WordPress/wordpress-playground/pull/1959/commits

- name: Check for uncommitted changes
# Prevent commit if the build failed to avoid polluting the commit history
if: steps.changes.outputs.BUILD_FAILED == '0'
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this check correct, given that changes is the ID of this step?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, could this use the step outcome GitHub already exposes instead of introducing an additional variable?

actions/toolkit#1034 (comment)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks! Using outcome is better 117725b.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder why did it work in the test runs if the condition was off

Copy link
Collaborator Author

@bgrgicak bgrgicak Oct 30, 2024

Choose a reason for hiding this comment

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

Interesting. You must have an id to set a output value.

If there is no id the variable doesn't exist, but the condition if: steps.changes.outputs.BUILD_FAILED == '0' will be true.

You can see how this example action runs in a test.

The lesson for me is. If you evaluate strings use something that isn't 0 or 1 as the string.

@bgrgicak
Copy link
Collaborator Author

We need to ensure there are no commits if no meaningful changes are made during a build.
@adamziel @brandonpayton how would you approach this?

One approach is to build and compare like we do.
Another is to check if the built version matches what we want to build by comparing something like version numbers.

Switch to comparing versions

I would like to explore this next.

Keep comparing builds

I don't like this approach in general as it's dirty and the only reason we do it is to keep CI working not because Playground actually needs it.

If we want to keep comparing builds I have a way to make ZIPs deterministic, but not SQLite.

For SQLite, I was thinking of shipping an empty database and letting WP populate it on boot, but that would slow down the boot.

Different SQLite and ZIP files between builds

The difference between builds is coming from SQLite files and ZIP generation.
Full research summary and test runs are here #1959

WordPress produces different database content on every build, like timestamps, and password hashes. As a result, each SQLite file will be different.

Each build will create files with newly created dates, so the ZIP content will be different. We can work around this by rewriting the time created to be the same for each build.

ZIP files aren't deterministic because they contain metadata that can be different between builds. This can be avoided by not including metadata in the build.

@adamziel
Copy link
Collaborator

@bgrgicak one idea would be to store the versions of all the dependencies in the build directory, e.g. in versions.json. It would be conceptually similar to "package-lock.json" and "composer-lock.json" and could look like this:

{
	// Hash of the WordPress release downloaded from w.org
	// Hashes could be easier to compute than the specific version numbers. 
	"wordpress": "af9827986bc640a5d05f3",
	// Hash of the used SQLite database integration plugin
	"sqlite-database-integration": "d82968317730d0a67b485ae4f934463b
}

With that in place, we'd only check if that one file changed. What do you think?

@brandonpayton
Copy link
Member

brandonpayton commented Oct 30, 2024

Switch to comparing versions

@bgrgicak, I didn't know this until a couple of weeks ago, but our minified-WP build process actually pre-installs WordPress, and sometimes we need to rebuild existing versions due to WordPress install changes.

Here is an example:
#1832

So I think we'll need something more than a version compare.

@adamziel
Copy link
Collaborator

Good note about picking up the changes in how Playground preinstalls WordPress! I'd say we can track that separately. The immediate pain point is not having automatic beta/RC rebuilds to work and version compare would solve that.

@brandonpayton
Copy link
Member

brandonpayton commented Oct 30, 2024

Good note about picking up the changes in how Playground preinstalls WordPress! I'd say we can track that separately. The immediate pain point is not having automatic beta/RC rebuilds to work and version compare would solve that.

Good point. We could also add a build flag to ignore version compares and commit all changes.

if (!args.force && versionInfo.slug !== 'nightly' && versions[versionInfo.slug] === versionInfo.version) {
if (
!args.force &&
versionInfo.slug !== 'nightly' &&
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.

@bgrgicak bgrgicak changed the title [CI] Prevent Refresh WordPress Major&Beta workflow from committing changes when build failed [CI] Prevent Refresh WordPress Major&Beta workflow from rebuilding an existing WP version Oct 31, 2024
@bgrgicak bgrgicak changed the title [CI] Prevent Refresh WordPress Major&Beta workflow from rebuilding an existing WP version [WordPress build] Always build the latest patch version of WordPress Oct 31, 2024
@bgrgicak bgrgicak changed the title [WordPress build] Always build the latest patch version of WordPress [WordPress build] Only build the latest patch version of WordPress Oct 31, 2024
@bgrgicak bgrgicak marked this pull request as ready for review October 31, 2024 07:57
@bgrgicak
Copy link
Collaborator Author

Thanks for sharing your thoughts @brandonpayton and @adamziel!

I have a working fix that will ensure we only build the latest patch. This will prevent rebuilds of the same version when we run it multiple times.

Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

Thank you for taking care of this. 🙇

I left a few comments including one that mentions a possible bug.

.github/workflows/refresh-wordpress-major-and-beta.yml Outdated Show resolved Hide resolved
packages/playground/wordpress-builds/build/build.js Outdated Show resolved Hide resolved
if (!args.force && versionInfo.slug !== 'nightly' && versions[versionInfo.slug] === versionInfo.version) {
if (
!args.force &&
versionInfo.slug !== 'nightly' &&
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.

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 1, 2024

Thanks @brandonpayton! I addressed the bug and left a comment for nightly.

Copy link
Member

@brandonpayton brandonpayton left a comment

Choose a reason for hiding this comment

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

This looks good. Let's merge and keep an eye on it.

@brandonpayton brandonpayton merged commit 79c65d6 into trunk Nov 1, 2024
10 checks passed
@brandonpayton brandonpayton deleted the fix/refresh-wordpress-to-prevent-commits-on-error branch November 1, 2024 14:45
@brandonpayton
Copy link
Member

I reenabled the workflow and triggered it manually to see how it goes after merge:
https://github.com/WordPress/wordpress-playground/actions/runs/11631218262

@brandonpayton
Copy link
Member

The workflow has completed successfully a number of times now. The next production test is seeing what happens when new WP versions are released.

@bgrgicak
Copy link
Collaborator Author

bgrgicak commented Nov 6, 2024

The workflow is working correctly.

6.7 RC3 was released on November 5th and it was added to Playground the same day and can be loaded on the Website.

The commit history only has the RC3 commit from the Recompile WordPress major and beta versions job.
As expected, all other runs didn't create commits, because there were no other changes to WordPress versions.

@adamziel
Copy link
Collaborator

Nice teamwork here 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Bug An existing feature does not function as intended
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants