Auto package configuration for Symfony

Recently, I decided to write a custom installer (Composer plugin) for my own packages instead of going with Symfony Flex (which I still use of course). In this article I'll explain why. For me, it made configuration management a lot easier so I wanted to share my experiences.

Thanks to Symfony Flex we can spend less time on package configuration and focus more on building applications and libraries. Flex operates as a Composer plugin that executes so called recipes to copy package configuration and routing, add sections to .env and .gitignore and more.

As a developer you can contribute to Flex by creating a pull request on the symfony/recipes or symfony/recipes-contrib repository for any package you like to be auto configured. All you have to do is create a manifest file and provide the configuration files you like to be installed.

When you create the pull request it is checked by the symfony-flex-server bot and one of the authorized reviewers reviews your changes. Once the pull request is approved by the reviewer, it can be merged.

Great to have such a tool. However, there are also some downsides to this approach. For instance, even with good average response times it can take a while before your recipe or update is merged and publicly available and you have limited control over whether the recipe will eventually be merged.

The reason pull requests can not be merged without a reviewer is that one of the goals of Flex is being a reliable source that offers high quality packages, which is a reasonable policy.

I think open discussions are useful but I personally don’t like the idea that I need to ask and wait for approval for every change in my configuration.

Other (minor) drawbacks are the fact that versions and configuration files are managed in a separate repository and recipes depend on the recipe server.

For instance recently when the server was unreachable my packages were installed without the recipes being executed. Not a big issue as you can still copy or create the files yourself, but it made me wonder if I really need my package configuration to be installed from a separate server.

And regarding version management: when you release a new version requiring a different configuration, make sure you create a new sub folder inside your recipe and have it approved and merged before you bump your package version or users might experience failing installations.

Example versioned package configuration

In order to leverage control you have the possibility to use the copy-from-package directive. You still need a hosted, versioned and approved recipe, but at least you can keep part of the configuration inside your library.

You can also set up your own recipe server to further increase control but this comes with the cost of maintaining a separate hosted environment.

Because I desire full control over the configuration I ship with my packages, like updates to be immediately available and want the configuration version to always be in sync with the currently installed version and not depend on a recipe server, I decided to create a small Composer plugin myself that allows you to put the configuration inside your package next to your code.

My packages are bundled with an installer that does the following.

  1. Detect the type of project (i.e. Symfony 3.4 / 4.x)
  2. Copy files from .install/<projectType>/ to your project
  3. [WIP] Add sections to files like .env and .gitignore
  4. Allow you to exclude specific packages from installation
  5. Allow you to disable the installer completely
Example composer install output

You can find the resulting installer here.

Again, I do like Flex and recommend anyone to use it but I just want to point out the fact that Flex is not the only possible solution for auto configuration. Composer allows you to easily write or use any other plugins for configuring your packages. The installer mentioned here is just a basic example.