How write a Symfony Flex recipe for a new bundle?
Asked Answered
C

1

17

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?

Capernaum answered 28/10, 2019 at 16:49 Comment(1)
It's not an easy process. Make sure it is worth your time just to save a bit of config time. github.com/symfony/recipes/blob/master/README.rstIndia
E
30

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.

Edmundoedmunds answered 28/10, 2019 at 17:46 Comment(7)
Thanks for extended description. So basically there is no way to include it in the bundle itself? And since my package is a private package, it is not possible to use symfony flex (since I would need to publish the recipe and probably also the package) without having to do extra configuration on the projects in the first place.Capernaum
Thanks or the clarification. It is what I've been looking for.Intermediate
It's a shame this kind of documentation is found on Stack Overflow and not in the actual Symfony docs. That's what corporate money does to your open source projects, they mingle it to death. Thanks for the summary though!Bakehouse
@HubertNNN, hello we are in 2021 and now it's possible to do your own recipe for your private repository 😁 ! Symfony Blog newsDerivative
Yup, @Floran. I'm waiting to have some time to update this answer to mention and explain this, to have it ready before 5.4/6.0 are released. Maybe tomorrow.Edmundoedmunds
@yivi, very cool ! It's a pretty new feature so a little more explanation on it will be appreciable 😁 I already setup my own private recipe server for my company. If you need some help for the edit, I'm here !Derivative
@Floran, finally I went a bit longer on the "private recipes" feature and the new "serverless" flex recipes, and posted it on a different answer here. Check it out if you want.Edmundoedmunds

© 2022 - 2024 — McMap. All rights reserved.