Why does composer removes my dependencies on deploy? - php

I'm having an issue with composer.
I'm working with git in a local environment. I'm the only one developer.
When I need some more dependencies (or need to change some versions), I edit the composer.json and run composer install locally.
Everything's fine.
Then, when everything works locally, I commit my changes (including composer.json and composer.lock) and push to my production server.
A post-receive script updates the sources and runs a composer install on the remote server.
What is expected :
Composer should install the new dependencies according to the composer.lock file.
I should be happy.
What happens :
Composer is angry :
Warning: The lock file is not up to date with the latest changes in
composer.json. You may be getting outdated dependencies. Run update to
update them.
Composer removes all dependencies.
My production is broken.
I have a heart attack
I have to log in to my server via ssh and run a composer update to make things work fine, but I know that a composer update is not recommended on a production server.
Here's the output of the post-receive composer's section :
composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
- Removing guzzle/guzzle (v3.9.3)
- Removing symfony/event-dispatcher (v2.7.1)
- Removing geoip/geoip (v1.15)
- Removing pimple/pimple (v3.0.0)
- Removing cocur/slugify (1.1.x-dev)
- Removing bentools/url (0.2)
- Removing bentools/simplexmlextended (1.2.0)
Generating autoload files
What am I doing wrong ?
Thanks,
Ben

This warning
Warning: The lock file is not up to date with the latest changes in composer.json, you may be getting outdated dependencies, run update to update them.
occurs when the md5sum of your composer.json differs from the one stored in the composer.lock:
{
"hash": "b15ed9405e8547867f74973ce8add172",
"packages": [ ... ]
}
Make sure your composer.json and composer.lock are identically with your local ones (compare their md5sums). I suspect that something in your deploy chain is not updating them correctly.
Make sure you added your dependencies locally with the require command:
composer require new/package ~2.5
or if composer.json was edited manually at least run
composer update new/package
after that for every additionally added package to ensure that it is added to your composer.lock properly.
Another approach:
run composer update --lock in production. This will update the hash in your lock file but won't upgrade your vendors.
Then run composer install to install the vendors from your comoser.lock.

When I need some more dependencies (or need to change some versions), I edit the composer.json and run composer install locally.
That's wrong. You can edit composer.json and then must run composer update, or you let Composer do the internal editing of the json file and just run composer require new/package (optionally with a version).
Either way, you should end up with a changed composer.json and composer.lock file, commit BOTH into your repository, and the expected outcome is that the lock file will contain all packages in the correct versions, which should be installed in production with a regular composer install run.
Note that your workflow is still very dangerous. If you push, and Github is down - how would you get the ZIPs to install?

Related

composer install recognizing updated composer.json file

I am familiar with the concept that, when composer.lock file is present, composer install command runs the packages from this file.
So when I add (manually put a vendor/pkg list) to "require" in composer.json, and run command install then only those packages locked in composer.lock files get installed.
But this understanding of mine got conflicted, when I found composer.lock file being git-ignored by my senior developers.
When any update on composer.json file is pushed to deployment server, command install is being run and it seems to "install" the updated packages.
What got me confusing is, since there's no mention of that newly added package in the composer.lock file in the deployment server, how is it being installed?
I tried the same on my local:
first added vendor/pkg in require of composer.json.
tried running command install.
And got this warning instead:
warning: the lock file is not up to date with the latest changes....
nothing to install or update.
So my question is :
why two different behaviors are being shown?
How are the newly added packages in .json and not in .lock are being installed in the deployment server and not in local?
I have been researching on this for a while, and its bugging me.
Maybe I am getting it wrong. Anyone there to clear this out?
There are a few options:
Add vendors with composer require vendor/pkg
Add in composer.json as you did, but then run composer update vendor/pkg (Running composer update without the package name will update all of them)

Composer install with only composer.lock

I freshly installed a PHP application given with a composer.lock file.
When running composer install, command line tool is still asking for a composer.json.... I don't have.
In composer documentation, it's said that install command first look for a composer.lock and then for a composer.json.
Why composer is still asking for a file it doesn't need to install my dependencies ?
composer install > returns :
Composer could not find a composer.json file
You still need the composer.json file to install or update any dependencies.
Having a composer.lock file means that composer will not search for the latest commits of the dependencies
A few weeks ago on Twitter, I noticed that the OpenCFP project doesn’t have a composer.lock file in it’s repository. “So what,” you might say, “just composer install and away you go. You’ll get the same dependencies, right?”
Wrong.
The point of the lock file is to record the exact versions that are installed so they can be re-installed. This means that if you have a version spec of 1.* and your co-worker runs composer update which installs 1.2.4, and then commits the composer.lock file, when you composer install, you will also get 1.2.4, even if 1.3.0 has been released. This ensures everybody working on the project has the same exact version.
Source: Composer: It's all about Lock File
You must have a composer.json to install dependencies, because it's the file where dependencies theirself are listed. Refer to the documentation.
composer.lock lists dependencies which has already been installed. The composer looks first into it in order to keep versions consistent.
The (documentation states)[https://getcomposer.org/doc/01-basic-usage.md#installing-with-composer-lock]:
running install when a composer.lock file is present resolves and installs all dependencies that you listed in composer.json, but Composer uses the exact versions listed in composer.lock to ensure that the package versions are consistent for everyone working on your project.
If you have lost your composer.json you can reverse engineering your composer.lock. Open it and read all the packages installed, then create a composer.json which requires them. Not every single package will be a direct dependency for your problem: you should identify and remove those which are not.

What are the differences between composer update and composer install?

What are the differences between composer update and composer install?
composer update
composer update will update your depencencies as they are specified in composer.json
For example, if you require this package as a dependency:
"mockery/mockery": "0.9.*",
and you have actually installed the 0.9.1 version of the package, running composer update will cause an upgrade of this package (for example to 0.9.2, if it's already been released)
in detail composer update will:
Read composer.json
Remove installed packages that are no more required in composer.json
Check the availability of the latest versions of your required packages
Install the latest versions of your packages
Update composer.lock to store the installed packages version
composer install
composer install will not update anything; it will just install all the dependencies as specified in the composer.lock file
In detail:
Check if composer.lock file exists (if not, it will run composer update and create it)
Read composer.lock file
Install the packages specified in the composer.lock file
When to install and when to update
composer update is mostly used in the 'development phase', to upgrade our project packages according to what we have specified in the composer.json file,
composer install is primarily used in the 'deploying phase' to install our application on a production server or on a testing environment, using the same dependencies stored in the composer.lock file created by composer update.
When you run composer install it will look for a lock file and install whatever is contained in it, if it can't find one, it'll read composer.json, install its dependencies and generate a lockfile.
When you run composer update it simply reads composer.json, installs the dependencies and updates the lockfile (or creates a new lockfile).
composer install
If composer.lock does exist.
Processes and installs dependencies from the composer.lock file.
If composer.lock does not exist.
Process package installs from composer.json.
Creates the composer.lock file based on the installed packages.
As per: composer help install:
The install command reads the composer.lock file from the current directory, processes it, and downloads and installs all the libraries and dependencies outlined in that file. If the file does not exist it will look for composer.json and do the same.
composer update
Processes dependencies from the composer.json file (installs, updates and removes).
Creates or updates the composer.lock file according to the changes.
As per: composer help update:
The update command reads the composer.json file from the
current directory, processes it, and updates, removes or installs all the
dependencies.
See also: Composer: It’s All About the Lock File
composer install
if(composer.lock existed){
installs dependency with EXACT version in composer.lock file
} else {
installs dependency with LATEST version in composer.json
generate the composer.lock file
}
composer update
composer update = remove composer.lock -> composer install
Why we need 2 commands. I think it can explain by composer.lock.
Imagine, we DON'T have composer.lock and in composer.json, there is a dependency "monolog/monolog": "1.0.*" or "monolog/monolog": "^1.0".
Then, it will have some cases
We working well today with current dependency version (eg:1.0.0) but a few
months later, the dependency update (eg:1.0.1) and it possible have some bug
Another team member may have a different dependency version if they run composer install in a different time.
What if we always use an EXACT version in composer.json such as "monolog/monolog": "1.0.1"?
We still need composer.lock because composer.json only track the main version of your dependency, it can not track the version of dependencies of dependency.
What if all dependencies of dependency also use the EXACT version?
Imagine you begin with ALL dependencies which use the EXACT version then you don't care about composer.lock. However, a few months later, you add a new dependency (or update old dependency), and the dependencies of this dependency don't use the EXACT version. Then it's better to care composer.lock at the beginning.
Besides that, there is an advantage of a semantic version over an exact version. We may update the dependency many times during development and library often have some small change such as bug fix. Then it is easier to upgrade dependency which uses semantic version.
The best difference between composer update and composer install
composer install
To add dependencies you need to add it manually to the composer.json file.
If composer.lock file exists, install exactly what's specificated on this file
Otherwise read composer.json file to look out what dependencies needs to be installed
Write the composer.lock with the information of the project (installed dependencies)
Not any component will be updated with this command.
composer update
To add or remove dependencies you need to add it manually to the composer.json file
The composer.lock file will be ignored
composer.json file dependencies will be installed and updated (if a dependency is not installed it will be downloaded)
If you can't (or don't know how to add or remove a library which is in fact easy,just add the name of the dependency and version in the require property of the file) modify the composer.json file manually or you prefer use the command line instead, composer has special functions for this :
composer require
For example if we want to add a dependency with the command line we will simply execute
composer require twig/twig
composer.json file will be modified automatically and the new dependency will be added
the dependency will be downloaded to the project
composer remove
If you want to remove an unused dependency we will execute simply :
composer remove twig/twig --update-with-dependencies
Twig will be removed with all his dependencies

What if I don't want to do composer update, I just want to use what ever in composer.json and composer.lock

I have an old composer based symfony project, that I just updated with some changes of code. I tested in development everything works fine. I have got issue when deploying the composer asked to run composer.phar self-update to update the composer since the composer is outdated. After that I do the composer.phar install. I get this error -
[RuntimeException]
Your composer.lock was created before 2012-09-15, and is not supported anymore. Run "composer update" to generate a new one.
What if I don't want to update. I am okay this. How can I force it not to update.
The structure of the lock file was changed, and therefor you should upgrade your lock file. You can upgrade your lock file without actually upgrading any dependencies by executing:
composer update nothing
I would suggest you look at the composer.lock file and note any versions that are used there. Then copy these into the composer.json, delete the lock file and run a normal install.
Of course, you do this on a copy of your software to see if all the same versions do appear again.

Should dependencies be deleted from disk automatically after install/update with Composer?

After removing a dependency from composer.json and running install or update, should I expect the files to be removed automatically from disk?
I had to remove them manually, not sure if I am supposed to.
Running a composer update will remove packages you removed from your composer.json.
Since install uses composer.lock instead of composer.json it will not remove packages removed from your composer.json. However, you should get a message that your lock file is out of sync with your composer.json and you should run an update.

Categories