Efficient development workflows with Composer
About me ● Wolfgang Ziegler ● drupal.org/u/fago ● @the_real_fago at twitter
Wolfgang Ziegler // fago ● More than 10 years of Drupal experience ● Leading force behind the Drupal 8 Entity Field API improvements Maintainer 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/class­loader": "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.drupal­composer.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 create­project  drupal­composer/drupal­project
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 – drupal­module – drupal­theme – drupal­profile – drupal­drush
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/MODULE composer 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": {    "sort­packages": true,  },
Update your modules ● composer update ● Commit the changes in composer.lock !
Update a single module composer update drupal/module composer update drupal/module   ­­with­depdendencies
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 repositories With 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 versions 1.*       =>  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 (prefer­stable) 1.*@dev   =>  1.1.0 (prefer­stable) *         =>  2.0.0
Custom repositories Without 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 create­project  drupal/module path 2.2.0 ● Add in the fork instead upstream
Adding in your fork "require": {   "samson/yt": "dev­BRANCH 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/pathauto composer install ­­prefer­source cd web/modules/contrib/pathauto git checkout ­b your­pathauto­branch
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/master version/2016­CW47 => build/version/2016­CW47 release/2016­CW47 => build/release/2016­CW47
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/phapp­cli
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": {     "preferred­install": {        "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://asset­packagist.org" }], "require": {  "oomphinc/composer­installers­extender": "*", }, "extra": {   "installer­types": ["library"],   "installer­paths": {     "web/libraries/{$name}/": ["vendor:bower­ asset", "vendor:npm­asset"]   } }
Package drunomics/dsk_media composer.json:   "require": {     "bower­asset/dropzone": "~4.2"   }
Usage composer install
Questions?

Efficient development workflows with composer