3

I am working in a php project, and our 3rd party dependencies are managed with packagist via composer.json. Pretty standard stuff. Sometimes we run into a situation where a given plugin has some issue, such that we would like to continue to use the plugin but the issue makes it a liability or just straight up unusable.

One idea might be to make a pull request to fix the issue, but that involves "a. the repo is actively monitored and b. we actually know how to fix the issue". We may have neither. If we have (b) but not (a) we could fork the repo with our own fix? Or we could modify the file in the vendor directory and commit it to the repo? Both prospects seem unappealing.

Most recently the php-whois package had an issue, because it used some terribly asinine code:

if (empty($r)) {
    if ($hasreg)
        $r['registered'] = 'no';
}

If $r is unset, or ='' or =0 or =null or a number of other situations, empty($r) will be true and $r['registered'] = 'no' will at the very least trigger a warning, or, as of php ~7.1+, trigger a fatal error.

What is the best course of action? Find a new php-whois package? Make the (easy) fix ourselves (just do $r=[];) and commit to our own repo? Something else?

This is a tricky situation that I don't find myself in often, but it has come up more than once.

Using Laravel 5.3, in case that's relevant.

  • 1
    Is there a reason you're letting Packagist automagically upgrade your dependencies to versions you haven't tested instead of limiting it to versions you have? – Blrfl May 11 '17 at 12:36
  • @Blrfl that's not what happened. The php version of the production server is slightly more recent than the version used in the vagrant box we develop on. So, everything was fine in development and didn't become an issue until we pushed to production – chiliNUT May 11 '17 at 13:36
  • 5
    The first issue is that you don't use the same version of your tools in development and in production. – Vincent Savard May 11 '17 at 14:39
  • I agree that that is an issue – chiliNUT May 11 '17 at 14:42
4

It depends, there is no general solution. Things you need to consider:

  • the license conditions of the 3rd party package (especially for the case you want to change the source code)
  • the willingness of the vendor/maintainer to fix bugs, or accept pull request, in conjunction with his response times
  • for commercial packages: your contract with the vendor
  • the possibility of creating a workaround in your own code, without changing the package code
  • the complexity of the package and the feasibility to implement your own bug fixes without breaking other things
  • the availability of alternative packages, their quality, their license terms, and the effort it takes to switch to such an alternative
  • your own requirements for response times in case your system has an issue because of this

I recommend whenever you have to choose a 3rd party component, you invest some thoughts into these point before you start using the package, otherwise don't be astonished if you wake up some morning and recognize you have painted yourself into a corner.

  • I would only add that usually the first course of action is to reach out to the 3rd party and attempt to get help. If you have a support contract, then chances are good that they will help you. It could be the way you have it hooked in or another library that is causing the conflict. – Berin Loritsch May 11 '17 at 12:13
  • 2
    @BerinLoritsch: in reality, the first cause of action is typically to create a workaround, if that's easily possible. And for many free open source packages, the absence of support contracts is quite normal. But when a package like php-whois is tagged with "Unknown license", this gives me a big warning sign when I consider to use it. – Doc Brown May 11 '17 at 12:21
  • Agreed. However there are some plugins which do have some support. – Berin Loritsch May 11 '17 at 13:23
2

The issue is that you're upgrading to new versions of third-party libraries and push the thing into production without thoroughly testing it.

Upgrading a dependency is not any different than any other change in your code. This means that once the change is done, one needs to run automated regression tests in order to be sure that everything works fine.

The php version of the production server is slightly more recent than the version used in the vagrant box we develop on. So, everything was fine in development and didn't become an issue until we pushed to production

Those tests should run on an environment as close as possible to production. If you run them on a different version of PHP and then carelessly push the change to production, you will have regressions, and it's not the fault of a third-party library, but rather of a flawed workflow.

So, back to your question:

One idea might be to make a pull request to fix the issue [...] we could fork the repo with our own fix? Or we could modify the file in the vendor directory and commit it to the repo? Both prospects seem unappealing.

If you're actively contributing to third-party libraries, in other words if your boss thinks that doing that will have financial benefits for the company, then go for it.

If not, it's not your job. You're paid to work on the project, not contributing to third-party libraries. Your task is to ensure that whatever happens with the dependencies, your project would still work. What could possibly happen?

  • A regression could be introduced in the next version of the library. This is the problem you mention in your question.

    In order to mitigate the risk of being affected by that, you set a specific version of the library which was correctly tested and proved to be compatible with your app and your production environment. You upgrade to the next versions in a similar way you perform any change on the source code, involving version control and regression tests.

  • A library can be plainly removed from a repository.

    To mitigate that risk, you should ensure that you have either a sort of a proxy which caches all the versions of all the repositories you ever downloaded, or you use a artifact repository. To my knowledge, the second solution is more common.

  • A library shifts progressively in a direction you dislike, making it more and more problematic to use.

    In order to mitigate that, you ensure you don't use the third-party library everywhere in your code. There should be an abstraction put between your code and the outside world, and a well-designed adapter should make it possible to switch, if needed, to a different library. This way, when it appears that a different library responds better to the requirements, you just write another adapter, and swap the libraries. As simple as that.

  • @DocBrown: my answer was based on a short discussion in the comments; unfortunately, the question wasn't edited to integrate those comments, given that they seem crucial for a good understanding of the original question, which appears more of an XY problem. I expanded my answer, including, among others, the relevant quote. – Arseni Mourzenko May 11 '17 at 20:44
  • Ah, I see, the comment was not there when I wrote my answer. Upvoted yours. – Doc Brown May 11 '17 at 21:38
1

Here's what we do: (which may be totally inappropriate for your shop):

We are a Windows C++/C# Shop, so managing 3rd party dependencies (open source or not), esp. in C++, is historically more complicated anyways.

Best(?) practices for when a 3rd party dependency breaks

What we do with 100% of our 3rd party dependencies is that we:

  • Host available source code in our own SCC servers
  • Host all binaries on our on SCC / artifact servers
  • Try to build the binaries ourselves, where the (C++) source code is available. (With all compiler flags considered, this is a necessity for most 3rd party C/C++ code anyways. At least that way I also have consistent pdb files.)
  • Even for open source C# libraries, where we use the bins from the Web, it is a requirement that their sourcecode is available on our server before we use them -- i.e. No public nuget access - only our company server for released code.

When it breaks:

If something breaks, since we should be able to build it on our infrastructure in, say, a day or so, (considering we may not have touched it for a while), we apply the source code fix to our source repo of the component, re-build it and we're done on our side.

Where possible, we also send out pull requests / patches to the original projects, so that we can later switch back to an updated unpatched version of the original 3rd party lib.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.