Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-17652 - Update composer and Symfony for Drupal 8 #10694

Merged
merged 18 commits into from
Aug 12, 2017

Conversation

dsnopek
Copy link
Contributor

@dsnopek dsnopek commented Jul 18, 2017

Work in progress PR for https://issues.civicrm.org/jira/browse/CRM-17652

Remaining tasks

  • Require civicrm/civicrm-packages as a normal composer package

@civicrm-builder
Copy link

Can one of the admins verify this patch?

@totten
Copy link
Member

totten commented Jul 18, 2017

jenkins, ok to test

composer.json Outdated
"name": "civicrm/civicrm-core",
"description": "Open source constituent relationship management for non-profits, NGOs and advocacy organizations.",
"type": "library",
"authors": [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for drafting this. TBH, though, there've been a lot of contributors, and there's a more complete list in CONTRIBUTORS.txt, contributor-key.yml, and release-notes/*.md. I'd like to avoid a fourth one. ;) For composer.json, maybe just list "CiviCRM LLC" or "civicrm.org ". (If a it really needs human, then maybe the current core team.)

Copy link
Contributor Author

@dsnopek dsnopek Jul 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intended to be humans per the composer documentation, but it's optional and we could even omit it, but pretty much all libraries whose composer.json files I've looked at provide it.

Looking at Symfony's composer.json, they actually put the project lead and then an entry for the "Symfony Community". That's not quite right per the docs, but we could do something similar here? If that's OK with you, I can update my PR!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that idea perhaps having the Core team + community, i think the idea is these are the people actively maintaining the thing

Copy link
Contributor

@mglaman mglaman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dsnopek! I was hoping to jam on this earlier, but took advantage of my vacation to vacation, instead :P

@@ -104,7 +104,8 @@ public function register($prepend = FALSE) {
}
$civicrm_base_path = dirname(dirname(__DIR__));

require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';
// @todo: need some way to check if we should register vendor or not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to check if a required class exists, and if it does not then load the autoloader?

We could check if \Composer\Autoload\ClassLoader exists. In the generated autoloader_real.php the randomly named class has

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

So if that exists, we know an autoloader has been bootstrapped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we could do class_exists() on a class from a CiviCRM dependency. I think I'd prefer something more direct, though, like checking if the vendor directory exists, which it shouldn't if installed via composer as opposed to from a tarball... Lemme try that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pushed a new commit that checks for the local vendor autoload, and loads it if it's there

@@ -123,7 +124,8 @@ public function register($prepend = FALSE) {
);
$include_paths = implode(PATH_SEPARATOR, $include_paths);
set_include_path($include_paths . PATH_SEPARATOR . get_include_path());
require_once "$civicrm_base_path/vendor/autoload.php";
// @todo: need some way to check if we should register vendor or not
//require_once "$civicrm_base_path/vendor/autoload.php";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

composer.json Outdated
"symfony/process": "~2.5.0",
"psr/log": "1.0.0",
"symfony/finder": "~2.5.0",
"symfony/config": "^2.5.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can keep ~ but use || to allow different? so ~2.5 || ~2.8 to compatibility with Drupal. But also, as stated in StackExchange.. 2.5 is outdated and not receiving releases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well ~2.5 would allow 2.8 because there isn't the last .0 on there. We probably actually should do ~2.5 || ~3.0 to be compatible with Drupal 8.4.x but I haven't tested with 8.4.x yet

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yeah. https://semver.mwl.be/#?package=symfony%2Fprocess&version=~2.5%20%7C%7C%20~3.0&minimum-stability=stable that looks like it'd be the trick (for also supporting 8.4.x)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa, that link is amazing! Thanks for sharing that :-)


// @todo: need some way to check if we should register vendor or not
//require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';
if (file_exists($composer_autoload)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional is a good idea, although I'm wondering if we might actually need to check both locations like https://github.com/civicrm/cv/blob/v0.1.27/bin/cv#L9

Reason: for better or worse, Civi has two bootstrap processes:

  • CMS-first (typical case; ex: a page-request hits Drupal, which then boots Civi by loading civicrm.settings.php and CRM_Core_Config::singleton())
  • Civi-first (less typical case; ex: request hits extern/rest.php, extern/ipn.php, bin/cli.php, or cv; this reads civicrm.settings.php and then boots CMS via CRM_Utils_System_*::loadBootStrap())

In the second scenario, the classloader needs to be available.

Speculation: this should be fine as long as Civi+CMS behavior are convergent -- they both say require_once vendor/autoload.php for the same copy of autoload.php.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. So, the code should probably be changed to look first for the local vendor directory first (will be present in a non-composer based install), but if it's not there, then look for a top-level vendor directory (will be present in a composer-based install).

I'll take a look! I first need to figure out a good way to test (trying bin/cli.php seems like it'd be the easiest?) and see the failure when using a Civi-first entry point, and then I can try that code change and see if it fixes it.

Thanks for the info :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed some changes that get bin/cli.php bootstrapping Drupal 8 (or at least not crashing when trying to do so). It required creating a settings_location.php file because the default logic for finding the Drupal config directory in civicrm.config.php doesn't work with civicrm-core installed by composer. I don't know if there's a sane way to fix that, since I don't know what all the cases in there are for and I don't want to break something

@dsnopek
Copy link
Contributor Author

dsnopek commented Jul 21, 2017

I finally got around to testing with Drupal 8.4.x -- the composer change described above in the thread with @mglaman works!

However, there were some additional changes required, because there was some stuff added in Symfony 2.6 which deprecated some Symfony 2.5 methods, and of course, the deprecated methods are removed in 3.x. So, I had to change some code around building the service container, and push the minimum Symfony dependency up to 2.6. Hopefully, that's acceptable? If not, I can make a separate branch/PR for supporting Drupal 8.4, but 8.4 will be release on October 4th, so it's coming up pretty quick

But after all that, I got it working on Drupal 8.4 :-)

@totten
Copy link
Member

totten commented Jul 21, 2017

@dsnopek nice work

Regarding the version bump to 2.6, that works for me. Two caveats:

  • I was a little worried about future developers running composer update (with the intention of updating one package but actually updating all), and that would be hard to spot, so CRM-17652 - composer.lock - Add unit test to redflag policy change dsnopek/civicrm-core#1
  • An extension like this could have stale references to setFactory(Class|Service|Method)... but it's not a widely known technique in our community, and that was the only example I could find in the universe of published extensions, and that extension tends to follow an evergreen attitude ("you should always be on latest 4.7.x"). So carry on. :)

@dsnopek
Copy link
Contributor Author

dsnopek commented Jul 21, 2017

An extension like this could have stale references to setFactory(Class|Service|Method)...

Ah, yeah. Well, that'll continue to work in any Symfony 2.x version (those methods are still there but deprecated), but that'll fail when using that extension with Symfony 3.x, ie. with Drupal 8.4. So, that extension won't break right away, and maybe the developer will pay attention to the deprecation notices :-)

@seamuslee001
Copy link
Contributor

@dsnopek David i just want to check that you were able to enable other modules through the GUI once CiviCRM had been installed is that correct?

@dsnopek
Copy link
Contributor Author

dsnopek commented Jul 22, 2017

@seamuslee001 Yes! I reported that worked on this comment on the JIRA ticket - I've written some crazy large comments on that issue, so I don't blame you for not noticing that bit of information :-)

@jackrabbithanna
Copy link
Contributor

How awesome is this! Fantastic @dsnopek really appreciate your time with this...So how do I test this...Do I just apply the patch to an already working installation, or do I need to use civibuild to build CiviCRM against master + this PR ? Are their any steps for applying this for testing that we should be aware of?

@dsnopek
Copy link
Contributor Author

dsnopek commented Jul 23, 2017

It's the same process as I originally posted in JIRA and on Stack Exchange (but I have been evolving the gist which is the steps to replace composer require civicrm/civicrm-core until all this is committed and the issues around assets and what's committed in the repo are fixed).

Here's the steps again:

  1. Download and install Drupal 8.3.5 (or the latest dev of Drupal 8.4.x!)
  2. Go into the root directory in the shell and run these commands to install CiviCRM via composer (one day this will just be composer require civicrm/civicrm-core): https://gist.github.com/dsnopek/56311dbea347874e75180883efabb620
  3. If you use Apache, remove the vendor/.htacess file. This is a security measure from Drupal, which prevents resources like CSS/JS being loaded. This will need some collaboration with the Drupal project to figure out a proper solution for because removing this file altogether is a bad idea on production. See: https://www.drupal.org/node/2896308
  4. Go into the /modules directory and do git clone https://github.com/dsnopek/civicrm-drupal.git --branch composer-library
  5. Go to the "Extend" page (/admin/modules and install the CiviCRM module
  6. Clear drupal cache via Drush (drush cr
  7. Log out and log back in again per CRM-19878
  8. CiviCRM works!

I don't know if anyone other than me has tested these steps yet, so I'd really appreciate any feedback on them!

@dsnopek
Copy link
Contributor Author

dsnopek commented Jul 25, 2017

Hrm. I merged the master branch (because there was a conflict) and it's failing in Jenkins in a way I don't totally understand. Any advice on how to fix it?

@seamuslee001
Copy link
Contributor

Hi @dsnopek I would recommend that you rebase your branch against civicrm's master branch with git rebase -i /master then do git push composer-library -f

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 3, 2017

@seamuslee001 Hm, I'd normally not rebase on a branch that was pushed remotely. However, if that the normal process for CiviCRM PRs, I can certainly do that!

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 3, 2017

Rebased! Hopefully tests will start working again :-)

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 3, 2017

And we're back to passing. Yay! :-)

@KarinG
Copy link
Contributor

KarinG commented Aug 5, 2017

Hi @dsnopek - thanks for all your work on this! I went through the steps you listed - above - and 💯 x 👍 !

I've got a functional (freshly baked) Drupal 8.3.6; CiviCRM 4.7.22; I've been able to:

  • install Drupal Telephone module and add a Telephone field to a Content Type (all via the GUI)
  • install our iATS Payments Extension via the CiviCRM Extension interface: drupal8.local/civicrm/admin/extensions?reset=1 (Add New)
  • process a LIVE (fake VISA) payment w/ iATS (in CiviCRM)
  • install webform module and webform bootstrap module
  • submit a webform

Thank you & Merci!

@seamuslee001
Copy link
Contributor

@totten i feel like with Karin's comment this has had plenty of testing now and seems sane

@KarinG
Copy link
Contributor

KarinG commented Aug 5, 2017

Just to clarify - I followed the exact steps in: #10694 (comment)

* @return void
*/
protected function requireComposerAutoload() {
$civicrm_base_path = dirname(dirname(__DIR__));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure you can use

$civicrm_base_path = dirname(__FILE__, 2);
$top_path = dirname(__FILE__, 5);

Would be good to include a comment clarifying what's magic about the 5-th parent directory (and/or use a Drupal method to discover Drupal root, if that's what that is).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's neat.

According to http://php.net/dirname , the second argument was added in PHP 7. We'll be stuck with multiple dirname()s for a while.

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 6, 2017

Thanks, @KarinG! I'm super glad it worked :-)

@xurizaemon Whoa! How is it possible that I never knew that dirname() had a 2nd argument? Thanks for the tip. I'll update the code and add some comments as suggested (probably tomorrow).

I don't think we can use a Drupal method to discover the Drupal root because we could end up here through an alternate entrypoint before Drupal is bootstrapped (ex. cli.php like @totten describes in this comment) and, at some point in the future, some other CMS could be composer-based and this same code would still need to find the top-level vendor directory which will be in the same place relatively, so this way is more generic.

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 7, 2017

I just pushed a commit with the changes suggested by @xurizaemon!

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 8, 2017

Hrm. It looks like the tests are failing because the version of PHP that's running the tests doesn't support the 2nd argument to dirname() - so, I'll have to revert that!

@totten
Copy link
Member

totten commented Aug 12, 2017

I think these changes are better in than out. @dsnopek , do you still want the "WIP" label on here?

Aside: In the past, we've encountered unexpected issues when touching this area (esp. involving tarball builds), so I'd like to do a quick trial-run of generating+installing tarballs before merging. So far, civihydra passes for D7+WP. Having a couple issues with latest Backdrop+Joomla, but I think they're tangential. Will post again when I've resolved those.

@jackrabbithanna
Copy link
Contributor

jackrabbithanna commented Aug 12, 2017 via email

@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 12, 2017

I think these changes are better in than out. @dsnopek , do you still want the "WIP" label on here?

@totten Like I said on the JIRA issue, I think this is mergable in it's current state. There's still more that should be done to improve the installation process, but we can address that in follow-ups. So... I'll remove the "WIP" label!

@dsnopek dsnopek changed the title (WIP) CRM-17652 - Update composer and Symfony for Drupal 8 CRM-17652 - Update composer and Symfony for Drupal 8 Aug 12, 2017
@jackrabbithanna
Copy link
Contributor

Yep we have two separate verification tests, it's definitely a huge improvement for the issue. It's got my vote

@totten
Copy link
Member

totten commented Aug 12, 2017

OK, I've confirmed that my testing issues on Backdrop+Joomla were unrelated.

Let's merge this!

@totten totten merged commit a1c16b9 into civicrm:master Aug 12, 2017
@dsnopek
Copy link
Contributor Author

dsnopek commented Aug 12, 2017

Woohoo! Thanks, Everyone! :-)

@KarinG
Copy link
Contributor

KarinG commented Aug 12, 2017

Jippie! What's next? It would be aswesome if we can civibuild create dmaster --cms-ver 8.3.6 ahead of the upcoming Sprints @totten!

@totten
Copy link
Member

totten commented Aug 14, 2017

@KarinG IIRC, it has been possible to say civibuild create d8master or civibuild create mybuild --type drupal8-demo --cms-ver 8.3.6 for quite a while. That calls the download.sh and install.sh from drupal8-demo.

Those scripts need to be updated, though. They match the original file-layout of the D8 port. Now that we're making progress toward composer-based distribution, the scripts should instead use composer for setup.

@KarinG
Copy link
Contributor

KarinG commented Aug 14, 2017

Hi @totten - sorry - yes that's what I meant - would you be able to update those scripts by the time the Sprints come around? I got things to work following the steps outlined above but it's a lot of steps/long process; it would be awesome if you could update your buildkit scipts.

@konadave
Copy link
Contributor

I was able to install into a drupal-composer/drupal-project based site. Follow the instructions above from the project root, not Drupal root. Then...

cd web
ln -s ../vendor
chmod 0775 sites/default

That got it to install, though it was broken; no menu, no style, etc. Go to http://www.yourdomain.com/civicrm/admin/setting/url?reset=1 and set the first edit control (there's no label displayed) to http://www.yourdomain.coml/vendor/civicrm/civicrm-core and save.

I haven't done extensive testing but so far it seems to be working fine and I'm able to install other modules.

@jackrabbithanna
Copy link
Contributor

@konadave so for it to work currently, you want to install Drupal 8 "like normal", that is not with composer....then follow the steps that David S. has provided.

the reason that the css, js etc... doesn't work, is because with a standard composer based install, the website doc root is in <project_root>/web ... basically the website docroot and the project root are not the same directory. CiviCRM is then placed in <project_root>/vendor/..... and you can't set the Resource URL to point to the Civi installation, because it is out of the website docroot....

Further work will be required in CiviCRM Core to make this work with D8 installed in the beginning with composer

@konadave
Copy link
Contributor

@jackrabbithanna I have it working using the steps I outlined. The symlink puts the vendor directory in docroot.

@jackrabbithanna
Copy link
Contributor

@konadave sorry I guess I didn't read your comment well the first time....thanks for documenting that...Not sure if that should become the "set" method or if something else should be developed, if so we should make another jira issue and pr about that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants