Problem/Motivation
https://github.com/cweagans/composer-patches is widely used but we probably can't offer full support.
Proposed resolution
Possible solutions:
- Do nothing in code but have handbook page to describe possible problems
- Make a validator that doesn't allow updates if the this library is installed. In this case more complex use cases could remove this validator if they want to support it.
- Check for
composer-exit-on-patch-failureto make sure it will error out and warn or error if not set - check to see if core in patched and warn or error
- check the patches applied in stage and make sure they are applied the same as active
The problem with 3 to 5 is we are basically supporting the library. We would probably also have to check the version of the project they are using because in a major version change of cweagans/composer-patches we could expect some API breaking changes that would break our checks.
→ this problem has been addressed by #3331168: Limit trusted Composer plugins to a known list, allow user to add more and will be fully addressed once #3340022: Tighten ComposerPluginsValidator: support only specified version constraint is done.
Also we would have to check the API policy because it is possible that how it stores which patches are applied in vendor/installed.json might not be considered an API and could break in any version. That would make 5) the most fragile.
→ Automatic Updates will never modify the extra section of composer.json, so that is a non-concern — combined with composer-exit-on-patch-failure, plus the protection against installing/uninstalling cweagans/composer-patches means this is all addressed.
We should not check that the same set of patches is applied. Because package_manager is a very general module; there very well may be a patch_manager module at some point in the future which will allow adding/removing patches listed in extra 🤓
To be clear: we only need to address this problem thoroughly enough to be included in core. That means we don't need to solve the problem from every angle; we just need to make this "good enough" for the majority of sites. Even a simple warning about
composer-exit-on-patch-failuremight be enough for core's purposes. We can leave very robust solutions to contrib.
At this point, we've done much more than this — we're validating that::
composer-exit-on-patch-failureis enabledcweagans/composer-patchesis required in the rootcomposer.json— i.e. not indirectlycweagans/composer-patchescannot be installed nor removed through Package Manager — it can only be enabled manually
… which combined with #3331168: Limit trusted Composer plugins to a known list, allow user to add more and #3340022: Tighten ComposerPluginsValidator: support only specified version constraint does guarantee that the use of cweagans/composer-patches cannot result in a site getting broken through either Automatic Updates or Project Browser.
Remaining tasks
Issue fork automatic_updates-3252299
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
heddnI think for 1&2 were we ignore its existence and don't update sites that use it; we are going to leave a lot of unhappy folks. especially for minor patches in contrib, 90% of the time the patches re-apply. Something that incorporates #3 into it seems like the best of all worlds. And maybe give a warning that the site is using it and it _could_ cause unexpected issues.
Some possible doom and gloom cases are when something goes from contrib into core and core updates and you need to remove the patch from contrib for the site to function. The patches apply still in contrib. Obviously they work in core too, it is part of core. But then in this scenario, the site stops functioning. Given we have sandboxing and hopefully a breaking change like that doesn't happen within a minor core release, we are probably OK. But worst case is a broken site. Best case, the site updates successfully 90-95% of the time.
Comment #3
phenaproximaAgreed. This plugin is very widely used and IMHO we cannot just ignore it or deny service.
To me, this is an appropriate solution for MVP.
I think this is the most robust way, but it could be implemented in contrib.
Comment #4
tedbow@heddn thanks for weighing.
re
remember the MVP for core and will be only patch updates for contrib so won't support any contrib updates for now.
We also could change how we handle cweagans/composer-patches in the MVP as we change what we support in the way of updates
Comment #5
phenaproximaComment #6
cweagansOne other thing to consider: if you're invoking `composer install` on a shell (as opposed to just running the Composer code directly from Drupal or something), you can set the env var `COMPOSER_EXIT_ON_PATCH_FAILURE` to true to force the behavior you want.
Also: it might be worth verifying somehow that the majority of Drupal 8/9 sites actually use Composer Patches. Not sure how many people would be using Composer and _not_ be using Composer Patches, but maybe it's more common than expected and you can sidestep this work altogether. I think it would be pretty reasonable for an MVP to not support patching, build support in contrib, and pull it into core in a later version.
Comment #7
effulgentsia commentedWe don't have TUF signing for patches and won't for MVP. Therefore, I think that if a patch needs to be re-downloaded, we need to error out by default.
If core isn't patched, then we should still allow composer-patches to exist and be used for patching modules that aren't being auto-updated. If we think it's important to support the use-case of core being patched (I'm not convinced it is for MVP), then I think we either need to do that via a separate contrib module (e.g., automatic_updates_extras) that could allow non-TUF-verified downloads, or we'd need composer-patches to make a local copy of patches that get downloaded during non-automatic install/update and only use that local copy during automatic updates.
Comment #8
phenaproximaDiscussed this with @tedbow, so let me summarize how we agreed to proceed. We will write a new validator, which will be included in the core Auto-Updates module, to implement a restrictive policy about patching. It will listen to ReadinessCheckEvent and PreApplyEvent. This is the logic it will use.
During ReadinessCheckEvent:
- Is cweagans/composer-patches in the active directory? If not, bail out; there's nothing to validate.
- Are we explicitly intending to update drupal/core? If so, is it currently patched in the active directory? If it is, flag an error; we don't support patching core right now.
- Is anything else (vendor dependency, contrib module or theme) patched? If so, flag a warning that we don't support patching, and if any of these things get updated in the stage directory, it will stop the update.
During PreApplyEvent:
- Is cweagans/composer-patches in the stage directory? If not, bail out; there's nothing to validate.
- Has drupal/core been patched in the stage directory? If it is, flag an error; we don't support patching core right now.
- Did anything else (vendor dependency, contrib module or theme) that is patched in the active directory, get updated in the stage directory? If so, flag an error, because we don't support updating patched things.
So, what I think this adds up to is two things:
- We won't let you patch core.
- We won't update anything else you've patched, and will stop the entire process if you try.
@tedbow, can you confirm this understanding?
Comment #9
tedbowthis sounds good except for ReadinessCheckEvent
I don't think we need to warn about drupal modules or themes here because we only support core and
\Drupal\automatic_updates\Validator\StagedProjectsValidatorstops an update if any of these are updated. So if somebody removes that validator it is there responsibility add the warning about patches.I would leave the check in
PreApplyEventthough as safeguard.Comment #11
tedbowJust bumping this issue to see if this is something we need to commit before stable. @phenaproxima or anyone else?
Comment #12
tedbowComment #13
tedbow@phenaproxima is going create issue to just fix the
composer-exit-on-patch-failureproblem in pacakge_manager as a RC targetComment #14
phenaproximaOpened #3293381: If cweagans/composer-patches is installed, require composer-exit-on-patch-failure.
Comment #15
tedbow#3293381: If cweagans/composer-patches is installed, require composer-exit-on-patch-failure was committed. Not sure if need to do anything else.
Comment #16
wim leersI don't see how we can not have an answer for this.
I see that #3293381: If cweagans/composer-patches is installed, require composer-exit-on-patch-failure addressed some portion of it at least. But we absolutely need clarity on this. It could be in the form of documentation, not code. But then I think requiring test coverage that goes further than #3293381's
package_manager/tests/src/Kernel/ComposerPatchesValidatorTest.phpis critical: we need to verify through tests not only that we complain loudly ifcomposer-exit-on-patch-failureis not set totrue; we also need to verify that we can indeed successfully update with patches applied! For example … a simple core patch.Comment #17
wim leersWhile working on #3331168: Limit trusted Composer plugins to a known list, allow user to add more, I also noticed that
\Drupal\package_manager\Validator\ComposerPatchesValidatorcurrently has a critical oversight: it only checks the activecomposer, not the stage one!That means if some module has a dependency on
cweagans/composer-patches, it could cause it to get installed, and then the value ofcomposer-exit-on-patch-failurewould never be checked byComposerPatchesValidator!Comment #18
wim leers#17 made it sound like
cweagans/composer-patchesisn't reliable. That's not what I meant — I meant PM/AU's existing safeguards are inadequate and untested.Comment #19
wim leersComment #20
kunal.sachdev commentedComment #22
wim leersPaired with @kunal.sachdev on a way forward to do #17 — realized that we cannot test that in a
Kerneltest, so helped him get the outline in place for testing that in aBuildtest! 👍 Good luck, @kunal.sachdev 😄Comment #23
kunal.sachdev commentedComment #24
tedbowThe summary currently still has "Possible solutions:" so it should updated describing what the current merge request is meant to do. Also we specify which merge request is the chosen fix, and close the other if that is appropriate
Comment #25
wim leers@tedbow identified an extra thing we need to protect against. I posted a proposal on how to do that.
I identified a few clarity nits … but also just spotted one more thing we need to test: https://github.com/cweagans/composer-patches#allowing-patches-to-be-appl... — we should expand our test so that the
drupal/alphaproject specifies adrupal/corepatch, which will be installed if and only ifconfig.extra.enable-patching === true.GREAT job on getting this test to work! 🤩 It looks excellent! With just these few additions (from @tedbow and the one I just asked for), we'll be able to be highly confident in our support for https://github.com/cweagans/composer-patches 😊
Comment #26
kunal.sachdev commentedSo, for the build test failure
Failed to copy "/tmp/.package_manager1138399f-efbb-4de5-9615-4d8919835d23/cYjbXr4SVceHzcM14tPFfA2Jnk3JCLZvpjYgEVtk-Xo/vendor/drupal/coder/.git/objects/pack/pack-4a9af0fe0580e9f82296d111933506654039d16a.idx" to "/tmp/build_workspace_1f164ac4a984a2ad22cbee436c59452bfdpZqI/project/vendor/drupal/coder/.git/objects/pack/pack-4a9af0fe0580e9f82296d111933506654039d16a.idx". in Drupal\package_manager\Stage->apply() (line 495 of modules/contrib/automatic_updates/package_manager/src/Stage.php)which is currently not there as we have a temp fix in GitExcluder , I tried to update drupal/core with Automatic Updates in a real drupal project:composer create-project drupal/recommended-project:10.0.0 test_dir --no-install --no-interactioncomposer require drupal/core-devas drupal/core-dev has a dependency ondrupal/codervendor/drupal/coderThis points out that we may not have this problem in real time.
Comment #27
wim leersDiscussed in detail with @tedbow & @kunal.sachdev.
Conclusions:
composer-patchesis something that would be good to have, but it's post-MVPcomposer-patchesor whether that is from a networking error, wrong requirement, whatever → this needs a separate issuecomposer-patchesshould never be installed nor removed — it should stay exactly as it is: so if it's absent in theactive, it should be instage, and vice versaComment #28
wim leersExecuting #27:
Done:
The third point is up to @kunal.sachdev 😊
Comment #29
wim leersExtracted the build test work Kunal did to #3338667: Add build test to test cweagans/composer-patches end-to-end's MR, while preserving Kunal's commits 👍
Just pushed a commit that now reverts those changes from this MR.
Comment #30
kunal.sachdev commentedComment #31
wim leersNote that this still uses
::getStageComposer()and::getActiveComposer(), but that was already the case in HEAD, so let's not delay it over that.This merge request is looking great, but is still in need of a range of finishing touches before this is RTBC. I'm confident you can get that done by the next time we meet, @kunal.sachdev! 😄
Comment #32
kunal.sachdev commentedComment #33
wim leersExcellent work here, @kunal.sachdev! 👏
Docs: ✅
Tests: ✅
Issue summary update: just did that.
Comment #34
phenaproximaFound a few nitty things that aren't blocking, and then one thing that looks like a genuine mistake that I'm surprised is not breaking tests.
Comment #35
wim leersComment #36
kunal.sachdev commentedComment #37
kunal.sachdev commentedComment #38
wim leersComment #40
tedbowTest failing on 7.4 ,core 9.5
Comment #41
tedbowRTBC again. I haven't reviewed this more, just fixed the php 7.4 error(pretty sure tests will pass now)
Leaving assigned to @phenaproxima
Comment #42
tedbowSorry I know this issue has been long slog. See MR comments
Comment #43
tedbowComment #44
tedbowI created #3341469: Create StageBase::stageDirectoryExists() for improved DX to see if stage directory exists. to help with this https://git.drupalcode.org/project/automatic_updates/-/merge_requests/66...
Comment #45
kunal.sachdev commentedComment #46
tedbowLooks great!
Comment #48
tedbow🎉 Thanks @kunal.sachdev, @Wim Leers, and @phenaproxima
And @cweagans for making a plugin that is so useful to so many people in Drupal that we can't just ignore it😜

☝️ gif reserved for critical, core-mvp issuesComment #49
wim leersYAY!
Unpostponed #3338667: Add build test to test cweagans/composer-patches end-to-end.
Comment #50
wim leersA regression was introduced shortly before commit, spotted by @kunal.sachdev: #3341841: Fix language nit in package_manager_help().
Comment #51
mark_fullmerI saw this recent comment from the maintainer of composer-patches: https://github.com/cweagans/composer-patches/issues/411#issuecomment-142...
I take that to mean that a future release of
cweagans/composer-patchessimply won't allow patches from this module to apply to a site: the patches *must* be defined in the site'scomposer.jsonfile.Testing on dev-main of Composer Patches (#f88fd4) seems to confirm this. Can someone corroborate this? Does this mean this approach for automatic_updates simply won't work?
Comment #52
cweagansI can corroborate that :) probably don’t take action on that right away though. Currently traveling, but I’ve gotten a lot of feedback on that and I’m thinking it through a bit more.
Comment #53
wim leers@mark_fullmer Thanks for bringing that to our attention! But …
composer-patchesalso works reliably!composer-patchesis released … and this very upstream change proves that that is a valuable and essential requirement 😊👍