Efficient development workflows
with Composer
About me
● Wolfgang Ziegler● drupal.org/u/fago● @the_real_fago at
Wolfgang Ziegler // fago
● More than 10 years of Drupal experience● Leading force behind the Drupal 8 Entity
Field API improvementsMaintainer of Typed Data API
● Creator of Rules, Field Collection, Profile2
CEO/CTO of
http://getcomposer.org
What is it?● Dependency manager for PHP● Use and publish packages● Package-metadata:
composer.json● Repository: packagist.org
composer.json{
"name": "drupal/core",
"description": "Drupal is an open source content management....",
"require": {
"twig/twig": "1.15.*",
"symfony/classloader": "2.5.*",
Using a package
composer require guzzle/guzzle
Providing a package● Add composer.json● Tag releases Semantic →
versioning● Add Git repository to packagist.org
Packagist
Using it in project
● Add composer .json● Specify
● Add dependencies"type": "project"
Using it in a project
git clone branch 8.1.x https://git.drupal.org/project/drupal.git
cd drupal
composer install
What happens?
● Reads composer.lock and installs recorded versions
● Downloads code and puts it into ./vendor (or somewhere else)
● Generates a class autoloader
Composer update & locks● composer update
– Update all the dependencies and write new lock file
● composer install
– Apply what's recorded in the lock file
Composer & VCS● Commit composer.json● For projects: Commit
composer.lock● For libraries: Commit
composer.lock for tests● Avoid commit vendor files
Versions & Composer
● Require versions like 2.1.*● composer supports many different
version constraints● Specify allowed versions, not
specific versions
Composer & Drupal Projects
Bye, bye, drush make!
● composer replaces drush make● Support for Drupal modules via:
– https://packagist.drupalcomposer.org
– https://packages.drupal.org/7
– https://packages.drupal.org/8
Project template
http://github.com/drupal-composer/drupal-project
Start a new d8 project
composer createproject drupalcomposer/drupalproject
What does it do?● Adds Drupal into the „web“ dir● Adds folder structure, drush, Drupal
console, …● Custom projects can add more stuff
and/or customize things– Add Drupal modules & themes!
Drupal modules & ./vendor?● Composer package types:
– library
– project
– drupalmodule
– drupaltheme
– drupalprofile
– drupaldrush
Working with a composer-based Drupal
project
composer install all the way!● Do not forget to run composer
install!● After pulling changes, run it!● Best: Add to deployment alias:
composer install && drush updatedb && ...
Adding a module
composer require drupal/MODULEcomposer require drupal/MODULE=1.*composer require drupal/MODULE=1.*@beta composer require drupal/MODULE=1.*@dev
Downloads the module + updates files!
Keep things ordered
"config": { "sortpackages": true, },
Update your modules
● composer update● Commit the changes in
composer.lock !
Update a single module
composer update drupal/module
composer update drupal/module withdepdendencies
Checking installed versions● List all packages:composer show
● List directly added pagckages only:composer show D
Where did it go?
composer show P
Patches● cweagans/composer-patches
"extra": { "patches": { "drupal/foobar": { "description": "URL to patch" } }}
Add custom repositoriesWith composer.json:
"require": { "fago/example": "1.*"}"repositories": [ { "type": "vcs", "url": "http://github.com/fago/example" }]
SemVer branching● Branches:
– 1.0.x– 1.1.x– 2.0.x
● Tags / Releases:– 1.0.0– 1.0.1– 1.1.0– 2.0.0
Composer versions1.* => 1.1.0
^1.0.1 => 1.1.0 (>=1.0.1, <2)
~1.0 => 1.1.0 (>=1.0.0, <2)
~1.0.0 => 1.0.1 (>=1.0.0, <1.1)
1.*@dev => 1.1.0 (preferstable)
1.*@dev => 1.1.0 (preferstable)
* => 2.0.0
Custom repositoriesWithout composer.json:"repositories": [{ "type": "package", "package": { "name": "fago/example", "version": "0.1.0", "source": { "url": "github.com/fago/example", "type": "git", "reference": "0.1.0" } }}]
Patches● cweagans/composer-patches
"extra": { "patches": { "drupal/foobar": { "description": "URL to patch" } }}
Fork & add your fork● Alternative to patch files● Works great with the Github pull
request workflow● composer createproject drupal/module path 2.2.0
● Add in the fork instead upstream
Adding in your fork
"require": { "samson/yt": "devBRANCH as 2.0.0"},"repositories": [ { "type": "vcs", "url": "https://github.com/fago/yt" }],
Keep builds fast
● composer fetches either „dist“ or „source“ packages
● Prefer „dist“ packages for fast builds & cache use!
● Pre-configured in drupal-project
Edit your vendors
rm r web/modules/contrib/pathautocomposer install prefersource
cd web/modules/contrib/pathautogit checkout b yourpathautobranch
Merge conflicts?
composer update lock
● „Nice“ hash in composer.lock● Just merge and resolve it by doing
either
composer scripts "scripts": {
"test": "phpunit web/modules/custom",
"deploy": "drush updatedb y && ...",
},
composer deploy composer test
composer scripts
● Uses vendor binaries!● React on events like
– post-package-install– post-create-project-cmd– ..
● Reference other scripts via @script● Handy for documented developer short-cuts
Deploying composer managed projects!
Avoid committing vendors!● Smaller diffs & pull requests
=> easy to review!● Keeps repositories smaller (only
custom code)● Work with vendor repositories
without submodules
Builds & Deployment
1.Hosting takes care of it 2.Deployment tools like capistrano
or deployer (http://deployer.org)3.Git-based deployments of build-
branches or build-repositories
Git-based deployments● Common in the Drupal world as it
is required by many Drupal hosters
● I like it :-)
Build branches
Never merge build branches back!
master => build/masterversion/2016CW47 => build/version/2016CW47release/2016CW47 => build/release/2016CW47
Build branches
● We keep them in the same repository
● Enables possible future enhancements
Creating builds● PHP-console script for creating
builds● Takes care of updating pre-existing
build branches (think: build/master)● Takes care of tags● Takes care of vendor repositories
phapp cli
● Tool for managing PHP applications
● Not yet many commands besides „phapp build“
● https://github.com/ drunomics/phappcli
phapp build● Custom build scripts via phapp.yml
per project=> Allows adding things like npm
● Just build in place? → phapp build
● Build a branch? → phapp build BRANCH
Deployment updates
● Apply changes after code update● Do not rely on special server
environments!
→ More reliable deployments!
Deployment script tools● composer scripts● Robo● Drush, Drupal console
Add dependencies to the project!
Creating re-usable packages
Why?● Develop re-usable PHP libraries,
e.g. REST clients● Feature modules for kick-starting
development
composer require drunomics/dsk_media
Add your own packages
● Custom repositories at project● Run your own packagist● Use Toran Proxy● Use satis & static files
– Scans your repositories– Re-run after every change
"repositories": [ { "type": "composer", "url": "https://satis.example.com" }],
Edit your code● Use source for your packages
"config": { "preferredinstall": { "drunomics/*": "source", "*": "dist" }}
Issue:Some modules need libraries
Handling libraries & assets● Possible solutions:
– Add them via custom repostories– composer scripts for running bower or
npm on project install– fxp/composer-asset-plugin– ...
asset-packagist.org
Project configuration"repositories": [{ "type": "composer", "url": "https://assetpackagist.org"}],"require": { "oomphinc/composerinstallersextender": "*",},"extra": { "installertypes": ["library"], "installerpaths": { "web/libraries/{$name}/": ["vendor:bowerasset", "vendor:npmasset"] }}
Package
drunomics/dsk_media composer.json:
"require": {
"bowerasset/dropzone": "~4.2" }
Usage
composer install
Questions?