This is part 2 of Uberdrupal: from distribution to profile.
In Part I of this post, I wrote about the context that led me investigate ways to speedup the installation of various Drupal websites.
Just as you might grab a napkin to sketch out an idea in your favorite joint or reach out for a pad of paper to test a concept with fellow developers at work, one often needs a fresh Drupal code-base (a Drupal napkin) to test and validate ideas. Practice makes perfect. If only installing a fresh Drupal code-base was as easy as grabbing a paper napkin under the glassy gaze of a disillusioned waitress... Actually, piece of cake! As we will soon see. Sort of.
There are many reasons why you would want to grab a Drupal code-base and start playing with it within seconds. I already mentioned testing concepts or bringing ideas to life. But there's much more: checking out the latest version of a module in an isolated environment, tracking down pesky bugs, comparing the many ways to implement a photo gallery or an animated banner, validating assumptions, etc.
In my case, I was looking for a way to quickly setup a Drupal 6 Ubercart store with some pre-built generic content. As far as I know, there's only one distribution that fits this bill and it's UberDrupal. In fact, UberDrupal does exactly what I want: it creates a Home and About us page and a $10 Example product. That's great! Now then, can I use this distribution's inner workings to create the pages, menus and products I need for my own use case? Yes you can!
The first issue is that UberDrupal's magic is frozen into the distribution (hard-coded if you prefer). The second issue is that with a release date going back to 2010-Oct-19, UberDrupal is, let's face ot, getting old. It was shrink-wrapped in October 2010 with the latest versions of Drupal core & Ubercart available at that time i.e. Drupal 6.19 and Ubercart 2.4. That's not bad per se. In fact, UberDrupal 6.x-1.0-alpha8 will install without a hitch. But wouldn't it be nice if you could upgrade to today's latest versions of Drupal (6.22) and Ubercart (2.7)? Wouldn't it be great if you could add a few of your favorite modules and libraries to the list? And while we're at it, let's be greedy, wouldn't it be awesome if you could have it create the basic products, menus and pages (nodes) that you will otherwise have to generate every time you create a fresh install?
Well, thanks to Ryan Szrama (rszrama), UberDrupal does all that. All we need to do is (1) crack open the distribution, (2) extract the installation profile, (3) change it so it will do exactly what we want it to do. Sounds like we have a plan.
Requirements - Note: each one of those requirements is worth a separate article. Look for more info in the Related content and References & documentation blocks.
OK, here we go!
Now in order to transform the UberDrupal distribution into a self-contained installation profile, we need to make some changes. As mentioned in Part I of this post, a basic installation profile is made up of 3 files. In the present case, these files are: uberdrupal.info, uberdrupal.make and uberdrupal.profile. As you've probably noticed, uberdrupal.info doesn't exist. So let's create it.
; Use semi-colons to add comments. ; Installation profiles are great! name = UberDrupal description = Installs and creates a basic Ubercart store. core = 6.x theme = acquia_proper
Next on our list is drupal-org.make. In this file, you can get a sense of what the original UberDrupal distribution was made of (Drupal core 6.19, etc.). The first thing we need to do is to rename this file to uberdrupal.make. Then replace its contents with what follows.
; This is the installation profile's makefile (the inner one). core = 6.x api = 2 ; CONTRIB MODULES ;projects[name_of_project] = version_number ;projects[name_of_project][subdir] = name_of_subdir projects[cck] = 2.9 projects[cck][subdir] = contrib projects[imagefield] = 3.10 projects[imagefield][subdir] = contrib projects[filefield] = 3.10 projects[filefield][subdir] = contrib projects[imageapi] = 1.10 projects[imageapi][subdir] = contrib projects[imagecache] = 2.0-beta12 projects[imagecache][subdir] = contrib projects[lightbox2] = 1.11 projects[lightbox2][subdir] = contrib projects[skinr] = 1.6 projects[skinr][subdir] = contrib projects[token] = 1.18 projects[token][subdir] = contrib projects[ubercart] = 2.7 projects[ubercart][subdir] = contrib ; THEMES projects[fusion] = 1.12 projects[acquia_prosper] = 1.1 ; PROFILER - 2.0-beta2 ; The following are required by Profiler when you create an installation profile. libraries[profiler][download][type] = "get" libraries[profiler][download][url] = "http://ftp.drupal.org/files/projects/profiler-6.x-2.0-beta2.tar.gz"
Why this content you ask? And why is it formated that way? I won't answer these questions here. But if you must know, watch Dmitri's Drupalcon Chicago presentation. Not only is it informative, it's quite entertaining. Dmitri is simply awesome. If you're in a bit of a hurry, check out Drush Make and Profiler - a brief overview.
Next on our list is uberdrupal.profile. Remember, this is the file that holds the installation script. We need to make one change here. Copy the following code and simply paste it at the top of the file, just below the <? php/ tag.
!function_exists('profiler_v2') ? require_once('libraries/profiler/profiler.inc') : FALSE; profiler_v2('uberdrupal');
Why? Because Drush Make requires this library to generate php code from the makefile (uberdrupal.make). See References & documentation for more background information. If you want to customize the script, go right ahead. It's pretty self-explanatory. For now, I'm going to leave it as is.
There is a fourth file in the uberdrupal directory named ubercart_image.pkg.inc. We don't need to change anything for this one. Just leave it as is.
We have a working installation profile. Now what? The simple answer is: we need a trigger. And then, we need to pull on that trigger. Before we move on, make a tar.gz archive of the uberdrupal directory with the 4 files in it. We will need it later.
The trigger itself is just another makefile. It is the overarching or parent makefile that we will use to call the uberdrupal installation profile.
Create a new text-only file, paste in the following lines and save it as uberdrupal_inst_profile.make. The name could be anything you fancy as long as it ends with .make.
; This is the overarching or parent makefile for the Uberdrupal installation profile. ; It will install Drupal as well as all the projects listed below. core = 6.x api = 2 ; REMINDER: when creating an installation profile, this is the proper place to download Drupal core. projects = drupal ; Calling the profile. projects[uberdrupal][type] = profile projects[uberdrupal][download][type] = get projects[uberdrupal][download][url] = "http://path-to-dir/uberdrupal.tar.gz" ; The following modules will be downloaded into sites/all/modules projects[admin_menu][version] = 1.8 projects[module_filter][version] = 1.6 projects[devel][version] = 1.26
Two quick comments here. First, I like to keep my installation profiles where I can access them from anywhere and from any machine. But you can also keep/store them locally. Just set the URL accordingly.
Second, you'll notice that I'm downloading the admin_menu, module_filter and devel modules. Why here you ask? And the answer is: that's just the way I like to work. See References if you're curious or just ask by posting a comment.
Only one thing left and that is to pull on the trigger. Any volunteers? Assuming your dev environment is drush-make ready (see requirements above):
drush make --prepare-install uberdrupal_inst_profile.make uberd
This command tells Drush to install UberDrupal as per the installation profile's instructions into the uberd directory. Watch the magic and smile. From here on, just do as you would normally do for a regular Drupal install (i.e. go to your website's URL, choose the profile we've just created, and so on...).
If it doesn't work at first, don't be discouraged, just backtrack a few steps and try again, slowly. A little reading always helps. You'll eventually get it right and, like me, you'll soon be jumping up and down, stretching your t-shirt in all directions. And there's nothing silly about that... or is there?