SlideShare a Scribd company logo
Lean Drupal Repositories with
Composer and Drush
by Greg Anderson
Photo by Adam Wyles
2016
Pantheon.io 2
Session Description
Composer is the industry-standard PHP dependency manager that is now in use in Drupal 8 core. This session will show the current best practices for
using Composer, drupal-composer, drupal-scaffold, Drush, Drupal Console and Drush site-local aliases to streamline your Drupal 7 and Drupal 8 site
repositories for optimal use on teams.
We will answer such gripping questions as:
● How do I avoid placing a copy all of the Drupal core and contrib modules into my repository?
● How do I keep my core and contrib modules up-to-date?
● What if I need to customize .htaccess, or some other file?
● Can I work with a "lean" repository, and still seamlessly use a full repository to deploy?
● How do I share Drush aliases with team members, without using another repository, and without making my alias list too long?
● What is a Drush wrapper script, and how can it help me?
● How does Drupal Console fit in to all of this?
● Should I use test fixtures in my Behat tests, or make a copy of the production site database?
These techniques will also be helpful for solo site developers--you never know, the next person who needs to check out, build and test your Drupal site
from scratch might be you!
Pantheon.io
Then create a Git repository:
cd myproject
git init
git add .
git commit -m “My new project”
3
Getting Started with Drupal and Composer
One easy step in Composer:
composer create-project drupal-composer/drupal-project myproject --stability=dev
Install and run with Drush:
cd web
drush qd --db-url=mysql://root@localhost/myprojectdb
Answer “yes” when Composer
asks to remove VCS files, or run
with --no-interaction option
Pantheon.io 4
Preferred Project Structure
webcomposer.json
drupal console
circle.yml
external libraries
behat.yml
behat drush
drupal/core
index.php
custom-installers
drupal-scaffoldmodules
contrib
custom
vendor
Pantheon.io 5
Specifying Project Layout
{
"name": "drupal-composer/drupal-project",
"scripts": {
"drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold",
"post-install-cmd": "sh ./scripts/composer/post-install.sh"
},
"extra": {
"installer-paths": {
"web/core": ["type:drupal-core"],
"web/modules/contrib/{$name}": ["type:drupal-module"],
"web/profiles/contrib/{$name}": ["type:drupal-profile"],
"web/themes/contrib/{$name}": ["type:drupal-theme"],
"drush/contrib/{$name}": ["type:drupal-drush"]
}
}
}
Pantheon.io 6
Renaming Document Root
# Ignore directories generated by Composer
drush/contrib
vendor
docroot/core
docroot/modules/contrib
docroot/themes/contrib
docroot/profiles/contrib
# Ignore Drupal's file directory
docroot/sites/default/files
.gitignore
#!/bin/sh
DOCUMENTROOT=docroot
# Prepare the scaffold files if they are not
if [ ! -f $DOCUMENTROOT/autoload.php ]
then
composer drupal-scaffold
mkdir -p $DOCUMENTROOT/modules
mkdir -p $DOCUMENTROOT/themes
mkdir -p $DOCUMENTROOT/profiles
post-install.sh
{
"extra": {
"installer-paths": {
"docroot/core": ["type:drupal-co
"docroot/modules/contrib/{$name}
"docroot/profiles/contrib/{$name
"docroot/themes/contrib/{$name}"
"drush/contrib/{$name}": ["type:
}
}
}
composer.json
Pantheon.io 7
Scaffold Files
web
drupal/core
scaffold files
modules
contrib
custom
.htaccess
autoload.php
index.php
robots.txt
updates.php
sites
examples.sites.php
default
default.services.yml
default.settings.php
Drupal.org
drupal-scaffold
Pantheon.io 8
Custom Scaffold Configuration
{
"name": "pantheon-systems/drupal-project",
"scripts": {
"drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold",
"post-install-cmd": "sh ./scripts/composer/post-install.sh"
},
"extra": {
"drupal-scaffold": {
"source": "https://github.com/pantheon-systems/drops-8/archive/{version}.tar.gz",
"includes": [
"sites/default/settings.php",
"sites/default/settings.pantheon.php"
]
}
}
}
Pantheon.io 9
Document Root at Project Root
composer.json
drupal console
external libraries
drush
core
index.php
custom-installers
drupal-scaffoldmodules
contrib
custom
vendor
circle.yml
private
Privatesubfolder
Pantheon.io 10
composer.json Relocated to Private Directory
{
"name": "pantheon-systems/drupal-project",
"scripts": {
"drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold",
"post-install-cmd": "sh ./scripts/composer/post-install.sh"
},
"extra": {
"installer-paths": {
"../core": ["type:drupal-core"],
"../modules/contrib/{$name}": ["type:drupal-module"],
"../profiles/contrib/{$name}": ["type:drupal-profile"],
"../themes/contrib/{$name}": ["type:drupal-theme"],
"../drush/contrib/{$name}": ["type:drupal-drush"]
}
}
}
Pantheon.io 11
Updating Code
web
drupal/core
scaffold files
modules
contrib
custom
.htaccess
autoload.php
index.php
robots.txt
updates.php
sites
examples.sites.php
default
default.services.yml
default.settings.php
Drupal.org
drupal-scaffold
composer
update
composer drupal-
scaffold
git pull
Project Files
Only
Scaffold Files
Only
Composer and
Scaffold
Files
Pantheon.io 12
Customizing Scaffold Files
{
"name": "pantheon-systems/drupal-project",
"scripts": {
"drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold",
"post-install-cmd": "sh ./scripts/composer/post-install.sh",
"post-drupal-scaffold-cmd": "cat htaccess-append.txt >> ../.htaccess"
}
}
To patch non-scaffold files, use:
cweagans/composer-patches
Pantheon.io 13
Checking for Security Updates
With Drush
With Composer
$ drush pm-updatestatus
Checking available update data ... [ok]
Checking available update data for Drupal. [ok]
Checking available update data for Token (token). [ok]
Name Installed Version Proposed version Message
Token (token) 7.x-1.2 7.x-1.6 SECURITY UPDATE available
$ composer require roave/security-advisories:dev-master
$ composer require drupal-composer/drupal-security-advisories:7.x-dev
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- drupal-composer/drupal-security-advisories 7.x-dev conflicts with drupal/token[7.1.2].
- Installation request for drupal-composer/drupal-security-advisories 7.x-dev ->
satisfiable by drupal-composer/drupal-security-advisories[7.x-dev].
- Installation request for drupal/token 7.1.2 -> satisfiable by drupal/token[7.1.2].
n.b. Requires git_deploy module if using Composer with
--prefer-source, or if dev modules are used.
Pantheon.io 14
Manage Custom Modules with Composer
webcomposer.json
drupal console
circle.yml
external libraries
behat.yml
behat drush
drupal/core
index.php
custom-installers
drupal-scaffoldmodules
contrib
custom
vendor
Variant
WHY?
Use private modules in
multiple projects.
Pantheon.io 15
Let’s Make a Module!
$ drupal generate:module $ drupal generate:controller
Pantheon.io 16
Customize Module’s composer.json
{
"name": "greg-1-anderson/snazzy",
"type": "drupal-module",
"description": "A Snazzy Module",
"keywords": ["Drupal"],
"license": "GPL-2.0+",
"homepage": "https://github.com/greg-1-anderson/snazzy",
"minimum-stability": "dev",
"support": {
"issues": "https://github.com/greg-1-anderson/snazzy/issues",
"source": "https://github.com/greg-1-anderson/snazzy"
},
"require": { }
}
Pantheon.io 17
Add Our Custom Module to Drupal Project
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/greg-1-anderson/snazzy.git"
}
],
"require": {
"composer/installers": "^1.0.20",
"drupal-composer/drupal-scaffold": "^1.0",
"greg-1-anderson/snazzy": "dev-master"
},
"extra": {
"installer-paths": {
"web/modules/custom/{$name}": ["greg-1-anderson/snazzy"],
"web/modules/contrib/{$name}": ["type:drupal-module"]
}
}
}
Pantheon.io 18
Generate require Section from Existing Site
composer create-project drupal-composer/drupal-project myproject --stability=dev
cd myproject
drush composer-generate @remote
Look up the modules and themes
used on @remote and add them to
the require section of the
composer.json in the cwd.
Pantheon.io 19
Lean Repository Deployment
Push
Request Test
Request Build
Behat
Deploy
Pull Lean Repo
Install
Update
Pantheon.io 20
Add a Project to Circle
A couple of clicks will get
Circle CI building your project.
There are a few credentials
that should also be set up:
● GitHub OAuth Token
● Terminus Machine Token
● SSH Key Pair
Pantheon.io 21
Generate OAuth Tokens for all Services
GitHub Personal Access Tokens Pantheon Machine Tokens
OAuth tokens are getting to be very common; many services provide them.
They work like passwords, but can have limited permissions, and may be revoked.
Pantheon.io 22
Copy OAuth Tokens into CI Envrionment Variables
OAuth Tokens:
Pantheon.io
Prevents ‘composer install’
from failing due to hitting the
GitHub rate limit.
23
Use OAuth Environment Variables in CI
dependencies:
pre:
- composer config -g github-oauth.github.com $GITHUB_OAUTH
- terminus auth login --machine-token=$PANTHEON_MACHINE_TOKEN
circle.yml
Log in to Terminus via machine
token, e.g. to later deploy from
dev to test.
Pantheon.io 24
Create SSH Key Pair Specifically for CI
$ ssh-keygen -C me+mysite-ci@example.com -f my-ci-keyfile
Add Private Key to Circle SSH Permissions Add Public Key to Provider SSH Keys
For linux servers: ssh-copy-id user@isp.com
Pantheon.io 25
Dependency Hell
Bootstrapping Drupal 8 via a global Drush will ONLY WORK if the
dependencies of the two projects are in perfect alignment.
Upgrading one without upgrading the other is dangerous.
Drush Drupal 8
require autoload.php
Bootstrap require autoload.php
Pantheon.io 26
Simple Example of Dependency Hell
class Sub extends Base
{
public function foo()
{
return $this->bar();
}
}
class Base
{
private function bar()
{
…
}
}
class Sub extends Base
{
public function foo()
{
return $this->boz();
}
}
class Base
{
private function boz()
{
…
}
}
FancyLib v1.0.1 FancyLib v1.0.2
Sub.php Sub.php
Base.php Base.php
Semantic Versioning will not save
you!
Two autoloaders that contain multiple
copies of the same library can still fail,
even if both conform to the same
public API.
Pantheon.io 27
Dependency Hell Affects Drupal Console Too
Drupal Console, like Drush, keeps dependencies in sync with the Drupal 8 release with the
same version number. Problems can still occur if versions become mismatched.
Drupal Console Drupal 8
require autoload.php
Bootstrap require autoload.php
Pantheon.io
Place Drush and Drupal Console in Drupal’s composer.json file:
cd /path/to/drupal-8-root
composer require drush/drush:8.*
composer require drupal/console
28
Solution is to Use a Single Autoloader
CRITICAL
Pantheon.io 29
Gentoo’s “Composer Problem”
“ As long as the necessary
require statements are left in
the code (where they
belong), we can ignore
Composer entirely and install
the package with the system
package manager. We set
PHP's include directory for
our users, so require('Class.
php'); already looks in the
right place.https://wiki.gentoo.org/wiki/Project:PHP/The_Composer_problem
Pantheon.io 30
How Could We Fix Things for Gentoo?
One Class.php shared by every application is not going to work!
Make an autoload.php that loaded versioned Class.php files from
a global location?
How would all of the different versions of Class.php be managed?
How would you apply a security update for Class.php?
By the time we have solved all of
these issues, we have pretty much re-
invented Composer.
Pantheon.io
Drush startup now happens in four phases:
31
Drush Startup
Drush Finder Drush Wrapper Drush Launcher Drush Application
Pantheon.io 32
Drush Finder
Responsible for finding the correct Drush to run
- Checks to see if it can find a Drupal site
- If the Drupal site contains a Drush script, use it
- If no Site-Local Drush is found, use global Drush
Does not consider alias files.
PHP Script
named
“drush”
Pantheon.io 33
Drush Wrapper
Optional. Located at the Drupal Root if it exists.
User may customize this script to:
- Add site-specific options (e.g. commandfile locations)
- Turn off global search locations with --local option
- Select the location of the Drush launcher (if non-standard)
If there is no Drush Wrapper, then the Drush Finder will find and
execute the Drush Launcher.
Shell Script
named
“drush.wrapper”
Pantheon.io 34
Drush Launcher
Sets up the PHP operating environment.
- Select php.ini file to use
- Select php executable to use
- Passes info about environment to Drush
The launcher will always use the Drush application located in the
same directory.
Shell Script
named
“drush.launcher”
Pantheon.io 35
Drush Application
Contains all the code that is Drush.
- Load configuration and command file
- Parse site alias files
Might dispatch again, e.g. if site alias is remote.
PHP
Application
named
“drush.php”
Pantheon.io 36
Drush Phar
Bundles all of the code from the Drush application into a single file.
- Does not use Drush Launcher (no PHP executable selection).
- Will run a Drush Wrapper script if one is available.
If a Drush Wrapper or site-local Drush is found, they will be executed
via redispatch. The site-local Drush may be a Phar or a regular
Drush application.
Phar file
named
“drush.phar”
Phar
Pantheon.io 37
Sharing Drush Aliases
cd "`dirname $0`"
private/vendor/bin/drush.launcher 
--local 
--include=../drush/commands 
--alias-path=../drush/aliases 
--config=../drush/config "$@"
drush.wrapper
drush
web
drush.wrapper
aliases
commands
index.php
aliases.drushrc.php
$ cd web
$ drush sa @live
$aliases["live"] = array (
'remote-host' => 'server.isp.com',
'remote-user' => 'www-admin',
'root' => '/srv/www/live.example.com',
'uri' => 'http://example.com',
);
Pantheon.io 38
Behat Driver Enhancement
cd /path/to/drupal-project
composer require drush-ops/behat-drush-endpoint
YES!
Adds behat Drush command
to your site; used to remotely
create content.
Pantheon.io 39
Behat Fixtures
Background:
Given "places" terms:
| name |
| Kingdom of Imaginarium |
| Empire of Fabrication |
And "offices" terms:
| name |
| Grand Poohbah |
| Undersecretary of Things |
| Minister of Ministering |
$ drush behat import --file=fixtures.yml
create_term:
places:
- name: Kingdom of Imaginarium
- name: Empire of Fabrication
offices:
- name: Grand Poohbah
- name: Undersecretary of Things
- name: Minister of Ministering
Option 1:
Use Behat’s built-in “Background”
Option 2:
Create fixtures with behat-drush-endpoint
Deletes and re-creates fixtures for every test; useful
for testing operations that modify or delete terms.
Taxonomy IDs stay constant for every test run.
ALSO (for Drupal 8): drush site-install --config-dir=export-dir
Pantheon.io 40
That’s a Wrap!
Follow me on Twitter for slides and other Composer + Drush updates:
@greg_1_anderson

More Related Content

What's hot (20)

PDF
Fast Paced Drupal 8: Accelerating Development with Composer, Drupal Console a...
Acquia
 
PPTX
Vagrant crash course
Marcus Deglos
 
PDF
Create a Varnish cluster in Kubernetes for Drupal caching - DrupalCon North A...
Ovadiah Myrgorod
 
PDF
Advanced front-end automation with npm scripts
k88hudson
 
PDF
Managing a WordPress Site as a Composer Project by Rahul Bansal @ WordCamp Na...
rtCamp
 
PPTX
How To Set a Vagrant Development System
Paul Bearne
 
PPTX
WordPress + NGINX Best Practices with EasyEngine
NGINX, Inc.
 
PDF
How we maintain 200+ Drupal sites in Georgetown University
Ovadiah Myrgorod
 
PPTX
Ansible
Vladimír Smitka
 
PDF
macos installation automation
Jon Fuller
 
PDF
Big query - Command line tools and Tips - (MOSG)
Soshi Nemoto
 
PDF
Intro to Git for Drupal 7
Chris Caple
 
PDF
Vagrant + Docker provider [+Puppet]
Nicolas Poggi
 
PDF
Docker slides
Jyotsna Raghuraman
 
PDF
Kubernetes Story - Day 2: Quay.io Container Registry for Publishing, Building...
Mihai Criveti
 
PDF
Drupal 8: frontend development
sparkfabrik
 
PDF
Drupal VM for Drupal 8 Dev - MidCamp 2017
Jeff Geerling
 
PPTX
Django via Docker
Brenden West
 
PDF
Puppeteerのお話
Shinji Kobayashi
 
PDF
Virtual CD4PE Workshop
Puppet
 
Fast Paced Drupal 8: Accelerating Development with Composer, Drupal Console a...
Acquia
 
Vagrant crash course
Marcus Deglos
 
Create a Varnish cluster in Kubernetes for Drupal caching - DrupalCon North A...
Ovadiah Myrgorod
 
Advanced front-end automation with npm scripts
k88hudson
 
Managing a WordPress Site as a Composer Project by Rahul Bansal @ WordCamp Na...
rtCamp
 
How To Set a Vagrant Development System
Paul Bearne
 
WordPress + NGINX Best Practices with EasyEngine
NGINX, Inc.
 
How we maintain 200+ Drupal sites in Georgetown University
Ovadiah Myrgorod
 
macos installation automation
Jon Fuller
 
Big query - Command line tools and Tips - (MOSG)
Soshi Nemoto
 
Intro to Git for Drupal 7
Chris Caple
 
Vagrant + Docker provider [+Puppet]
Nicolas Poggi
 
Docker slides
Jyotsna Raghuraman
 
Kubernetes Story - Day 2: Quay.io Container Registry for Publishing, Building...
Mihai Criveti
 
Drupal 8: frontend development
sparkfabrik
 
Drupal VM for Drupal 8 Dev - MidCamp 2017
Jeff Geerling
 
Django via Docker
Brenden West
 
Puppeteerのお話
Shinji Kobayashi
 
Virtual CD4PE Workshop
Puppet
 

Viewers also liked (18)

PDF
Migrating NYSenate.gov
Pantheon
 
PDF
WP or Drupal (or both): A Framework for Client CMS Decisions
Pantheon
 
PDF
Test Coverage for Your WP REST API Project
Pantheon
 
ODP
Start with Drupal CMS
Edeth Meng
 
PDF
How Drupal 8 Reaches Its Full Potential on Pantheon
Pantheon
 
PDF
Testing Your Code as Part of an Industrial Grade Workflow
Pantheon
 
PDF
WordPress at Scale Webinar
Pantheon
 
PDF
Drupal 8 and Pantheon
Pantheon
 
PPTX
Level Up: 5 Expert Tips for Optimizing WordPress Performance
Pantheon
 
PDF
Continuous Integration Is for Teams: Moving past buzzword driven development
Pantheon
 
PPTX
Decoupled Architecture and WordPress
Pantheon
 
PDF
Drupal Performance
Pantheon
 
PDF
WordPress REST API: Expert Advice & Practical Use Cases
Pantheon
 
PDF
Why Your Site is Slow: Performance Answers for Your Clients
Pantheon
 
PDF
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Pantheon
 
PDF
Automating & Integrating Pantheon with JIRA, Slack, Jenkins and More
Pantheon
 
PDF
Best Practice Site Architecture in Drupal 8
Pantheon
 
PDF
Development Workflow Tools for Open-Source PHP Libraries
Pantheon
 
Migrating NYSenate.gov
Pantheon
 
WP or Drupal (or both): A Framework for Client CMS Decisions
Pantheon
 
Test Coverage for Your WP REST API Project
Pantheon
 
Start with Drupal CMS
Edeth Meng
 
How Drupal 8 Reaches Its Full Potential on Pantheon
Pantheon
 
Testing Your Code as Part of an Industrial Grade Workflow
Pantheon
 
WordPress at Scale Webinar
Pantheon
 
Drupal 8 and Pantheon
Pantheon
 
Level Up: 5 Expert Tips for Optimizing WordPress Performance
Pantheon
 
Continuous Integration Is for Teams: Moving past buzzword driven development
Pantheon
 
Decoupled Architecture and WordPress
Pantheon
 
Drupal Performance
Pantheon
 
WordPress REST API: Expert Advice & Practical Use Cases
Pantheon
 
Why Your Site is Slow: Performance Answers for Your Clients
Pantheon
 
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Pantheon
 
Automating & Integrating Pantheon with JIRA, Slack, Jenkins and More
Pantheon
 
Best Practice Site Architecture in Drupal 8
Pantheon
 
Development Workflow Tools for Open-Source PHP Libraries
Pantheon
 
Ad

Similar to Lean Drupal Repositories with Composer and Drush (20)

PDF
Composer tools and frameworks for Drupal
Promet Source
 
PDF
Composer tools and frameworks for drupal.ppt
Promet Source
 
PDF
Composer is the new Drush - Drupal Developer Training (internal)
Exove
 
PDF
Composer & Drupal
drubb
 
PDF
Drupal + composer = new love !?
nuppla
 
PPTX
Exploring composer in drupal 8 with drupal project - salva molina
Salvador Molina (Slv_)
 
PDF
Efficient development workflows with composer
nuppla
 
PDF
Introduction to Composer for Drupal
Luc Bézier
 
PDF
Efficient development workflows with composer
nuppla
 
PDF
Improving your Drupal 8 development workflow DrupalCampLA
Jesus Manuel Olivas
 
PDF
Drupal 8 improvements for developer productivity php symfony and more
Acquia
 
PDF
Modernize Your Drupal Development
Chris Tankersley
 
PDF
Stop making, start composing - Using Composer for Drupal development
kaspergarnaes
 
PDF
Dependency management with Composer
Jason Grimes
 
PDF
Development Setup of B-Translator
Dashamir Hoxha
 
PPTX
drupal ci cd concept cornel univercity.pptx
rukuntravel
 
PPTX
Drupal 8 - Improving your development workflow
valuebound
 
PDF
Drupal8 for Symfony developers - Dutch PHP
Antonio Peric-Mazar
 
PPTX
Managing your Drupal project with Composer
Matt Glaman
 
PPTX
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
Composer tools and frameworks for Drupal
Promet Source
 
Composer tools and frameworks for drupal.ppt
Promet Source
 
Composer is the new Drush - Drupal Developer Training (internal)
Exove
 
Composer & Drupal
drubb
 
Drupal + composer = new love !?
nuppla
 
Exploring composer in drupal 8 with drupal project - salva molina
Salvador Molina (Slv_)
 
Efficient development workflows with composer
nuppla
 
Introduction to Composer for Drupal
Luc Bézier
 
Efficient development workflows with composer
nuppla
 
Improving your Drupal 8 development workflow DrupalCampLA
Jesus Manuel Olivas
 
Drupal 8 improvements for developer productivity php symfony and more
Acquia
 
Modernize Your Drupal Development
Chris Tankersley
 
Stop making, start composing - Using Composer for Drupal development
kaspergarnaes
 
Dependency management with Composer
Jason Grimes
 
Development Setup of B-Translator
Dashamir Hoxha
 
drupal ci cd concept cornel univercity.pptx
rukuntravel
 
Drupal 8 - Improving your development workflow
valuebound
 
Drupal8 for Symfony developers - Dutch PHP
Antonio Peric-Mazar
 
Managing your Drupal project with Composer
Matt Glaman
 
Ran Mizrahi - Symfony2 meets Drupal8
Ran Mizrahi
 
Ad

More from Pantheon (12)

PDF
Drupal Migrations in 2018
Pantheon
 
PDF
Architecting Million Dollar Projects
Pantheon
 
PDF
Streamlined Drupal 8: Site Building Strategies for Tight Deadlines
Pantheon
 
PDF
Getting Started with Drupal
Pantheon
 
PDF
Defense in Depth: Lessons Learned Securing 200,000 Sites
Pantheon
 
PDF
Automate Your Automation | DrupalCon Vienna
Pantheon
 
PDF
Sub-Second Pageloads: Beat the Speed of Light with Pantheon & Fastly
Pantheon
 
PDF
Building a Network of 195 Drupal 8 Sites
Pantheon
 
PDF
Hacking Your Agency Workflow: Treating Your Process Like A Product
Pantheon
 
PDF
Preparing for the Internet Zombie Apocalypse
Pantheon
 
PDF
Content as a Service: What to Know About Decoupled CMS
Pantheon
 
PDF
Drupal 8 CMI on a Managed Workflow
Pantheon
 
Drupal Migrations in 2018
Pantheon
 
Architecting Million Dollar Projects
Pantheon
 
Streamlined Drupal 8: Site Building Strategies for Tight Deadlines
Pantheon
 
Getting Started with Drupal
Pantheon
 
Defense in Depth: Lessons Learned Securing 200,000 Sites
Pantheon
 
Automate Your Automation | DrupalCon Vienna
Pantheon
 
Sub-Second Pageloads: Beat the Speed of Light with Pantheon & Fastly
Pantheon
 
Building a Network of 195 Drupal 8 Sites
Pantheon
 
Hacking Your Agency Workflow: Treating Your Process Like A Product
Pantheon
 
Preparing for the Internet Zombie Apocalypse
Pantheon
 
Content as a Service: What to Know About Decoupled CMS
Pantheon
 
Drupal 8 CMI on a Managed Workflow
Pantheon
 

Recently uploaded (20)

PDF
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
Biography of Daniel Podor.pdf
Daniel Podor
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
Biography of Daniel Podor.pdf
Daniel Podor
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 

Lean Drupal Repositories with Composer and Drush

  • 1. Lean Drupal Repositories with Composer and Drush by Greg Anderson Photo by Adam Wyles 2016
  • 2. Pantheon.io 2 Session Description Composer is the industry-standard PHP dependency manager that is now in use in Drupal 8 core. This session will show the current best practices for using Composer, drupal-composer, drupal-scaffold, Drush, Drupal Console and Drush site-local aliases to streamline your Drupal 7 and Drupal 8 site repositories for optimal use on teams. We will answer such gripping questions as: ● How do I avoid placing a copy all of the Drupal core and contrib modules into my repository? ● How do I keep my core and contrib modules up-to-date? ● What if I need to customize .htaccess, or some other file? ● Can I work with a "lean" repository, and still seamlessly use a full repository to deploy? ● How do I share Drush aliases with team members, without using another repository, and without making my alias list too long? ● What is a Drush wrapper script, and how can it help me? ● How does Drupal Console fit in to all of this? ● Should I use test fixtures in my Behat tests, or make a copy of the production site database? These techniques will also be helpful for solo site developers--you never know, the next person who needs to check out, build and test your Drupal site from scratch might be you!
  • 3. Pantheon.io Then create a Git repository: cd myproject git init git add . git commit -m “My new project” 3 Getting Started with Drupal and Composer One easy step in Composer: composer create-project drupal-composer/drupal-project myproject --stability=dev Install and run with Drush: cd web drush qd --db-url=mysql://root@localhost/myprojectdb Answer “yes” when Composer asks to remove VCS files, or run with --no-interaction option
  • 4. Pantheon.io 4 Preferred Project Structure webcomposer.json drupal console circle.yml external libraries behat.yml behat drush drupal/core index.php custom-installers drupal-scaffoldmodules contrib custom vendor
  • 5. Pantheon.io 5 Specifying Project Layout { "name": "drupal-composer/drupal-project", "scripts": { "drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold", "post-install-cmd": "sh ./scripts/composer/post-install.sh" }, "extra": { "installer-paths": { "web/core": ["type:drupal-core"], "web/modules/contrib/{$name}": ["type:drupal-module"], "web/profiles/contrib/{$name}": ["type:drupal-profile"], "web/themes/contrib/{$name}": ["type:drupal-theme"], "drush/contrib/{$name}": ["type:drupal-drush"] } } }
  • 6. Pantheon.io 6 Renaming Document Root # Ignore directories generated by Composer drush/contrib vendor docroot/core docroot/modules/contrib docroot/themes/contrib docroot/profiles/contrib # Ignore Drupal's file directory docroot/sites/default/files .gitignore #!/bin/sh DOCUMENTROOT=docroot # Prepare the scaffold files if they are not if [ ! -f $DOCUMENTROOT/autoload.php ] then composer drupal-scaffold mkdir -p $DOCUMENTROOT/modules mkdir -p $DOCUMENTROOT/themes mkdir -p $DOCUMENTROOT/profiles post-install.sh { "extra": { "installer-paths": { "docroot/core": ["type:drupal-co "docroot/modules/contrib/{$name} "docroot/profiles/contrib/{$name "docroot/themes/contrib/{$name}" "drush/contrib/{$name}": ["type: } } } composer.json
  • 7. Pantheon.io 7 Scaffold Files web drupal/core scaffold files modules contrib custom .htaccess autoload.php index.php robots.txt updates.php sites examples.sites.php default default.services.yml default.settings.php Drupal.org drupal-scaffold
  • 8. Pantheon.io 8 Custom Scaffold Configuration { "name": "pantheon-systems/drupal-project", "scripts": { "drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold", "post-install-cmd": "sh ./scripts/composer/post-install.sh" }, "extra": { "drupal-scaffold": { "source": "https://github.com/pantheon-systems/drops-8/archive/{version}.tar.gz", "includes": [ "sites/default/settings.php", "sites/default/settings.pantheon.php" ] } } }
  • 9. Pantheon.io 9 Document Root at Project Root composer.json drupal console external libraries drush core index.php custom-installers drupal-scaffoldmodules contrib custom vendor circle.yml private Privatesubfolder
  • 10. Pantheon.io 10 composer.json Relocated to Private Directory { "name": "pantheon-systems/drupal-project", "scripts": { "drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold", "post-install-cmd": "sh ./scripts/composer/post-install.sh" }, "extra": { "installer-paths": { "../core": ["type:drupal-core"], "../modules/contrib/{$name}": ["type:drupal-module"], "../profiles/contrib/{$name}": ["type:drupal-profile"], "../themes/contrib/{$name}": ["type:drupal-theme"], "../drush/contrib/{$name}": ["type:drupal-drush"] } } }
  • 11. Pantheon.io 11 Updating Code web drupal/core scaffold files modules contrib custom .htaccess autoload.php index.php robots.txt updates.php sites examples.sites.php default default.services.yml default.settings.php Drupal.org drupal-scaffold composer update composer drupal- scaffold git pull Project Files Only Scaffold Files Only Composer and Scaffold Files
  • 12. Pantheon.io 12 Customizing Scaffold Files { "name": "pantheon-systems/drupal-project", "scripts": { "drupal-scaffold": "DrupalComposerDrupalScaffoldPlugin::scaffold", "post-install-cmd": "sh ./scripts/composer/post-install.sh", "post-drupal-scaffold-cmd": "cat htaccess-append.txt >> ../.htaccess" } } To patch non-scaffold files, use: cweagans/composer-patches
  • 13. Pantheon.io 13 Checking for Security Updates With Drush With Composer $ drush pm-updatestatus Checking available update data ... [ok] Checking available update data for Drupal. [ok] Checking available update data for Token (token). [ok] Name Installed Version Proposed version Message Token (token) 7.x-1.2 7.x-1.6 SECURITY UPDATE available $ composer require roave/security-advisories:dev-master $ composer require drupal-composer/drupal-security-advisories:7.x-dev ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages. Problem 1 - drupal-composer/drupal-security-advisories 7.x-dev conflicts with drupal/token[7.1.2]. - Installation request for drupal-composer/drupal-security-advisories 7.x-dev -> satisfiable by drupal-composer/drupal-security-advisories[7.x-dev]. - Installation request for drupal/token 7.1.2 -> satisfiable by drupal/token[7.1.2]. n.b. Requires git_deploy module if using Composer with --prefer-source, or if dev modules are used.
  • 14. Pantheon.io 14 Manage Custom Modules with Composer webcomposer.json drupal console circle.yml external libraries behat.yml behat drush drupal/core index.php custom-installers drupal-scaffoldmodules contrib custom vendor Variant WHY? Use private modules in multiple projects.
  • 15. Pantheon.io 15 Let’s Make a Module! $ drupal generate:module $ drupal generate:controller
  • 16. Pantheon.io 16 Customize Module’s composer.json { "name": "greg-1-anderson/snazzy", "type": "drupal-module", "description": "A Snazzy Module", "keywords": ["Drupal"], "license": "GPL-2.0+", "homepage": "https://github.com/greg-1-anderson/snazzy", "minimum-stability": "dev", "support": { "issues": "https://github.com/greg-1-anderson/snazzy/issues", "source": "https://github.com/greg-1-anderson/snazzy" }, "require": { } }
  • 17. Pantheon.io 17 Add Our Custom Module to Drupal Project { "repositories": [ { "type": "vcs", "url": "https://github.com/greg-1-anderson/snazzy.git" } ], "require": { "composer/installers": "^1.0.20", "drupal-composer/drupal-scaffold": "^1.0", "greg-1-anderson/snazzy": "dev-master" }, "extra": { "installer-paths": { "web/modules/custom/{$name}": ["greg-1-anderson/snazzy"], "web/modules/contrib/{$name}": ["type:drupal-module"] } } }
  • 18. Pantheon.io 18 Generate require Section from Existing Site composer create-project drupal-composer/drupal-project myproject --stability=dev cd myproject drush composer-generate @remote Look up the modules and themes used on @remote and add them to the require section of the composer.json in the cwd.
  • 19. Pantheon.io 19 Lean Repository Deployment Push Request Test Request Build Behat Deploy Pull Lean Repo Install Update
  • 20. Pantheon.io 20 Add a Project to Circle A couple of clicks will get Circle CI building your project. There are a few credentials that should also be set up: ● GitHub OAuth Token ● Terminus Machine Token ● SSH Key Pair
  • 21. Pantheon.io 21 Generate OAuth Tokens for all Services GitHub Personal Access Tokens Pantheon Machine Tokens OAuth tokens are getting to be very common; many services provide them. They work like passwords, but can have limited permissions, and may be revoked.
  • 22. Pantheon.io 22 Copy OAuth Tokens into CI Envrionment Variables OAuth Tokens:
  • 23. Pantheon.io Prevents ‘composer install’ from failing due to hitting the GitHub rate limit. 23 Use OAuth Environment Variables in CI dependencies: pre: - composer config -g github-oauth.github.com $GITHUB_OAUTH - terminus auth login --machine-token=$PANTHEON_MACHINE_TOKEN circle.yml Log in to Terminus via machine token, e.g. to later deploy from dev to test.
  • 24. Pantheon.io 24 Create SSH Key Pair Specifically for CI $ ssh-keygen -C [email protected] -f my-ci-keyfile Add Private Key to Circle SSH Permissions Add Public Key to Provider SSH Keys For linux servers: ssh-copy-id [email protected]
  • 25. Pantheon.io 25 Dependency Hell Bootstrapping Drupal 8 via a global Drush will ONLY WORK if the dependencies of the two projects are in perfect alignment. Upgrading one without upgrading the other is dangerous. Drush Drupal 8 require autoload.php Bootstrap require autoload.php
  • 26. Pantheon.io 26 Simple Example of Dependency Hell class Sub extends Base { public function foo() { return $this->bar(); } } class Base { private function bar() { … } } class Sub extends Base { public function foo() { return $this->boz(); } } class Base { private function boz() { … } } FancyLib v1.0.1 FancyLib v1.0.2 Sub.php Sub.php Base.php Base.php Semantic Versioning will not save you! Two autoloaders that contain multiple copies of the same library can still fail, even if both conform to the same public API.
  • 27. Pantheon.io 27 Dependency Hell Affects Drupal Console Too Drupal Console, like Drush, keeps dependencies in sync with the Drupal 8 release with the same version number. Problems can still occur if versions become mismatched. Drupal Console Drupal 8 require autoload.php Bootstrap require autoload.php
  • 28. Pantheon.io Place Drush and Drupal Console in Drupal’s composer.json file: cd /path/to/drupal-8-root composer require drush/drush:8.* composer require drupal/console 28 Solution is to Use a Single Autoloader CRITICAL
  • 29. Pantheon.io 29 Gentoo’s “Composer Problem” “ As long as the necessary require statements are left in the code (where they belong), we can ignore Composer entirely and install the package with the system package manager. We set PHP's include directory for our users, so require('Class. php'); already looks in the right place.https://wiki.gentoo.org/wiki/Project:PHP/The_Composer_problem
  • 30. Pantheon.io 30 How Could We Fix Things for Gentoo? One Class.php shared by every application is not going to work! Make an autoload.php that loaded versioned Class.php files from a global location? How would all of the different versions of Class.php be managed? How would you apply a security update for Class.php? By the time we have solved all of these issues, we have pretty much re- invented Composer.
  • 31. Pantheon.io Drush startup now happens in four phases: 31 Drush Startup Drush Finder Drush Wrapper Drush Launcher Drush Application
  • 32. Pantheon.io 32 Drush Finder Responsible for finding the correct Drush to run - Checks to see if it can find a Drupal site - If the Drupal site contains a Drush script, use it - If no Site-Local Drush is found, use global Drush Does not consider alias files. PHP Script named “drush”
  • 33. Pantheon.io 33 Drush Wrapper Optional. Located at the Drupal Root if it exists. User may customize this script to: - Add site-specific options (e.g. commandfile locations) - Turn off global search locations with --local option - Select the location of the Drush launcher (if non-standard) If there is no Drush Wrapper, then the Drush Finder will find and execute the Drush Launcher. Shell Script named “drush.wrapper”
  • 34. Pantheon.io 34 Drush Launcher Sets up the PHP operating environment. - Select php.ini file to use - Select php executable to use - Passes info about environment to Drush The launcher will always use the Drush application located in the same directory. Shell Script named “drush.launcher”
  • 35. Pantheon.io 35 Drush Application Contains all the code that is Drush. - Load configuration and command file - Parse site alias files Might dispatch again, e.g. if site alias is remote. PHP Application named “drush.php”
  • 36. Pantheon.io 36 Drush Phar Bundles all of the code from the Drush application into a single file. - Does not use Drush Launcher (no PHP executable selection). - Will run a Drush Wrapper script if one is available. If a Drush Wrapper or site-local Drush is found, they will be executed via redispatch. The site-local Drush may be a Phar or a regular Drush application. Phar file named “drush.phar” Phar
  • 37. Pantheon.io 37 Sharing Drush Aliases cd "`dirname $0`" private/vendor/bin/drush.launcher --local --include=../drush/commands --alias-path=../drush/aliases --config=../drush/config "$@" drush.wrapper drush web drush.wrapper aliases commands index.php aliases.drushrc.php $ cd web $ drush sa @live $aliases["live"] = array ( 'remote-host' => 'server.isp.com', 'remote-user' => 'www-admin', 'root' => '/srv/www/live.example.com', 'uri' => 'http://example.com', );
  • 38. Pantheon.io 38 Behat Driver Enhancement cd /path/to/drupal-project composer require drush-ops/behat-drush-endpoint YES! Adds behat Drush command to your site; used to remotely create content.
  • 39. Pantheon.io 39 Behat Fixtures Background: Given "places" terms: | name | | Kingdom of Imaginarium | | Empire of Fabrication | And "offices" terms: | name | | Grand Poohbah | | Undersecretary of Things | | Minister of Ministering | $ drush behat import --file=fixtures.yml create_term: places: - name: Kingdom of Imaginarium - name: Empire of Fabrication offices: - name: Grand Poohbah - name: Undersecretary of Things - name: Minister of Ministering Option 1: Use Behat’s built-in “Background” Option 2: Create fixtures with behat-drush-endpoint Deletes and re-creates fixtures for every test; useful for testing operations that modify or delete terms. Taxonomy IDs stay constant for every test run. ALSO (for Drupal 8): drush site-install --config-dir=export-dir
  • 40. Pantheon.io 40 That’s a Wrap! Follow me on Twitter for slides and other Composer + Drush updates: @greg_1_anderson