Note: modman, the tool that is the subject of this article, is for *nix or Mac OS X only.
As an agency, most of our development at Classy Llama has typically been done in a self-contained context; one site, one codebase, one VCS repository. Even when a particular piece of functionality was reused, it tended to be directly copied from point A to point B and be re-tooled along the way.
If you’re a Magento developer, chances are better than average that your version control workflow is similarly straightforward. (Because chances are better than average that either you work in an agency context, or you manage one or more Magento sites for a single business.) What product developers – like those heroes who create hosts of Magento extensions that make our lives easier – know is that workflow quickly becomes more complicated when you’re developing functionality that must work across multiple sites and even multiple versions of the platform. When creating a distributable extension, your end deliverable is that extension’s code and nothing else. But you still have to develop it within a working Magento codebase – multiple in fact, presuming you want it to be compatible with multiple Magento versions.
You might find yourself with a similar need for your version control workflow, even if product development is not your area. As agencies mature, we tend to value more and more the efficiency gain from packaged functionality that’s easily reusable. And if you’re an in-house developer, imagine a scenario where you manage two different brand sites but need to simultaneously build the same feature for both, or perhaps version 2.0 of your site is in the works but a fancy new piece of functionality needs to go up ASAP. Many scenarios can lead to the need for rapidly deploying and testing one extension in different contexts.
We developers can come up with some embarrassingly half-baked solutions to challenges like this because we want to keep our focus on what we’re creating, not pesky issues like manageable workflow. The good news is that such workflows can be dead simple when you equip yourself with the right tool. And in this case, the right tool is modman, a lightweight program created by Colin Mollenhour.
Note: The focus of this article is on version control workflow across multiple codebases. It is not comprised of tips on making your code more universal/distributable.
Note the Second: This article also presumes that you are using version control in your development. If you aren’t . . . we were all there once! Don’t beat yourself up; just start using a VCS. Here at Classy Llama, we use git.
Let’s get down to it and define our scenario. We’re developing a useful extension that we’ll call, unimaginatively, MyShop_UsefulExtension. And for whatever reason, it does not belong to one particular site, but must be tested on several. Our VCS repository will contain only the extension code:
app/ code/ community/ MyShop/ UsefulExtension/ etc/ config.xml Model/ Observer.php design/ frontend/ base/ default/ layout/ usefulextension.xml template/ usefulextension/ etc/ modules/ MyShop_UsefulExtension.xml skin/ frontend/ base/ default/ usefulextension/
. . . and our challenge is how to keep full working Magento codebases synced with this code while we develop. Our VCS itself makes it easy to have multiple running working copies of the code, of course, but what makes Magento and platforms like it a special challenge is that all of these files need to be distributed throughout the main codebase instead of being contained in one place. How do we make sure our own code is simultaneously isolated for version control and also plugged into all the right places so we can actually run it?
We could perhaps solve this problem by creating a meticulous list of paths for our VCS to ignore, in which case our repository root could coincide with the root of the Magento site codebase itself. But this could end up a bit daunting to maintain, and there would always be the possibility of accidentally committing a file that isn’t actually part of our code. (Not to mention that if the codebase where you want your extension deployed is itself under version control, this option goes immediately out the window.) modman has a better way.
modman takes information about the repository that contains your module (git and Subversion are supported) and takes care of both updating your local copy and merging its files into the main codebase.
The program was written specifically with Magento in mind, but it can be used for any platform with similar requirements. Visit the GitHub page for easy installation instructions:
Once we’ve taken care of installing modman, we need to prepare our extension to utilize it. This is as simple as adding a file called “modman” to our root, containing mappings between the files/directories in our repository and their respective locations in Magento:
app/code/community/MyShop/UsefulExtension app/code/community/MyShop/UsefulExtension app/design/frontend/base/default/layout/usefulextension.xml app/design/frontend/base/default/layout/usefulextension.xml app/design/frontend/base/default/template/usefulextension app/design/frontend/base/default/template/usefulextension app/etc/modules/MyShop_UsefulExetension.xml app/etc/modules/MyShop_UsefulExetension.xml skin/frontend/base/default/usefulextension skin/frontend/base/default/usefulextension
The left path on each line is the path to the file or directory relative to our repository root. The right path indicates where this file or directory should be copied to in the main codebase. With an extension structured as straightforward as ours, these are conveniently the same.
With the modman file in placed and pushed to the repo, all that’s needed in our Magento codebase is to initialize modman and kick off the clone/copy of our extension:
cd /path/to/web/root modman init modman clone MyShop_UsefulExtension [email protected]:MyShop/usefulextension.git
The above commands result in the extension being cloned into “MyShop_UsefulExtension” in a special directory called “.modman”. By default, the files as specified in the manifest file are actually symlinked into the main codebase rather than being copied directly.(Make sure you follow the installation instructions and enable symlinks for templates in the Magento admin.) This has two major advantages: First, already deployed files will stay in sync as you develop without the need for redeployment. And second, broken symlinks can easily be identified and removed in the event you delete files from your extension.
Here’s the view from our web root directory:
.modman/ MyShop_UsefulExtension/ app/ skin/ app/ code/ community/ MyShop UsefulExtension -> ../../../../.modman/MyShop_UsefulExtension/app/code/community/MyShop/UsefulExtension ...
The “init” and “clone” commands should be run in every codebase where you need to develop and/or test your extension. As you work and push new changes, keep each codebase updated with the following:
modman update MyShop_UsefulExtension
The above will pull your latest changes from the repository and re-deploy files as specified in the “modman” manifest.
It’s really that simple. With these basic commands, you can smoothly proceed with the development of a self-contained extension in as many contexts as you need.
modman has a few more useful tricks you’ll find it helpful to know. Additional commands can be passed directly to git or Subversion by including them after the modman command, such as the following, which clones a specific branch initially:
modman clone MyShop_UsefulExtension [email protected]:MyShop/usefulextension.git --branch develop
You can also tell modman to perform the deployment of symlinks into the main codebase without bothering to update the extension working copy first by using the “deploy” command. (A common need when you’ve just added new paths to the “modman” file.)
modman deploy MyShop_UsefulExtension
I mentioned above that one benefit of using symlinks was easy clean-up of deleted module components. modman has a command specifically for this purpose: “clean”, which will find leftover symlinks from previous deployments and remove them.
In certain circumstances, you may find it desirable for your extension files to be directly copied into the Magento codebase instead of symlinked. (For example, as a handy way of installing your final extension on a given site.) The “–copy” flag can be used with any command that typically performs the file deployment:
modman clone --copy MyShop_UsefulExtension [email protected]:MyShop/usefulextension.git
Just take note that the “clean” command will become useless when files/directories have been deployed via copy, as there will now be no broken symlinks to be identified if you should delete a path from your manifest file later.
A final tip on using modman for your Magento development: It’s important to use the appropriate degree of specificity for paths in the “modman” manifest file. It’s fairly obvious that we wouldn’t want to simply include the path “app/code” in our manifest file. This would result in that entire directory being wiped out in our main codebase, in favor of the contents of our extension! However, using the example structure we’ve established above, it would seem reasonable to include the generalized path “app/code/community/MyShop”. But imagine a scenario where you’ve created two modman-compatible extensions under the same vendor namespace and want to deploy them both to the same codebase. The “MyShop” directory can’t be symlinked from both. That’s why you’ll notice in my example manifest file that I’ve used the more specific “app/code/community/MyShop/UsefulExtension”. Always use paths appropriately specific to the extension; paths that no other module should touch. modman will create the correct intermediate directories where needed.
When you need to develop an extension in a packaged, distributable manner, you’re likely to have headaches enough ahead of you from the development alone. Finding an efficient way to deploy your work across these workspaces and keep it in sync doesn’t need to be one of those headaches. Colin Mollenhour has provided us a fantastic tool to meet that challenge.
Learn more about the program at the modman wiki.