Composer Patches
Background
The cweagans/composer-patches
composer plugin enables adding patches for your composer dependencies.
There have been reports that the Drupal Association is reporting large hosting costs associated with developers hotlinking patch files in their composer patches configuration. Beyond this, hotlinking patch files is not a good idea because it adds an additional dependency when building your project. If the D.A. servers are down, so is your ability to build your site.
At least it should be
Make sure you have "composer-exit-on-patch-failure": true,
in the "extra"
section of your composer.json
file. This will stop composer install
from completing if the patching fails. Without this turned on, it can be easy to not notice that a patch failed, and leave you without whatever fix you needed for the site.
Our Practice
In short:
Download patch files to the
patches
folder with a consistent filename to ensure easy maintenance.Add patches to the composer.json file with metadata to make other developers' or our future selves' lives easier.
Patch Files
Patch files should be downloaded to a patches folder in your project root. They should be given a consistent filename consisting of the following information:
module_name - the machine name of the module
issue_number - the issue number for the issue where the patch is being discussed
comment_number - The comment number where the patch file was updated, or the most recent relevant comment number on the issue discussion. This will make it easier to go back and see what has changed when you need to go check on the patch.
Your patch file should follow the format: {{module_name}}-{{issue_number}}-{{comment_number}}.patch
How to get a patch file for a drupal.org ticket.
With the introduction of GitLab, this information is in flux. Patches on the ticket are being slowly replaced with Merge requests, and in the future .patch
files may not be the best way to keep Drupal module bug fixes applied. This may be a good source for updated information.
Often patch files are uploaded to the ticket. This is useful because the patch corresponds to a specific moment in time in the issue discussion, and makes it easy to track which version of the fix you are working with.
If an up-to-date .patch
file exists on the ticket, download that. Alternatively, if there is a merge request on the ticket, there should be a link labeled “plain diff” at the bottom of the issue summary. Right-click that, and save it to the patches directory with an appropriate
{{module_name}}-{{issue-number}}-{{most_recent_comment_number_on_the_issue}}.patch
filename.
You can also get a patch from a GitLab merge request page by appending .patch
to the URL.
Composer.json
Adding the patch to your composer.json project should be done in a similarly rigorous way as you did with your patch naming.
In composer.json we want to capture the following information:
Short Description
Jira Ticket ID
Issue/Comment URL
path to patch
Your composer.json patch entry will take the following form:
"{{package 1}}": {
"{{short description} - {{jira-issue}} - {{issue/comment url}}": "{{patch path}}"
},
"{{package 2}}": {
"{{short description} - {{jira-issue}} - {{issue/comment url}}": "{{patch path}}"
}
To give an example that lines up with the patches directory above:
"patches": {
"drupal/unique_field_ajax": {
"Stop the module from breaking VBO - s511-987 - https://www.drupal.org/project/unique_field_ajax/issues/3298235#comment-14614385": "patches/unique_field_ajax-3298235-4.patch"
},
"drupal/views_bulk_edit": {
"Copyright field gives required error even when not trying to change that field - s511-2011 - https://www.drupal.org/project/views_bulk_edit/issues/3024419#comment-14548770": "patches/views_bulk_edit-3024419-30.patch"
}
},
Edge Cases
Multiple Patches with Conflicts
If you’re applying more than one patch that has conflicts with the other patches you’re applying, you can have Composer install your own fork of a module with all your own patches applied. This doesn’t happen often, but it can happen…
Fork the module on either GitLab or GitHub
Create a new branch with all of your patches applied with the conflicts resolved. Name the branch something inspiring, like sfusd-1234--fancy-patches
Reference the branch directly through composer…
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/kalamuna/stringoverrides "
}
],
"require": {
"drupal/stringoverrides": "dev-sfusd-1234--fancy-patches"
}
}
The above will make Composer install the “allofmypatches” branch of stringoverrides, from Kalamuna’s own fork on GitHub.