Optimize Site Deployments with Drush (DrupalCamp WNY 2011)

Preview:

DESCRIPTION

When a site goes live, are you crossing your fingers or are you confident that everything is configured? Are you looking to manage and optimize site deployments like any other operational process? Do you find it impossible to create development, test and production environments that act the same every time? Do you have a custom set of modules or configurations that you rely on for all your sites?This session will teach you how to optimize your site deployments with open tools such as drush, drush make, features, leveraging software versioning systems such as subversion and git. Beyond these projects, the session will train you to develop your own custom modules for consistent and precise deployments including variables, users, content types, nodes, imagecache presets, menus, blocks, theme configuration, and more.Using these techniques you can automate and optimize your deployment procedures, giving you technical flexibility and saving valuable time.

Citation preview

Optimize Site Deploymentswith Drush

Friday, 2011.10.14Jon Peck, Owner, FluxSauce.com

Audience: Intermediate.

Revision 1.  Licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

Who am I?

• Jon Peck • Founded web application

development firm FluxSauce • Zend Certified PHP Engineer• Web development since 1998• Used Drupal for the last three

years• Worked at ProZ.com for four

Overview

• Why should you script site deployments?• What are drush and drush make, and how can you use

them?• What is features, and does fit your needs?• What are some recommended site deployment strategies? • How can you develop your own strategy?

Why should I script site deployments?

• Reliability• Track changes over time

(including blame) • Support multiple tiers • Manage and optimize

your operations

"Aaahhh!!!", CC BY 2.0 by Evil Erin @ flickr

What is drush?

drush is a command line shell and scripting interface for Drupal.

Site installation status report using drush.

What can you use drush for?

• Manage modules • Manage users• Execute Drupal commands• Manipulate and extract site variables• Execute MySQL queries using Drupal config

Downloading and installing devel in 1.359 seconds.

What is drush make?

A standard recipe for

downloading everything you need for a site

installation."Mom's new pumpkin pie recipe with gingersnaps", CC BY-SA 2.0

by Ann Larie Valentine @ flickr

Scripting a deployment - simplest

1. Get the files (drush make) drush -y make --no-patch-txt "PATH/drush.make" FOLDER

2. Install and configure (drush) cd FOLDERdrush -y site-install --config="PATH/drushrc.ENV.php"

3. Enable modules (drush) drush -y en \  admin_menu\  ctools \...

Scripting a deployment - flexible

/projects/NAME/config - stored in repository • drush.*.php• drush.make• config.ini• install.sh • setup.sh• rebuild.sh

Drupal Deployment Skeleton (MIT license)• http://goo.gl/09JkE• https://github.com/fluxsauce/DrupalDeploySkel

What is features?

What can you use features for?

• Within your site• Using drush

What are features' limitations?

• Imperfect exports• No site variables

without third-party modules

• No theme, block support

• No logic• If you can't do it in

the GUI... "40+296 Hello?", CC BY 2.0 by Bark @ flickr

Use a custom module for complete control.

With hook_install(), you can programmatically: • Create users, roles, permissions• Create and hide blocks• Create content (nodes)• Import content types / CCK • Create vocabularies and terms• Set site variables (drush vget)

Custom module gotchas

• Clear all caches after installing your custom module drush cc all

• Custom modules used like this need a user associated drush -u 1 -y en custom_module

• Changes and updates need to go in hook_update_N within your module

Deployment strategies

• Store everything in a versioning system • Always backup both your scripts and database

first!• Tiered development strategy • Unique database credentials for each tier• When in doubt, rebuild on dev first• Instead of repeating steps, do it in code• Document the process

How can I do this?

• Get drush• Get drush_make• Define your needs.• Build and document your module toolbox• Start small, then scale up

Questions?

"Question mark in Esbjerg", CC BY-SA 2.0 by Alexander Drachmann @ flickr

Thanks!drush • http://drupal.org/project/drush

drush_make • http://drupal.org/project/drush_make

Drupal Deployment Skeleton (DDS)• http://goo.gl/09JkE (gitHub)

Drush Make Generator• http://drushmake.me

permissions_api • http://drupal.org/project/permissions_api

Traditional Development... Practice for Software Development• http://dltj.org/article/software-development-practice/

Contact• jpeck@fluxsauce.com• @FluxSauce• http://fluxsauce.com

Appendix - code examples

Use these snippets to programmatically create:• Creating a user• Roles and permissions• Manipulating blocks• Create content (nodes)• CCK Content Types• Vocabulary• Terms• Site variables• imagecache presets

Creating a user

$roles = user_roles();

$user_data = array(  'name' => 'steve',  'pass' => 'steve',  'mail' => 'jpeck+steve@fluxsauce.com',  'init' => 'jpeck+steve@fluxsauce.com',  'status' => 1,  'roles' => array(array_search('Manager', $roles) => 1),);

$user = user_save('', $user_data);

Roles and permissions

Requires permissions_api module // Administrative role$result = permissions_create_role('Manager');// Permissions$permissions_grant = array(  'access administration menu',  'administer nodes',...  'administer taxonomy',);permissions_grant_permissions('Manager', $permissions_grant);

Manipulating blocks

// Disable "User login"$sql_query  = 'UPDATE {blocks} ';$sql_query .= 'SET status = 0 ';$sql_query .= 'WHERE module = "user" ';$sql_query .= 'AND region = "left" ';$sql_query .= 'AND status = 1 ';$sql_query .= 'AND delta = 0 ';$sql_query .= 'AND theme = "fourseasons" ';$sql_query .= 'LIMIT 1 '; $result = db_query($sql_query);

Create content (nodes)if (!function_exists('node_object_prepare')) {  include_once(drupal_get_path('module', 'node') . '/node.pages.inc');}

// Home$node = new stdClass();$node->type = 'page';node_object_prepare($node);$node->title = 'An excellent title';$node->body = '<p>Hello, world!</p>';$node->teaser = node_teaser($node->body);$node->uid = 1;$node->format = 2; // Full HTML$node->path = 'home';$node->pathauto_perform_alias = FALSE;node_save($node);

CCK Content Types

Export the content type using the GUI and paste the content into a file in module/content_types/

$filename = drupal_get_path('module', $module_name) . '/content_types/' . $content_type . '.cck';// Build form state$form_state = array(  'values' => array(    'type_name' => '<create>',    'macro' => implode('', file($filename)),  ),;drupal_execute('content_copy_import_form', $form_state);

Vocabularymodule_load_include('module', 'taxonomy', 'taxonomy');$t = get_t();

// Create the vocabulary programmatically.$vocab = array(  'name' => 'Medium',  'description' => $t('Storage and/or transmission tools used to store and deliver information or data.'),  'help' => '',  'relations' => 0,  'hierarchy' => 0,  'multiple' => 0,  'required' => 1,  'tags' => 0,  'module' => 'taxonomy',  'weight' => 0,  'nodes' => array('portfolio_item' => 1),);

taxonomy_save_vocabulary($vocab);

Terms// Get the vid of the vocabulary we just created.$vid = db_result(db_query('SELECT vid FROM {vocabulary} WHERE name = "%s"', 'Medium'));

// Create the term programmatically.$terms = array(  'Videos' => 'Full-motion visual presentations of information.',);foreach ($terms as $name => $definition) {    $term = array(      'name' => $name,      'vid' => $vid,      'description' => $t($definition),    );    taxonomy_save_term($term);}

Site variables

drush vget --pipe site_frontpage $variables['site_frontpage'] = 'node/1';

Then in code...

$variables = array();// Front page$variables['site_frontpage'] = 'node/1';

foreach ($variables as $name => $value) {  variable_set($name, $value);}

imagecache presetsExternal file:  $_presets = array();$_presets['galleria_gallery'] = array (...);return $_presets;

Module:

/** * Implementation of hook_imagecache_default_presets(). */function MODULE_imagecache_default_presets() {  global $_presets;  $module_name = 'MODULE';  $filename = drupal_get_path('module', $module_name) . '/defaults/imagecache_presets.inc.php';  include_once($filename);  return $_presets;}