A few days ago I wrote about a WordPress plugin that was broken under PHP 8.1. We need to patch it in a sustainable way in production until the vendor issues a fix. Because we deploy with Composer in a continuous deployment environment, it’s not so simple as just commiting the change or (gasp) modifying the file on the server.
One approach would be to create a git copy of the plugin in our private GitLab repository, commit the changes there, and then deploy that version instead. There’s a lot of overhead involved in that approach:
- Create the repository, including (optionally) using svn2git to import the plugin from the WordPress plugins repository. You can also just commit the current state.
- Add the plugin to our Satis-based Packagist repository.
- Redeploy referencing that repository instead of the WordPress upstream via WordPress Packagist.
That’s a lot of work for a four-line change, especially when we think it’s likely that the vendor will provide a fix. It’s not as through we’re maintaing a complex fork here.
Fortunately, my friend Andy Zito made me aware of the composer-patches project, which offers a lightweight alternative. With composer-patches, you can define patches to be applied to composer packages post-installation. These can be at a remote URL, or stored locally in your project. The default current working directory for applying the patch is the root installation directory of the package. For example, given this block:
1 | "extra": { |
Composer will clone the simply-static plugin from the WordPress plugins repository (via WordPress packagist), and then apply the patch stored at patches/simply-static.patch
within the project repository.
To create the patch, I took a copy of the plugin code and initialized a git repository. I then added everything but did not commit. I then made the necessary changes, and used git diff
to create the patch:
1 | diff --git a/simply-static.php b/simply-static.php |
Composer then applies the patch; functionally, it’s doing patch -p1 < /path/to/your/patch
in the root of the plugin directory.
This is not a replacement for proper version control if you’re actually managing a fork. In this case, I’m taking the line that the version control is the responsibility of the vendor, and they’re managing the changes. Given a more complex set of changes, and in particular a real change in functionality, I’d probably go the longer route and create a separate repository.