19

As a PHP developer I find myself working with Composer a lot. In the past it was on personal projects and such so I didn't have much problems with it, but now with Laravel 4 it's on project that require deploying and I'm in kind of a struggle to adapt my workflow.

All my projects are git repositories, thus per convention and because it's still quite buggy, like most developers I put the vendor directory in my .gitignore. Now the problem is : I also use Git to deploy to the server, and by all logic the vendor directory is not uploaded as it's not tracked by the repository.

So my question is towards people that have worked with Composer and Git for longer than me : what is the best workflow to keep the server in sync ? How to track the vendor folder without really tracking it ? I tried uploading it every time I update with Composer but some of my vendor folders are quite big and I can't manually upload 30Mb of files every time something updates.

I don't really know, how do you guys work it out ? I tried not ignoring the vendor folder but Git just messes it up, half are recognized as cloned repos and are just ignored anyway, etc.

UPDATE : Note that I'm on a shared host so I don't have access to the server's terminal.

Maxime Fabre
  • 2,252
  • 3
  • 20
  • 24

6 Answers6

9

The best way is to run composer install on the server after updating to the latest code. You should also make sure you commit your composer.lock file, which the server will then use to install (you should not run composer update on the server).

Seldaek
  • 40,986
  • 9
  • 97
  • 77
  • 3
    Well that's the problem : I'm on shared hosting so I don't have access to the server's terminal. – Maxime Fabre Jan 24 '13 at 12:52
  • You should be able to get ssh access fairly easily. – MikeMurko Mar 12 '13 at 02:50
  • @MaximeFabre You can also run [shell commands](http://www.php.net/manual/en/function.exec.php) from php or even use [phpshell](http://phpshell.sourceforge.net/). – PiTheNumber Apr 16 '13 at 07:20
  • 2
    I'm experiencing some pretty long install times, in the 2 minute ballpark. I don't even have that many dependencies - basically just have 2. I'm not sure if installing directly to production is a good idea as it can take your app down for a few minutes while it completes. – kalenjordan Oct 02 '13 at 18:25
  • 3
    With all advantages we can have with composer, deploying a Magento project with composer is really painful. I had a similar issue as the person who ask the question here. I know that Magento is quite special cause of the folder structure. For this reason, I use composer to install on a dev environment, put all into git and deploy. I know that's not the "best practice" or the current ideology but sorry I have to deal with efficiency and not with an additional bottleneck. I see anyway also an advantage to put all in git. I can check if a dependency had changes and prevent problems. My 50cts :-) – Sylvain Rayé Dec 11 '13 at 12:28
  • 2
    @MaximeFabre There's absolutly no need to use shared hosting for anybody, this is for bloody amateurs who want to upload basic HTML, not for serious developers. Get a server! – Sliq Feb 19 '14 at 04:34
  • Why is it important not to run `composer update` on the server? – Jake Wilson Jun 30 '15 at 20:31
  • 1
    @Jakobud because if you do you might end up with different versions of your dependencies in production than you have while developing, and that might introduce new bugs you didn't test against and break your production environment unexpectedly. – Seldaek Jul 01 '15 at 09:23
  • Not if you keep your `composer.lock` file. The purpose of that file is to ensure consistent dependency versions. – Jake Wilson Jul 01 '15 at 20:16
  • 1
    @Jakobud `composer update` ignores the lock file, that is exactly why you should run `composer install` on prod servers. – Seldaek Jul 02 '15 at 09:16
  • @SylvainRayé Watch out for .gitattributes files with ident entries. Git will modify these files on every pull with the latest commit ID. The best way to add the vendor folder to your Git repository is as a collection of [submodules](http://git-scm.com/docs/git-submodule), but Composer makes that difficult. – NobleUplift Sep 08 '15 at 18:26
  • The trouble with this, it seems to me, is that if the package is already installed `composer install` won't update to the version in `composer.lock`. The suggestions below, copying `composer.json` and `composer.lock` to a `tmp/` folder and then installing, definitely work, but it seems bizarre to me that Composer wouldn't have a command to get you synced up with `composer.lock`. – Paul d'Aoust Mar 11 '16 at 22:00
4

Capistrano (or Capifony if you are using Symfony2) is very useful for deployments with composer. You can trigger a deployment remotely and it will run a composer install in isolation so the site remains online until it has been deployed successfully. There are many other benefits such as retaining previous deployments and rolling back, copying old vendors before deployments, compiling assets etc. etc.

gezpage
  • 441
  • 4
  • 11
4

I'm working on something like this in the git post-receive hook on the server. This isn't tested and may be buggy, but you should get the idea.

#!/bin/bash
# get the updated composer.json
git checkout master -- composer.json

# only do this stuff if composer.json is different
# you could check this manually, or with git or cmp
cp composer.json tmp/composer.json

# may take a minute, but won't take the site down
(cd tmp; composer install --prefer-dist)

# this doesn't seem to be atomic
git checkout -f

# switch vendors over
# this isn't quite an atomic operation, but is very close
# you could probably do it with symlinks and "mv -Tf" to make it atomic
mv vendor vendor.old
mv tmp/vendor vendor

rm -r tmp vendor.old

Ideally all of the deploy (i.e. in this case the git checkout and the composer install) except one single mv would happen in isolation, outside of www. This doesn't work if you have untracked files (eg CMS uploads) in your working tree and rely on PHP's __FILE__ not resolving symlinks (due to this PHP bug).

dave1010
  • 15,135
  • 7
  • 67
  • 64
  • Please note: [I've asked the same thing here](http://stackoverflow.com/questions/21721495/how-to-deploy-correctly-when-using-composers-develop-production-switch) AFTER Composer has changed the behaviour of `install` when using `require-dev`. There's bounty on my question. I would kindly ask you to add an answer there as you obviously know what you are talking about :) – Sliq Feb 19 '14 at 04:34
2

This is an old question but in case anybody is looking a solution:

I slightly modify the @dave1010 answer to use git pull instead of git checkout--force

#!/bin/bash
# get only composer files 
git fetch
git checkout origin/master -- composer.json
git checkout origin/master -- composer.lock

# make sure tmp is empty
rm -rf tmp
mkdir tmp

# copy the composer files to tmp
cp -r vendor tmp/vendor
cp composer.json tmp/composer.json
cp composer.lock tmp/composer.lock

# may take a minute, but won't take the site down
(cd tmp; composer install --no-scripts --verbose; cd ..)

# switch vendors over
rm -rf vendor_old
mv vendor vendor_old
mv tmp/vendor vendor

# update your code
git pull

# run again composer install. This time will print 'Nothing to install or update'
# but will execute pre/post scripts & generate autoload files
composer install --optimize-autoloader

There is maybe a better solution using capistrano/composer. But I like mine better.

Mario Campa
  • 4,092
  • 1
  • 26
  • 25
1

You can use something like jenkins to ftp your files over this way you can direct jenkins to run composer install on the jenkins server and then ftp the files over.

This also allows you to ignore the vendor folder.

It does require a build server to be made and you would need to be able to execute commands vs the build server

hanco ike
  • 285
  • 2
  • 14
-1

The key is your composer.lock file. The composer.lock keeps track of exactly what packages (and versions) you have installed. When you deploy, send your composer.lock file up to the production server as well, and simply do a composer update. All the exact same package versions will be installed. With deployment software like Capistrano or Flightplan you can make the composer update step part of the process so it happens automatically.

Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
  • 1
    Post from @Seldaek above suggests not to use composer update on the production server. There are nice explanations here http://stackoverflow.com/questions/21721495/how-to-deploy-correctly-when-using-composers-develop-production-switch – Carlton May 12 '15 at 16:06