Build with Composer - composer-php

In a life cycle of a php project we have
install: composer install
publish: composer push
But, what would be the command to build a php project with composer?

what would be the command to build a php project with composer?
Simply speaking, you build the PHP project. Composer is a utility you can use to manage a PHP projects dependencies. Additionally you can also use it to define your PHP project.
How you build the PHP project is entirely up to you. This is normally dependent of what kind of PHP project that is and how you organize it.
To give an example: Lets consider your PHP project just is the project directory with the composer.json at its root with all the other sub-directories and files.
Composer operates within that directory. So when you want to create a build artifact of that project you do the following:
composer install --no-dev - Prepare the vendor folder with the production dependencies and the autoloader.
composer archive - Create the build artifact.
As you will do this quite often and over and over again you could add a Composer Script named build or similar to put things together:
{
"scripts": {
"build": [
"#composer --no-plugins --no-interaction install --no-scripts --no-dev",
"#composer --no-plugins --no-interaction archive"
]
},
"scripts-descriptions": {
"build": "Build project artifact."
}
}
You can then run:
$ composer build
...
Composer will then output the file-name. By default it should be a .tar file (tarfile, tarball), you can inspect it on the commandline with the tar utility (here gnutar):
$ tar -tvf "$(composer show -sN | sed 's|/|-|')"*.tar | less
And that would be the example. Whatever composer push is, I don't know. It is likely that you have it somewhere in your Composer configuration. So I can't comment on it.
To extend a bit on the given example: I manage most (if not even all) of my PHP projects with Composer. However this is not the full truth. I actually version control them with Git. Looking from a birds perspective, the Git utility is way more leading than the Composer utility. That is for example, that I want to be able to build a specific git revision.
Now Composer is not that bad with Git. It recognizes if the project exists and in case of the composer archive example, it even puts the git revision hash into the file name of the build artifact.
However Composer operates in-tree. That is the place where the development happens as well, so this can easily clash (you don't want the build to remove the development dependencies while you're running tests as well - or afterwards). And even Composer recognizes that the project is managed by Git, it is otherwise a bit dumb as Composer is merely concerned about the dependencies and knows very little about the project itself - it can't just guess how you manage the overall project.
So what then commonly happens is that you still use Composer during the build but you have a dedicated build process and runner that knows the ins and outs of the project and its build.
$ make
is such a runner. Works with a Makefile in the project, e.g.
$ make deploy
knows when it needs to build again. And speaking of PHP projects: It certainly can just rsync to remotes and run smoke-tests to mark the deployment as green (use old, dumb tech and keep it simple).

Related

Get production versions of packages on "composer install"

Since composer was created, it made our life a lot easier. However, running composer install often ends up with so many files that can be useful for development, but just bloat the production server. Shared hosting often has limited inodes, or you must upload the "vendor" folder yourself since composer isn't on the server.
When the vendor folder has 6,000 files+ this is an issue, especially if you have multiple projects with 6,000 files each. And so many of these files are "README.MD" or "TODO". Production servers don't need the dev's "TODO" file.
I tried searching on Google but I can't find any clues, so anyone knows if there is a composer command that will install a production version?
There was a feature request for that, but it was rejected (several times). Right now the best what you can get from Composer is:
composer install --no-dev --prefer-dist
It will skip installation dev packages and prefer dist archives, which usually does not contain tests and other files not necessary to run package on production.
If this is still not enough, you may try to use octolab/cleaner plugin.
composer install --no-dev
The official link:
https://getcomposer.org/doc/03-cli.md#install
If you want to exclude something very specific, you want archive.
https://getcomposer.org/doc/04-schema.md#archive
"archive": {
"exclude": ["*.md", "vendor/**/tests", "/*.test"]
}

Can I run composer update in root folder and update all subfolder composer.json files?

I have a WordPress app that has multiple plugins which are all built with OOP principles using Composer to manage autoloading in each plugin.
Now I'm wondering is it possible to just run
composer install --no-dev
in the project root, and somehow trigger running all the composer installs in the plugins so that the classmap is updated.
This is important when I want to deploy by pulling from a repository and performing the build using some kind of continuous integration.
Or do I need to manually specify in my deploy/build script to perform installation separately for each plugin?
I think that Wordpress still has no real Composer integration, which looks like a shame for everyone (including me) not involved in Wordpress development, but the project might have valid reasons, or it is no simple task (probably both).
That being said: You cannot run Composer in a directory level "one up" and mass-update the subdirectories. But it should only be a task of a simple shell script to iterate over all found directories, and if a composer.json is found inside, to update (or install) the dependencies.
My suggestion (including a random number of bugs) would be:
#!/bin/bash
for dir in {*,subdirA/*,subdirB/*}
do
if [ -d $dir ]
then
pushd $dir
if [ -f composer.json ]
then
composer install
fi
popd
fi
done

Should I use --prefer-dist for production?

When I do composer install on the production system, should I use the flag --prefer-dist?
--no-dev is recommended, since it prevents the installation of packages that are only needed during development. But what is with --prefer-dist? This flag makes that the installed packages are without VCS stuff, as I read in this answer. I assume that I don't need this on a production machine. Am I right?
The dist file (e.g. tar archive) is usually quicker to download than cloning the repository (which is the case when using --prefer-source).
The main difference is that cloning the repository will give you everything, while a lib maintainer can create the dist itself. This means that they might not include the tests in the dist file for instance. That's why people suggest using --prefer-dist, as it might end up downloading less files.
Anyway, --prefer-dist isn't really needed as Composer always defaults to the dist file when downloading a stable dependency. As it's really a bad practice to have unstable dependencies running in production, you probably end up downloading the dist for all packages anyway (unless you use --prefer-source of course).

forcing composer to regenerate autoloads when composer.json of a dependency is changed?

My workflow for developing Symfony bundles is the following:
install Symfony
create a git repo for the new bundle, put a composer.json file in there
require the new package in the top-level composer.json, using #dev version
composer update newpackage => the package is downloaded, using git clone
work on the git clone inside vendors, committing and pushing from it
This is all fine and dandy, but seems to break in one specific case:
if I alter the 'autoload' tag of the already-installed package, it seems that Composer has a hard time taking it into account:
I tried 'composer dumpautoload', and it does nothing
I do not want to remove the composer.lock file, as I do not want other packages to be updated to a newer version, I only want to alter the autoload config of that one package
I tried removing by hand vendor/composer/installed.json, and what happened is that Composer re-downloaded all the vendors and wiped any data which happened to be in there at that moment
The same problem manifested itself when I did alter the autoload section of the package on a separate clone, pushed the changes to git and ran 'composer update mypackage' - although that might have been related to packagist not having received the ping from github.
I can of course alter by hand the composer.lock and vendor/composer/installed.json files, but that seems too hackish. It also does not gives the guarantee that user downloading the package the 1st time will see it working.
Try:
./composer.phar dumpautoload -o
It reads the composer.json files and rewrites all the autoload files which pick up the new paths.
dumpautoload uses the package information from vendor/composer/installed.json and not the individual composer.json files. You need to change the autoload info there, too.
The file installed.json is only being update when you run a
composer update

Different handling of composer update

Me and my team are working on a project that uses Composer for dependency management. There seems to be a difference in how a composer update is handled on several machines (running the same latest build version of Composer), but we can't figure out why.
When my teammate runs a composer update on a dependency it tries to remove a lot of data/nodes from the composer.lock file (like the entire dist and support nodes):
When I run the same update, it tries to re-add all those keys again:
We can't figure out why this is happening. Is this a certain setting?
Update: On further inspection, it appears that the "(dis)appearing" nodes all contain https links, could it have something to do with a (missing) SSL library or something?
It seems that one Composer prefers dist and one prefers source.
Look into ~/.composer/config.json if you defined a preferred install in any of your two composers. Or if you defined different preferred installs in the composer.json.
"config": {
"preferred-install": "dist"
}
You can force composer to use either dist or source with
composer update --prefer-dist
or
composer update --prefer-source
--prefer-source: There are two ways of downloading a package: source and dist. For stable versions composer will use the dist by default. The source is a version control repository. If --prefer-source is enabled, composer will install from source if there is one. This is useful if you want to make a bugfix to a project and get a local git clone of the dependency directly.
--prefer-dist: Reverse of --prefer-source, composer will install from dist if possible. This can speed up installs substantially on build servers and other use cases where you typically do not run updates of the vendors. It is also a way to circumvent problems with git if you do not have a proper setup.

Resources