Background to the Composer Initiative
Many organizations are moving toward a GitOps-based approach to managing software, and the way that Mautic was configured from the Composer perspective was previously suboptimal for organizations who need to manage Mautic installation and deployment with Composer.
This also made it very difficult to apply patches - whether from Mautic or from the organization themselves - in a way that is commonly accepted as best practice.
Two other Strategic Initiatives - Mautic Next Generation and the Mautic Marketplace - depend on significant changes to our architecture for being able to decouple plugins and themes and also have them managed independently.
We announced the Composer Initiative as a Strategic Initiative in November 2020 and work started to determine how to move Mautic toward a more future-friendly configuration.
What we have done
This project has been led by Nick Veenhof from Dropsolid and we are extremely grateful for his knowledge and time in making this initiative a reality. Also, big thanks to Rahul Shinde, John Linhart, and Dennis Ameling for their support in testing, reviewing, and suggesting improvements; and to the Drupal project from which we have taken much inspiration!
Three things were kept in mind when deciding how to execute this project:
- Making the developer experience as smooth as possible
- Enabling a phased approach to decoupling from core
- Following established best practices
There are several key things to be aware of now that we have mostly completed this project.
- While we have ‘technically’ decoupled the app directory, all plugins, and themes into separate repositories, you will still find them located in the original folders in github.com/mautic/mautic at this stage:
<ol> <li>This approach allows for a smooth development process as all the files and folders that you see in Mautic are in the same repository.</li> <li>In the future, we may consider removing some plugins that are not widely used from Core and enabling users to selectively install them via the marketplace.</li> <li>Those plugins will, at that point, become maintained by a separate Tiger Team.</li> <li>The mirror repositories are read-only, pull requests should be made against <a href="https://github.com/mautic/mautic">https://github.com/mautic/mautic</a>, not the mirrors - you will receive a reply from the bot if you attempt to make a PR against a mirror.</li> </ol> </li> <li>Whenever a pull request is made which touches any of these files, the changes are automatically pushed down to the read-only mirror repositories thanks to the amazing tool <a href="https://www.subtreesplit.com/">SubTreeSplit</a> by Tobias Nyholm.</li> <li>We now have a composer.json file in /app (as well as in all plugin and theme directories) which is used to build Mautic when installing with Composer.</li> <li>We now have the Recommended Project repository - <a href="https://github.com/mautic/recommended-project">https://github.com/mautic/recommended-project</a> and the scaffold - <a href="https://github.com/mautic/core-composer-scaffold">https://github.com/mautic/core-composer-scaffold</a> which allows you to manage dependencies and move files outside the web root directory if you wish to do so.</li>
What happens when you build Mautic
As before, you can still pull down Mautic and use the composer install command to install dependencies. This will now be much faster thanks to the upgrade to Composer 2.
You will notice that we now have a requirement on mautic/core-lib - this is the /app folder. We also now pull in all of the plugins and themes individually however in this first phase, we are telling Composer to use the files which it finds in mautic/mautic rather than looking elsewhere for the files - this is a precursor to being able to move some of this outside of the core.
We have also added some configuration settings and we set the correct paths for the different types of resources we are pulling in - the app directory, plugins, and themes.
Within the app folder, we have an additional composer.json file (in fact, all plugins and themes also now have a composer.json file) which has some settings relating to the scaffolding.
How do you use the recommended project?
This recommended project template provides a starter kit for managing your Mautic dependencies with Composer.
Usage
Note: The instructions below refer to the global composer installation. You might need to replace composer with php composer.phar (or similar) for your setup.
After that you can create the project:
composer create-project mautic/recommended-project:4.x-dev some-dir --no-interaction
With composer require ... you can download new dependencies to your installation.
cd some-dir
composer require mautic/mautic-saelos-bundle:~2.0
The composer create-project command passes ownership of all files to the project that is created. You should create a new git repository, and commit all files not excluded by the .gitignore file.
What does the template do?
When installing the given composer.json some tasks are taken care of:
- Mautic will be installed in the public-directory.
- Autoloader is implemented to use the generated composer autoloader in vendor/autoload.php, instead of the one provided by Mautic (public/vendor/autoload.php).
- Plugins (packages of type mautic-plugin) will be placed in public/plugins/
- Themes (packages of type mautic-theme) will be placed in public/themes/
- Creates public/media directory.
- Creates environment variables based on your .env file. See .env.example.
Updating Mautic Core
This project will attempt to keep all of your Mautic Core files up-to-date; the project mautic/core-composer-scaffold is used to ensure that your scaffold files are updated every time mautic/core is updated. If you customize any of the "scaffolding" files (commonly .htaccess), you may need to merge conflicts if any of your modified files are updated in a new release of Mautic core.
Follow the steps below to update your core files.
- Run composer update mautic/core --with-dependencies to update Mautic Core and its dependencies.
- Run git diff to determine if any of the scaffolding files have changed. Review the files for any changes and restore any customizations to .htaccess or others.
- Commit everything all together in a single commit, so the public will remain in sync with the core when checking out branches or running git bisect.
- In the event that there are non-trivial conflicts in step 2, you may wish to perform these steps on a branch, and use git merge to combine the updated core files with your customized files. This facilitates the use of a three-way merge tool such as kdiff3. This setup is not necessary if your changes are simple; keeping all of your modifications at the beginning or end of the file is a good strategy to keep merges easy.
FAQs
Should I commit the contributed plugins I download?
Composer recommends no. They provide arguments against but also workarounds if a project decides to do it anyway.
Should I commit the scaffolding files?
The Mautic Composer Scaffold plugin can download the scaffold files (like index.php, .htaccess, …) to the public/ directory of your project. If you have not customized those files you could choose to not check them into your version control system (e.g. git). If that is the case for your project it might be convenient to automatically run the mautic-scaffold plugin after every install or update of your project. You can achieve that by registering @composer mautic:scaffold as post-install and post-update command in your composer.json:
"scripts": {
"post-install-cmd": [
"@composer mautic:scaffold",
"..."
],
"post-update-cmd": [
"@composer mautic:scaffold",
"..."
]
},
How can I apply patches to downloaded plugins?
If you need to apply patches (depending on the project being modified, a pull request is often a better solution), you can do so with the composer-patches plugin.
To add a patch to Mautic plugin foobar insert the patches section in the extra section of composer.json:
"extra": {
"patches": {
"mautic/foobar": {
"Patch description": "URL or local path to patch"
}
}
}
How do I specify a PHP version?
This project supports PHP 7.4 as the minimum version, however, it's possible that a composer update will upgrade some package that will then require PHP 7+ or 8+.
To prevent this you can add this code to specify the PHP version you want to use in the config section of composer.json:
"config": {
"sort-packages": true,
"platform": {
"php": "7.4"
}
},