Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How write a Symfony Flex recipe for a new bundle?

I tried to find any documentation about using Symfony Flex but so far no luck.

Almost all docs point to installing a bundle that uses symfony Flex, not how to create a bundle that is using it.

I even tried to reverse engineer some of the packages but again, no luck.

My goal is to generate a default configuration file for my bundle in config/packages/my_bundle.yaml.

What I need to know is where do I need to put it and what env variables (if any) will I have available?

like image 500
HubertNNN Avatar asked Oct 28 '19 16:10

HubertNNN


People also ask

What is Symfony recipe?

Symfony recipes allow the automation of Composer packages configuration via the Symfony Flex Composer plugin. This repository contains "official" recipes for Composer packages endorsed by the Symfony Core Team.

What is flex in Symfony?

Symfony Flex is a Composer plugin that modifies the behavior of the require , update , and remove commands. When installing or removing dependencies in a Flex-enabled application, Symfony can perform tasks before and after the execution of Composer tasks.

Should I use Symfony Flex?

Using Symfony Flex is optional, even in Symfony 4, where Flex is used by default. However, Flex is so convenient and improves your productivity so much that it's strongly recommended to upgrade your existing applications to it.

What is a bundle in Symfony?

A Symfony bundle is a collection of files and folders organized in a specific structure. The bundles are modeled in such a way that it can be reused in multiple applications. The main application itself is packaged as a bundle and it is generally called AppBundle.


1 Answers

What is a Flex Recipe?

Keep in mind that the flex recipe is a separate repository from your package repository, that needs to be hosted separately from the Bundle package.

In the most likely scenario that your is a public bundle/recipe, you'll have to submit your recipe to the "contrib" repository, get it approved and merged, so it's available as a community recipe.

Additionally, it's important to remember that most users will not have the contrib repository enabled by default. So if this is important for installing this bundle, you should tell your users how to do so before they install your recipe (e.g. in your bundle's readme file).

Private Recipes

The other option would be having a private Flex recipe, as described here. The easiest way to generate a private recipe is to follow the same steps that Symfony does. Check this question and its answers for more details: How to generate a private recipe JSON from the contents of a recipe directory?


With that out of the way: Basically, a Flex recipe is a repository with a manifest.json file with specific keys to enable certain "configurators".

The available manifest.json configurators are:

Bundles

Which bundles should be enabled on bundles.php. These are added when the recipe is installed, and removed when the recipe is uninstalled.

{
    "bundles": {
        "Symfony\\Bundle\\DebugBundle\\DebugBundle": ["dev", "test"],
        "Symfony\\Bundle\\MonologBundle\\MonologBundle": ["all"]
    }
}

Configuration

The "configuration" configurator deals with two keys: copy-from-recipe and copy-from-package. The first one can copy files from the recipe repository, the second one copies files from the package repository.

{
    "copy-from-package": {
        "bin/check.php": "%BIN_DIR%/check.php"
    },
    "copy-from-recipe": {
        "config/": "%CONFIG_DIR%/",
        "src/": "%SRC_DIR%/"
    }
}

In this example, a file bin/check.php in the package will be copied to the projects %BIN_DIR%, and the contents of config and src on the recipe package will be copied the corresponding directory.

This is the typical use case to provide default configuration files, for example. From what you ask, this is your stated purpose for wanting to create a flex recipe.

Env Vars

This configurator simply adds the appropriate environment variable values to the project's .env and .env.dist. (Again, these would be removed if you uninstalled the recipe)

{
    "env": {
        "APP_ENV": "dev",
        "APP_DEBUG": "1"
    }
}

Composer Scripts

This configurator adds tasks to the scripts:auto-scripts array from the project's composer.json. The auto-scripts are tasks that are executed every time composer update or composer install are executed in the project.

{
    "composer-scripts": {
        "vendor/bin/security-checker security:check": "php-script",
        "make cache-warmup": "script",
        "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
    }
}

The second part on each line specifies what kind of command it is: a regular PHP script (php-script), a shell script (script), or a Symfony command (symfony-cmd, executed via bin/console).

Gitignore

This will add entries to the project's .gitignore file.

{
    "gitignore": [
        "/phpunit.xml"
    ]
}

A complete example of a manifest.json (lifted from here, as most other examples on this post):

{
    "bundles": {
        "Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle": ["all"]
    },
    "copy-from-recipe": {
        "config/": "%CONFIG_DIR%/",
        "public/": "%PUBLIC_DIR%/",
        "src/": "%SRC_DIR%/"
    },
    "composer-scripts": {
        "make cache-warmup": "script",
        "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
    },
    "env": {
        "APP_ENV": "dev",
        "APP_DEBUG": "1",
        "APP_SECRET": "%generate(secret)%"
    },
    "gitignore": [
        ".env",
        "/public/bundles/",
        "/var/",
        "/vendor/"
    ]
}

Additional configurators

There are two configurators which do not rely on the manifest.json file:

Post-install output.

If a file named post-install.txt exists in the recipe's package, its content is displayed when installation is complete. You can even use styles as defined here, for additional prettiness/obnoxiousness.

Example:

<bg=green;fg=white>                </>
<bg=green;fg=white> Much success!! </>
<bg=green;fg=white>                </>

  * <fg=yellow>Next steps:</>
    1. Foo
    2. <comment>bar</>;
    3. Baz <comment>https://example.com/</>.

This will be presented to the user after the installation is complete.

Makefile

If a file named Makefile exists in the recipe's repository, the tasks defined here would be added to the project's Makefile (creating the Makefile if it didn't exist).

cache-clear:
    @test -f bin/console && bin/console cache:clear --no-warmup || rm -rf var/cache/*
.PHONY: cache-clear

Simple as that. I guess than most packages would not need a makefile command, so this would have much less use than other configurators.

You can read the full documentation here.

like image 193
yivi Avatar answered Sep 22 '22 19:09

yivi