Thanks to visit codestin.com
Credit goes to github.com

Skip to content

How to handle composer dev bundles in non-dev environments? #346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
inverse opened this issue Apr 3, 2018 · 19 comments
Closed

How to handle composer dev bundles in non-dev environments? #346

inverse opened this issue Apr 3, 2018 · 19 comments

Comments

@inverse
Copy link

inverse commented Apr 3, 2018

I am trying to migrate an existing Symfony 4 application to flex and use the DoctrineMigrationBundle for both dev/test environments which is installed as a dev dependency.

which all looks good in my bundles.php:

    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],

The problem comes when booting:

  PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineFixturesBundle" from namespace "Doctrine\Bundle\FixturesBundle".                  
  Did you forget a "use" statement for another namespace? in /var/www/kitaspot/releases/64/src/Kernel.php:33        

Since this is a dev dependency this is stripped out when deploying to production. What's advised in this situation? Aside including it as a normal dependency.

@xabbuh
Copy link
Member

xabbuh commented Apr 4, 2018

Are you accidentally running your application in the dev or test environment while not having installed the dev dependencies?

@inverse
Copy link
Author

inverse commented Apr 4, 2018

This error was observed when deploying with deployer. I'm pretty sure it's running in prod.

@inverse
Copy link
Author

inverse commented Apr 12, 2018

@xabbuh Any ideas. It's not just this bundle. I have

    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],

All of which are required as dev composer dependencies.

@inverse inverse closed this as completed Apr 19, 2018
@inverse
Copy link
Author

inverse commented Apr 19, 2018

Resolved in: symfony/maker-bundle#151

@Gemorroj
Copy link
Contributor

but not resolved for me :/

export APP_ENV=prod
./composer.phar install --no-dev
Loading composer repositories with package information
Installing dependencies from lock file
Nothing to install or update
Generating autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class
Executing script cache:clear [KO]
 [KO]
Script cache:clear returned with error code 1
!!
!!  In AbstractRecursivePass.php line 122:
!!
!!    Invalid service "App\DataFixtures\AppFixtures": class "App\DataFixtures\App
!!    Fixtures" does not exist.
!!
!!
!!
Script @auto-scripts was called via post-install-cmd

bundles.php

return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
    Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
    Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
    Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
];

composer.json

{
    "type": "project",
    "license": "MIT",
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "ext-apcu": "*",
        "ext-gd": "*",
        "ext-pdo_sqlite": "*",
        "symfony/orm-pack": "*",
        "symfony/console": "^4.0",
        "symfony/flex": "^1.0",
        "symfony/framework-bundle": "^4.0",
        "symfony/lts": "^4@dev",
        "symfony/monolog-bundle": "^3.2",
        "symfony/serializer-pack": "*",
        "symfony/yaml": "^4.0",
        "symfony/dotenv": "^4.0",
        "symfony/validator": "^4.0",
        "nelmio/api-doc-bundle": "^3.2@dev",
        "imagine/imagine": "^0.7@dev"
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0",
        "symfony/var-dumper": "^4.0",
        "symfony/maker-bundle": "^1.4"
    },
    "config": {
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "replace": {
        "symfony/polyfill-iconv": "*",
        "symfony/polyfill-php71": "*",
        "symfony/polyfill-php70": "*",
        "symfony/polyfill-php56": "*"
    },
    "scripts": {
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "conflict": {
        "symfony/symfony": "*"
    },
    "extra": {
        "symfony": {
            "id": "01C0P3TPAW6JF5P0QRKQ1T7WZE",
            "allow-contrib": false
        }
    }
}

@weaverryan
Copy link
Member

See symfony/symfony#27088

nicolas-grekas added a commit to symfony/symfony that referenced this issue Apr 30, 2018
… missing parent class (weaverryan)

This PR was merged into the 3.4 branch.

Discussion
----------

ResolveBindingsPass: Don't throw error for unused service, missing parent class

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no->
| Tests pass?   | yes
| Fixed tickets | symfony/flex#346 (comment)
| License       | MIT
| Doc PR        | n/a

Hey guys!

In short: if you:

A) auto-register a class as a service
B) That class's parent class is missing
C) ... but this class/service is unused

Currently, `ResolveBindingsPass` will fail and throw an exception. The change avoids that - only throwing the exception if the service IS used. This is already done in `AutowirePass`.

The real issue is DoctrineFixturesBundle, where, on production, the bundle (and so, `Fixtures` base class) is not installed, causing a build error, even though these service classes are unused.

Cheers!

Commits
-------

309da92 Avoiding an error when an unused service has a missing base class
@jeroendesloovere
Copy link

I'm having the same problem when trying to deploy to Heroku (which uses "prod" environment").

My setup

composer require --dev doctrine/doctrine-fixtures-bundle

This is the error when trying to deploy using git push heroku:

// ...
remote:        Generating optimized autoload files
remote:        ocramius/package-versions:  Generating version class...
remote:        ocramius/package-versions: ...done generating version class
remote:        Executing script cache:clear [KO]
remote:         [KO]
remote:        Script cache:clear returned with error code 255
remote:        !!  PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DoctrineFixturesBundle" from namespace "Doctrine\Bundle\FixturesBundle".
remote:        !!  Did you forget a "use" statement for another namespace? in /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/src/Kernel.php:32
remote:        !!  Stack trace:
remote:        !!  #0 /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/vendor/symfony/http-kernel/Kernel.php(403): App\Kernel->registerBundles()
remote:        !!  #1 /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/vendor/symfony/http-kernel/Kernel.php(122): Symfony\Component\HttpKernel\Kernel->initializeBundles()
remote:        !!  #2 /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/vendor/symfony/framework-bundle/Console/Application.php(64): Symfony\Component\HttpKernel\Kernel->boot()
remote:        !!  #3 /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/vendor/symfony/console/Application.php(143): Symfony\Bundle\FrameworkBundle\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
remote:        !!  #4 /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/ in /tmp/build_5e6efc0e7a2b34b7ab9951f4681e9656/src/Kernel.php on line 32
remote:        !!
remote:        Script @auto-scripts was called via post-install-cmd
remote:  !     Push rejected, failed to compile PHP app.
remote:
remote:  !     Push failed

And my composer.json contains

    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "doctrine/doctrine-bundle": "^1.8",
        "friendsofsymfony/user-bundle": "^2.1",
        "sensio/framework-extra-bundle": "^5.1",
        "simple-bus/doctrine-orm-bridge": "^5.0",
        "simple-bus/symfony-bridge": "^5.1",
        "symfony/apache-pack": "^1.0",
        "symfony/asset": "^4.0",
        "symfony/console": "^4.0",
        "symfony/dotenv": "^4.0",
        "symfony/flex": "^1.0",
        "symfony/framework-bundle": "^4.0",
        "symfony/lts": "^4@dev",
        "symfony/orm-pack": "^1.0",
        "symfony/swiftmailer-bundle": "^3.2",
        "symfony/translation": "^4.0",
        "symfony/twig-bundle": "^4.0",
        "symfony/web-server-bundle": "^4.0",
        "symfony/webpack-encore-pack": "^1.0",
        "symfony/yaml": "^4.0"
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0",
        "friendsofphp/php-cs-fixer": "^2.10",
        "symfony/browser-kit": "^4.0",
        "symfony/phpunit-bridge": "^4.0"
    },

Solutions, anybody?

It could be solved by moving doctrine/doctrine-fixtures-bundle to require.
But I do not want it to load it in always, just for tests.

=> Does anybody know another solution?

@Pierstoval
Copy link
Contributor

Pierstoval commented Jul 5, 2018

Yes: update your config/bundles.php and make sure the bundle is enabled only in tests & dev

@weaverryan
Copy link
Member

@jeroendesloovere hmm. Indeed, if you look at the error, it looks like it's happening because the DoctrineFixturesBundle is being instantiated during the cache:clear - it's hitting this line: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/3.3/src/Kernel.php#L33

When you install doctrine/doctrine-fixtures-bundle, the recipe should make sure that the bundle is only instantiated in the dev and test environments (you'll see this in config/bundles.php). My guess is that this code IS correct in your setup. I think the problem is that:

  1. Heroku runs composer install
  2. composer install eventually runs bin/console cache:clear

... but, for some reason, the APP_ENV environment variable during this stage is set to dev, when it needs to be set to prod. I'm not sure how this works on Heroku, but you need to make sure that at least this one env var is set to prod so that the cache:clear can run successfully in the prod mode.

@Pierstoval
Copy link
Contributor

Pierstoval commented Jul 5, 2018

Heroku works with env vars, so you need to run heroku config:set APP_ENV=prod and run the same command for every env var. Or you can use the Settings panel on your project's dashboard.

@jeroendesloovere
Copy link

jeroendesloovere commented Jul 6, 2018

Some more information:

I believe cache:clear is not the problem

@weaverryan and @Pierstoval
We can find cache:clear in composer.json. So heroku calls this over here...

    "scripts": {
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },

Local clearing of the cache gives no problems as you can see in the screenshots below.
schermafbeelding 2018-07-06 om 11 35 05
schermafbeelding 2018-07-06 om 11 35 02

src/DataFixtures using DoctrineFixturesBundle classes

Could this be the problem?

I have src/DataFixtures/* classes which use DoctrineFixturesBundle classes.
So I guess the problem has something to do with the following:
--> When running "production" environment, it tries to autowire all classes

# services.yaml
services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false       # Allows optimizing the container by removing unused services; this also means

=> But DoctrineFixturesBundle is not enabled for production environment in config.bundles.php:
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],.
=> So they can not be found indeed...

Possible solution?

Ignore autowiring on DataFixtures if in production environment?

@jeroendesloovere
Copy link

I have tried some things and found the solution.

Using composer require doctrine-fixtures-bundle --dev as described in the docs was so wrong.
It needs to be composer require doctrine-fixtures-bundle.

@rsavinkov
Copy link

rsavinkov commented Aug 30, 2018

@inverse, @Gemorroj, @jeroendesloovere
Did you check environment variable APP_ENV on production environment? Is it "prod"?
I had same problem, and I have just fixed it.

@ChoppyThing
Copy link

ChoppyThing commented Sep 19, 2018

Still getting the same issue for this with deployer:

Script cache:clear returned with error code 255 !! PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "MakerBundle" from namespace "Symfony\Bundle\MakerBundle". !! Did you forget a "use" statement for another namespace? in /releases/1/src/Kernel.php:43 !! Stack trace:

I can't figure out where cache:clear is getting the dev env from. In deployer the env is correctly set to prod. For now i've added debug and the web profiler to "normal" requirements(not dev) but it's weird to have this on a production environnement.

@inverse
Copy link
Author

inverse commented Sep 19, 2018

@ChoppyThing did you set the app env to production for deploy?

For me I hooked in this before deploy/rollback

task('load:env-vars', function () {
    $environment = run('cat {{deploy_path}}/shared/.env');
    $dotenv = new \Symfony\Component\Dotenv\Dotenv();
    $data = $dotenv->parse($environment);
    set('env', $data);
});

@ChoppyThing
Copy link

@inverse I did. I'll try this tomorrow, thanks.

@featuriz
Copy link

featuriz commented Apr 10, 2023

APP_ENV=prod composer update --no-dev -o
doc: https://symfony.com/doc/current/configuration.html#selecting-the-active-environment

@ctsDevel
Copy link

Same problem. bundles.php file is not updated when deploying to prod.

@featuriz
Copy link

featuriz commented Oct 8, 2023

Same problem. bundles.php file is not updated when deploying to prod.

bundles.php file content will be like this,

    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
    Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],

here all means, it will be loaded in all environments.

If you have flex bundle it will automatically update this list, whenever you install or remove a bundle. If not then you have to do it manually.

If the module is missing here, then add it and set the environment accordingly. Refer Symfony Doc for bundles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants