Problem/Motivation

External dependencies can use .gitattributes to control what files are present in Composer packages: http://blog.madewithlove.be/post/gitattributes/

This means that if you use composer install with the --prefer-dist flag, the dependencies installed by Composer might not contain the test directories we clean up in our post-install scripts.

The result is that our post-install script throws an exception when e.g. tests/ directory is missing.

The reason we have the post-install cleanup script is this: #2585165: Don't include vendor test code (especially mink) in the Drupal webroot and also #2508591: vendor/ is web accessible both security issues.

Proposed resolution

Two proposals:

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Mile23 created an issue. See original summary.

mile23’s picture

Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new64.97 KB

Pins paragonie/random_compat to ~1.2 in composer.json.

Removes paragonie/random_compat's test directory from the list of directories to remove in the composer hook.

Since the testbot performs a composer install, this should tell us whether paragonie/random_compat 1.2.0 passes our tests.

Update: From the test log:

18:45:18   - Removing paragonie/random_compat (1.1.1)
18:45:18   - Installing paragonie/random_compat (v1.2.0)
arknoll’s picture

StatusFileSize
new1 KB

Removed composer.lock from the diff. This will cause merge fails on latest 8.1.x.

mile23’s picture

Yah, git can't apply my patch already.

So whoever applies the patch in #3 should run composer update before committing it.

Or else we'll need to reroll.

barryvdh’s picture

If a directory changes, it shouldn't block the entire instal process..
Why not check if the folder actually exists? This can happen to any library, that adds the test folder to .gitattributes.

barryvdh’s picture

A better solution would be to not have the vendor directory in the public folder, but I'm guessing that's discussed in a different issue already..

mile23’s picture

Yes, ideally vendor/ would be elsewhere, but we have to support shared hosting.

Also, if we test whether or not the directory exists before deleting it, then we lose the benefit of an error when the vendor changes the files around.

barryvdh’s picture

If a project adds the test folder to .gitattributes, it will be ignored when creating the archive. But if you install packages with --prefer-source, for example because of API rate limits, it will still include the tests folder.

So not checking will leave some people vulnerable.

FYI, I also have a composer plugin with some common folders/file to delete, like docs and examples; https://github.com/barryvdh/composer-cleanup-plugin

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

bojanz’s picture

Version: 8.2.x-dev » 8.1.x-dev
Status: Needs review » Needs work

The patch does need to include the composer.lock changes for paragonie/random_compat alone as well as the actual updated library.
The trick is in running "composer update paragonie/random_compat" instead of just composer update.

bojanz’s picture

Status: Needs work » Needs review
StatusFileSize
new48.54 KB

Hm, looking at https://github.com/paragonie/random_compat/tree/v1.2.1 I still see the tests/ directory, and get no error running composer update?
I'm confused.

Here's the patch that updates the library, in any case.

barryvdh’s picture

As I said before, the directory still exists, but is excluded with the .gitattributes export-ignore feature. See https://github.com/paragonie/random_compat/commit/e1ddb31788f16f4527074f...

This means, that on dist downloads, they are excluded, but on source downloads they are still there. So you don't know for sure if the folder exists before running the removal.
This will happen with every library that uses this feature (which are a lot of them..)

bojanz’s picture

We definitely need to do #5 then.

The current code is:

        if (is_dir($dir_to_remove)) {
          if (!static::deleteRecursive($dir_to_remove)) {
            throw new \RuntimeException(sprintf("Failure removing directory '%s' in package '%s'.", $path, $package->getPrettyName()));
          }
        }
        else {
          throw new \RuntimeException(sprintf("The directory '%s' in package '%s' does not exist.", $path, $package->getPrettyName()));
        }

We just need to kill that last "else".

londova’s picture

Hello guys,
I am an average/advanced computer user and I find it difficult to manage all these changes. Could you make them more "user friendly"? I spent about 1 week and unable to solve this problem.
Or Drupal Commerce is ONLY for people with advance knowledge in coding?

bojanz’s picture

@British-Link
Drupal Commerce for Drupal 8 is incomplete pre-alpha software, aimed at developers looking to contribute.
Regular users are advised to use the Drupal 7 version until Commerce hits beta or RC1 (depending on how comfortable you are chasing bugs and doing custom coding).

bojanz’s picture

Title: paragonie/random_compat filesystem changed, vendorTestCodeCleanup is out of date » Don't throw an exception if a vendor test dir can't be found
Assigned: Unassigned » bojanz
Status: Needs review » Needs work

Working on a new patch.

mile23’s picture

Title: Don't throw an exception if a vendor test dir can't be found » Combination of --prefer-dist and .gitattributes confuses our vendor test cleanup
Issue summary: View changes

Just a reminder: The reason we know this is an issue is because it threw an exception.

Updated issue summary.

We could also consider a follow-up of adding our test directory to a .gitattributes file.

mile23’s picture

Issue summary: View changes
bojanz’s picture

Priority: Normal » Major
Status: Needs work » Needs review
StatusFileSize
new663 bytes

The only way to support both --prefer-source and --prefer-dist is to not throw an exception. Patch attached.

Note: there were no tests to change.
Changing priority to major since this crashes Composer.

karens’s picture

8.0 production sites that use composer are now affected by this. I see this is a patch against 8.1 but we need this for 8.0 as well. It seems to apply cleanly to 8.0 and it works there as far as I can tell.

bojanz’s picture

Confirmed. We need this in all branches.

webflo’s picture

Status: Needs review » Reviewed & tested by the community

Makes sense, thanks for working on it.

fortis’s picture

StatusFileSize
new765 bytes
new765 bytes

I think we have to show a notice to keep $packageToCleanup up to date in the future

fortis’s picture

and we should update $packageToCleanup by removing 'tests' from 'behat/mink' element, there is another patch for that #2682003: Update $packageToCleanup, 'tests' cleanup are no longer required for Behat/Mink package

mile23’s picture

Status: Reviewed & tested by the community » Needs review

Nice, @fortis.

+1 on printing a warning.

The issue was left at RTBC, though, so I'm setting it to Needs Review so others can opine.

bojanz’s picture

I disagree with #23.

It will output a warning on --prefer-source for every library that uses the .gitattributes approach (which will soon be all of them).
That will result in a lot of bogus reports, like the one about Mink.

I still think we need to go with #19, otherwise we'll have to keep explaining this day after day.

Regarding #24, repeating what I said in https://www.drupal.org/node/2682003#comment-10949795:

No, that is incorrect. Mink still has a tests directory: https://github.com/Behat/Mink/tree/master/tests
And if you install/update with --prefer-source, you will get it.

barryvdh’s picture

I agree, showing the warning will probably lead to a lot of issues/questions.

+1 for just removing the Exception.

fortis’s picture

Status: Needs review » Reviewed & tested by the community

@bojanz yes, you're right
#19 works fine, RTBC

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.05 KB

How about we use composer's IOInterface to solve this for us... and only output stuff when -vv or more is used. The reason we tried to log something here is because the presence of tests in Behat was actually a security risk!

I think the patch attached gives us the best of both world's - a working composer and information on what is happening inside Drupal\Core\Composer\Composer

mile23’s picture

IO+++++ :-)

How about -vv for success notifications and -v for not found and error?

I only care because it's a security thing.

barryvdh’s picture

But just to be clear, you're keeping this list inside the core of Drupal? So everytime a package changes, it needs a core update, before it's safe?
Why not create a Composer plugin, so it can be updated independ of the core, at the same time as the packages?

And are you going to accept PRs for *every* package that can be used with Drupal? Eg., say I want to use dompdf in my site/module, so I require it in my root composer.json. But I don't want the tests/examples, so should I create a PR to Drupal core to add the dompdf package rules to it? Seems like a lot of work/time for this..

Imho this plugin is still a workaround for the vendor dir being in the webdir. Or is this configurable?
When people can use the Composer CLI, I'm assuming they probably also can change the webroot or at least symlink it to a different dir, right?
So why not create a build script to give users a 'safe' version, but for the devs who want to user Composer to manage deps, place it outside the webroot?

alexpott’s picture

@Barryvdh yes this is just a work around - and yes vendor can be configured to be outside webroot - you just have to edit the autoload.php in Drupal's root - it exists to make this possible. The point of this is nuke the tests and unnecessary stuff that would be shipped with core... for two reasons (a) test code if available to the web has security holes and (b) the downloadable package dropped over 1mb due to this.

If a project or contributed module adds another dependency to that Drupal site it is up to them to make recommendation about to safely deploy that dependency. It's great to see that composer projects are finally starting to exclude tests and other unnecessary files if one uses the --prefer-dist option... that said the (ab)use of .gitattributes to do this seems very very icky.

barryvdh’s picture

Yes I understand why you do this, it really does make sense for when you ship in in the web dir. But imho that should be just for the '1-zip install', not for when people use composer to handle it. Then it should just be outside the vendor dir. But okay, if it's not feasible to expect this from developers, then this is at least better then nothing..

(As a note, the security issue that started all this, xss in Mink, has been fixed: https://github.com/minkphp/Mink/pull/694)

alexpott’s picture

Issue summary: View changes
StatusFileSize
new1.72 KB
new2.41 KB
new106.22 KB

Discussed with @bojanz on IRC - we agreed that a missing directory is not an error so we're just going to output an informational in this case. However if the recursive delete fails we should always display an error as something has gone very wrong.

Tested by running composer update -vv --prefer-dist on core.

Sample output:

bojanz’s picture

Status: Needs review » Reviewed & tested by the community

Works for me, thanks.

alexpott’s picture

Also I'm wrong about .gitattributes being a "very very icky" solution. @bojanz pointed me to http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes see "exporting your repository"... in fact it is a super elegant solution that makes it no composer's responsibility to do - nice.

I guess what we could do is file PR's against all the dependencies that don't have a .gitattributes file to have one. And then we can remove this and a note about using composer with --prefer-source in production not being supported by Drupal somewhere on d.o.

barryvdh’s picture

@alexpott Indeed, best would be that every project does that, but not everyone agrees about this.
FYI, I've asked Mink to do that, which removed the tests dir ( https://github.com/minkphp/Mink/pull/691) , but driver-suite was needed by other packages, to some more refactoring for that is needed. If you want, you can ask them to follow up on this.
But mink and other tests tools aren't need in production anyways.

alexpott’s picture

Issue summary: View changes
StatusFileSize
new147.79 KB
new2.35 KB
new2.76 KB

Hmmm actually I think we can do a bit better with the logging...

RobKoberg’s picture

After applying the patch in #38, I get the error detailed here: https://www.drupal.org/node/2686639#comment-10965209

mradcliffe’s picture

Patch #38 applied successfully and I was able to run-through composer update on Travis CI with Drupal 8.1.x branch.

  • Before - Expand the composer line to see the issue.
  • After - Expand the composer line to see that composer update was successful and did not revert.

@RobKoberg, are you applying this patch on Drupal 8.0.x instead of Drupal 8.1.x? I think the patch only applies on 8.1.x and 8.2.x because 8.0.x does not have the Composer IO class. I also did not need to apply this patch for 8.0.x when using Composer Manager 8.x-1.x.

bojanz’s picture

@mradcliffe
The IO class comes from Composer itself, there are no differences between Drupal versions when it comes to this bug.

gvso’s picture

After applying patch in #38, I got:

composer drupal-update
> Drupal\composer_manager\Composer\Command::update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Removing paragonie/random_compat (1.1.1)
  - Installing paragonie/random_compat (v1.2.2)
    Loading from cache

> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
PHP Fatal error:  Undefined class constant 'VERY_VERBOSE' in /var/www/drupal_projects/drupal81_dev/core/lib/Drupal/Core/Composer/Composer.php on line 163

Fatal error: Undefined class constant 'VERY_VERBOSE' in /var/www/drupal_projects/drupal81_dev/core/lib/Drupal/Core/Composer/Composer.php on line 163

Testing on a fresh Drupal 8.1-dev installation.

barryvdh’s picture

Did you run `composer self-update`? Try with the latest Composer.
Verbosity support is added 28 jan, so you should have been receiving 30-day warnings for a couple of weeks.
https://github.com/composer/composer/commit/49d7d65933c78e163354c2c58088...

RobKoberg’s picture

The patch was applied to the latest 8.0.x version (downloaded the tar.gz from drupal.org yesterday). I had also just installed PHP7 yesterday (for cli and apache). I ran through the instructions at http://docs.drupalcommerce.org/v2/install.html for an Existing Site. D8 had previously installed fine. The Composer Manager and Drupal Console also was installed new yesterday.

bojanz’s picture

Priority: Major » Critical

This breaks Composer completely.
And since 8.1 and 8.2 don't have the vendor/ directory anymore, we now have a critical issue.

barryvdh’s picture

So let's just remove the Exception for now and then work on a 'better' verbose logging improvement..
(So just #19)

bojanz’s picture

The last RTBC patch is fine. We don't need to care about supporting Composer older than beta1.

  • alexpott committed ffbaa3f on 8.2.x
    Issue #2664274 by alexpott, bojanz, fortis, Mile23, arknoll: Combination...

  • alexpott committed 06a0758 on 8.1.x
    Issue #2664274 by alexpott, bojanz, fortis, Mile23, arknoll: Combination...

  • alexpott committed 95e6931 on 8.0.x
    Issue #2664274 by alexpott, bojanz, fortis, Mile23, arknoll: Combination...
alexpott’s picture

Priority: Critical » Normal
Status: Reviewed & tested by the community » Needs work

Okay - I've committed #19 because that solves the critical problem. I'll now reroll #38 and use the BC approach the merge plugin does to logging.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new2.45 KB
new2.46 KB
new132.29 KB

Here's a reroll and using a similar approach to the merge plugin...

Here's a screenshot whilst running composer -vv update on core:

alexpott’s picture

Charlotte17’s picture

For those following this issue on 8.0.x, you have to apply the patch in #19, followed by the patch in #52 to get things running again.

bojanz’s picture

@Charlotte17
The patch from #19 is already present in 8.0.x-dev.

mile23’s picture

Status: Needs review » Reviewed & tested by the community
  • Applied #52 against 8.1.x.
  • rm -rf vendor
  • rm composer.lock
  • composer install --prefer-dist -vv

Yielded messages like this:

  - Installing behat/mink (v1.7.1)
    Loading from cache
    Extracting archive

> post-package-install: Drupal\Core\Composer\Composer::vendorTestCodeCleanup
    Processing behat/mink
      Directory 'tests' does not exist
      Removing directory 'driver-testsuite'

The same process with -v (only one v) yeilds:

  - Installing behat/mink (v1.7.1)
    Loading from cache
    Extracting archive

> post-package-install: Drupal\Core\Composer\Composer::vendorTestCodeCleanup

The same process with composer update --prefer-dist -vv yields:

  - Installing behat/mink (v1.7.1)
    Loading from cache
    Extracting archive

> post-package-install: Drupal\Core\Composer\Composer::vendorTestCodeCleanup
    Processing behat/mink
      Directory 'tests' does not exist
      Removing directory 'driver-testsuite'

And just to cover the original problem:

  - Installing paragonie/random_compat (v1.4.1)
    Loading from cache
    Extracting archive

> post-package-install: Drupal\Core\Composer\Composer::vendorTestCodeCleanup
    Processing paragonie/random_compat
      Directory 'tests' does not exist

So therefore: I think this is ready for prime time.

Patch applies cleanly to 8.2.x as well.

  • catch committed e9fc0f1 on 8.2.x
    Issue #2664274 by alexpott, bojanz, fortis, Mile23, arknoll, Barryvdh:...

  • catch committed 3fc42dd on 8.1.x
    Issue #2664274 by alexpott, bojanz, fortis, Mile23, arknoll, Barryvdh:...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.2.x and cherry-picked to 8.1.x. Thanks!

scuba_fly’s picture

Version: 8.1.x-dev » 8.0.x-dev

I guess we still need #52 on the 8.0.x branch?

bojanz’s picture

Version: 8.0.x-dev » 8.1.x-dev

There won't be any new 8.0.x releases, so there's no point in tweaking this further.

siliconmind’s picture

@bojanz so how do I update 8.0 to 8.1 with composer?
When I run composer update on 8.0.3 - I get this crappy The directory 'tests' in package 'behat/mink' does not exist. error.

When I edit my composer.json file to use drupal/core 8.1 I can't update because composer complains that installed 8.0.x requires symfony/yml 2.7 and 8.1.x requires symfony/yml 2.8

bojanz’s picture

@SiliconMind
Drupal 8.0.6 contains the fix to this bug. Upgrade to that and you'll be fine.

The rest of your question is a generic Composer support request which doesn't belong in this issue.

siliconmind’s picture

@bojanz
But I can't update to 8.0.6 from 8.0.3 with composer. If I just do composer update it fails with error:

The directory 'tests' in package 'behat/mink' does not exist.

Am I missing something?

bojanz’s picture

8.0.3 is Composer-broken, you can either update core without Composer (by manually downloading the tarball), or apply the patch from this issue and then update via Composer.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.