composer-patches
composer-patches copied to clipboard
Support for mirrors/proxies
This composer plugin uses direct URLs to patch files. As such it doesn't respect the mechanisms Composer has in place for packages that allow you to replace packages by listing different repositories.
In particular this means that the features available through services like Private Packagist https://packagist.com cannot include patches installed through this plugin. For packages we mirror metadata and code archives to ensure the customer has a copy of the file if it's either unreachable or deleted, so they can keep deploying their currently used version in case of problems. Further in Enterprise environments Private Packagist may be used as the only service allowed to contact outside repositories to download code, while developer machines and CI systems may only download code from Private Packagist. Neither of these mechanisms can be implemented fully if projects rely on patches through this plugin as the direct download links prevent Private Packagist from proxying downloads.
So I wonder if there is (a) interest in addressing this problem at all? (b) What an approriate mechanism could be to allow for this.
My initial idea would be to adjust this plugin to check if any of the Composer repositories offer a yet to be defined new endpoint for cweagans/composer-patches-mirrors as part of their packages.json file which is downloaded anyway. If they do, then instead of downloading patches directly, the URLs are first sent to this new API endpoint on the Composer repository which may rewrite them.
That way individual Composer repositories can replace URLs with mirrored URLs of their own, but can skip any URLs they either don't have copies of or the user doesn't want them to replace.
Any ideas/thoughts on this proposal? Problems with my solution or other ideas on how to address the underlying issue?
I'm not sure I understand the problem here. It shouldn't matter where package metadata is coming from (packagist.org, private packagist, satis, etc) - the patch is just slapped on after the package is downloaded. If it applies properly, great. If a user changes metadata sources for a given package, I think it would also be appropriate to change where the patch is coming from?
Can you help me understand a bit more here? Is there a specific scenario where things aren't working correctly?
@cweagans The problem is that the patch listed in some package is at https://some-maintainers-basement.com/foo/bar/123.patch - now as a business that relies on this patch getting applied when deploying, I don't want my deploys to stop working when https://some-maintainers-basement.com goes down. And in a corporate network, my dev machine running composer update/install may not even be allowed to download any patch files from https://some-maintainers-basement.com.
Part of what Private Packagist does for all Composer packages is mirror them, so all your packages, even any third party dependencies hosted elsewhere are installed from packagist.com. Composer has functionality for mirroring or proxying packages like this built in. That's why the "require" section in Composer doesn't contain URLs but only package names. So in the repositories section you separately choose where package data is coming from. Such functionality cannot currently be provided for the code in the patches themselves. But we'd like Private Packagist to do that, especially for all our Drupal customers. Hence my proposal here to give Composer repositories a way to rewrite the patch URLs before they get downloaded and applied, so Private Packagist could rewrite all patch URLs to e.g. https://repo.packagist.com/my-company/patch-https-some-maintainers-basement-com-foo-bar-123.patch and download the file from there. We can then store a copy so that if the open source maintainer's website is down, our customers can still install the patch.
Ah, okay. That makes sense. I see a pretty clear way of making this work transparently in 2.x, but that's nowhere near ready for day-to-day use.
To solve the immediate problem, I'm not opposed to putting this directly into this plugin if there's a straightforward/low-impact way to do it. If it's completely disabled by default and only enables itself in a Private Packagist environment, that's fine. One other option would be to do this in another plugin and just make sure that your event subscribers run after these: https://github.com/cweagans/composer-patches/blob/1.x/src/Patches.php#L73-L74, add a getter and setter for https://github.com/cweagans/composer-patches/blob/1.x/src/Patches.php#L49, and then you can do whatever you'd like (assuming Composer gives you a way to get the instance of some other plugin).
I think I'd rather add it to this plugin in a transparent way, so that we don't have to force people to install another plugin on existing projects to make use of this, Private Packagist may also not end up being the only user.
I think my proposal with enabling this based on a setting returned by packages.json when Composer makes a request to the repositories anyway probably makes sense. I'll just have to check how this works when running on a composer install with an existing lock file.
Either way if you're not opposed, we'll look into working on this in the next few weeks and send a PR when we have an idea how this could work :-)
main
doesn't resolve patches from dependencies anymore, so this may be less of an issue. It also caches patches locally to avoid the scenario where the patch URL is not available anymore.
@cweagans This is still very much an issue and something we'd like to work on. Unfortunately it was pushed down our priorities quite a bit.
Essentially Composer offers mirroring capabilities to work in environments that don't have public internet access but only allow access to a reviewed Composer repository. Any composer plugin directly trying to access URLs on the internet rather than going through Composer's network mechanisms breaks this feature.
As a consequence Private Packagist customers using this plugin cannot get their projects to work in that restrictive a corporate network currently, e.g. when trying to manage drupal projects.
That said, happy to just reopen this / a PR when we actually get around to it, instead of keeping this open forever ;-)
Any composer plugin directly trying to access URLs on the internet rather than going through Composer's network mechanisms breaks this feature.
1.x
and main
both now use the Composer downloader component, so proxying and all that should work properly. Not in a release yet, but you can try 1.x-dev if you'd like.