Continuous deployment with Git submodules

We make heavy use of Git submodules to include external projects, such as custom-built components or our very own Joomlatools extensions, in our Joomla projects.

These applications are then continuously tested and deployed. Previously, we used our Composer plugin to install these dependencies but over time, we found this approach lacking:

  1. It's not easy to spread out work over different branches for both the dependencies and the main project: you constantly need to change the composer.json manifest and update or remove packages.
  2. Debugging these installations is hard and they tend to break easily. This is because our Composer plugin is just a thin layer in between Composer and Joomla's installer logic.
  3. The Joomla installer is invoked on every deployment, which will overwrite files and make changes in the database.
  4. No need to publish and manage packages on Packagist.

That's why we decided to use Git submodules in our continuous deployment projects. This solves these problems and more:

  1. The submodules always point to the right commit (or branch/tag), which means the repository state is always correct. No need to uninstall Composer packages and update composer.lock.
  2. Git has all the required logic baked in so deploying the application requires no external tools.
  3. We no longer need to make changes to files: everything is already in place. Database changes can be consistently managed with the database migrations.

In this post we'll show you how we set up your repository with Joomla extensions in submodules.

For this tutorial, we assume you are using the Joomlatools Vagrant box. If you are not, don't worry, the same workflow applies everywhere but some commands could be different.

1. Add the external project as a submodule

  1. Create a new project and step into the newly created directory:

    joomla site:create example
    cd /var/www/example
    
  2. Initialise the Git repository:

    git init
    git config user.email "me@example.com"
    git config user.name "Your Name"
    git add -A
    git commit -a -m "Initial commit"
    
  3. Create a new directory to place the submodules in:

    mkdir -p libraries/submodules
    
  4. In this example, we'll include our Hello World component. Add its remote URL as a submodule:

    git submodule add https://github.com/joomlatools/joomlatools-composer-helloworld.git libraries/submodules/helloworld
    
  5. We want to use v0.0.4 instead of the master branch, so go into the submodule and check out the right tag:

    cd libraries/submodules/helloworld
    git checkout v0.0.4
    
  6. Go back to your main repository and commit the changes:

    cd /var/www/example/
    git commit -a -m "Add the helloworld component as a submodule"
    

Joomla can't use the component until its files are put in the right spot. In this case, we need to make sure Joomla can find the components/com_helloworld and administrator/components/com_helloworld directories.

To do this, we will create symlinks relative to the link name and commit these symlinks into the repository as well. We can do this with the extension:symlink command in the Joomlatools Console.

You need to take proper care to point the --projects-dir option to the right directory. In this case, that is our libaries/submodules directory:

joomla extension:symlink --relative --projects-dir=/var/www/example/libraries/submodules example helloworld

Don't forget the --relative flag!

Verify these changes with git status and make sure the symlinks work by listing the contents of these directories: ls components/com_helloworld/.

Add all symlinks and commit your changes with:

git add -A
git commit "Add symlinks"

3. Install the extension

All that's left is to register the component in Joomla and import required databases in the database. The way you approach this strongly depends of the way you manage database changes.

To continue our example, we'll install it directly using the extension:install command:

joomla extension:install example com_helloworld

Log in to the administrator part of the site and check that Hello World is now listed in the Components menu.

4. Conclusion

That's it, your external components and plugins can now be included into your Joomla applications with no extra effort!

Remember to always update your submodules when changing branches or cloning the repository. In the recent version of Git, you can automate this by enabling the submodule.recurse option:

git config --global submodule.recurse true

We recommend taking a few moments to read through the Git documentation to gain a better understanding of submodules.

Send us your feedback

This is how we are tackling these types of problems right now. If you have any more ideas or want to share your workflow with us, we love to hear from you!

Get in touch through our developer channels on Twitter or Facebook.

Happy Joomla coding!