Skip to content
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

lint:container throws an error if dsn is configured as an env variable #303

Closed
knyk opened this issue Jan 20, 2020 · 17 comments
Closed

lint:container throws an error if dsn is configured as an env variable #303

knyk opened this issue Jan 20, 2020 · 17 comments

Comments

@knyk
Copy link

knyk commented Jan 20, 2020

If you want to lint container using lint:container command it throws an error like
Incompatible use of dynamic environment variables "SENTRY_DSN" found in parameters.

caused by another error

The option "dsn" with value "%env(SENTRY_DSN)%" is invalid.

coming from vendor/sentry/sentry/src/Options.php:74

the strange thing is that bundle work fine with dsn from env variable, perfectly clears cache etc.

only linting container throws that error

it is not critical but DSN as env variable is very required thing because if you have many environments you can't just hard code dsn into yaml config

for now we can't run container linter during CI/CD process

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

The root of the issue seems to be here: symfony/symfony#20850 (comment)

it's not a bug for sure, it's what it says, an incompatible use of dynamic environment. You can't inject an env var anywhere. Any place that is reading the value of a parameter at compile time (in a DI ext or a compiler pass) is not compatible with env vars.

But nowhere in this bundle we instantiate the Options class at build time, it's only defined as a service in the DI container. Can you post the stack trace of this linting error, so I can understand why is it being instantiated?

@knyk
Copy link
Author

knyk commented Jan 21, 2020

root@d6b4d38df2eb:/var/www/html# php bin/console lint:container -v

In Compiler.php line 111:
                                                                                       
  [Symfony\Component\DependencyInjection\Exception\EnvParameterException]              
  Incompatible use of dynamic environment variables "SENTRY_DSN" found in parameters.  
                                                                                       

Exception trace:
  at /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php:111
 Symfony\Component\DependencyInjection\Compiler\Compiler->compile() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:762
 Symfony\Component\DependencyInjection\ContainerBuilder->compile() at /var/www/html/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php:67
 Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand->execute() at /var/www/html/vendor/symfony/console/Command/Command.php:255
 Symfony\Component\Console\Command\Command->run() at /var/www/html/vendor/symfony/console/Application.php:1029
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:97
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/console/Application.php:272
 Symfony\Component\Console\Application->doRun() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:83
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /var/www/html/bin/console:44

In OptionsResolver.php line 987:
                                                                         
  [Symfony\Component\OptionsResolver\Exception\InvalidOptionsException]  
  The option "dsn" with value "%env(SENTRY_DSN)%" is invalid.            
                                                                         

Exception trace:
  at /var/www/html/vendor/symfony/options-resolver/OptionsResolver.php:987
 Symfony\Component\OptionsResolver\OptionsResolver->offsetGet() at /var/www/html/vendor/symfony/options-resolver/OptionsResolver.php:823
 Symfony\Component\OptionsResolver\OptionsResolver->resolve() at /var/www/html/vendor/sentry/sentry/src/Options.php:74
 Sentry\Options->__construct() at n/a:n/a
 ReflectionClass->newInstanceArgs() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1144
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1117
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1121
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1623
 Symfony\Component\DependencyInjection\ContainerBuilder->callMethod() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1169
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1117
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1623
 Symfony\Component\DependencyInjection\ContainerBuilder->callMethod() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1169
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1267
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1215
 Symfony\Component\DependencyInjection\ContainerBuilder->doResolveServices() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:1117
 Symfony\Component\DependencyInjection\ContainerBuilder->createService() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:618
 Symfony\Component\DependencyInjection\ContainerBuilder->doGet() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:558
 Symfony\Component\DependencyInjection\ContainerBuilder->get() at /var/www/html/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php:40
 Symfony\Component\DependencyInjection\ExpressionLanguageProvider->Symfony\Component\DependencyInjection\{closure}() at /var/www/html/vendor/symfony/expression-language/Node/FunctionNode.php:50
 Symfony\Component\ExpressionLanguage\Node\FunctionNode->evaluate() at /var/www/html/vendor/symfony/expression-language/Node/GetAttrNode.php:81
 Symfony\Component\ExpressionLanguage\Node\GetAttrNode->evaluate() at /var/www/html/vendor/symfony/expression-language/ExpressionLanguage.php:66
 Symfony\Component\ExpressionLanguage\ExpressionLanguage->evaluate() at /var/www/html/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:191
 Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->checkType() at /var/www/html/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:123
 Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->checkTypeDeclarations() at /var/www/html/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:96
 Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->processValue() at /var/www/html/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:82
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->processValue() at /var/www/html/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php:70
 Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass->processValue() at /var/www/html/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php:46
 Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass->process() at /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php:94
 Symfony\Component\DependencyInjection\Compiler\Compiler->compile() at /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php:762
 Symfony\Component\DependencyInjection\ContainerBuilder->compile() at /var/www/html/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php:67
 Symfony\Bundle\FrameworkBundle\Command\ContainerLintCommand->execute() at /var/www/html/vendor/symfony/console/Command/Command.php:255
 Symfony\Component\Console\Command\Command->run() at /var/www/html/vendor/symfony/console/Application.php:1029
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:97
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/console/Application.php:272
 Symfony\Component\Console\Application->doRun() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:83
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /var/www/html/bin/console:44

lint:container [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command>

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

It seems that some service is triggering the chain of instantiation, I see multiple ContainerBuilder->createService() calls; can you debug those calls and tell me which service chain is being instantiated?

@knyk
Copy link
Author

knyk commented Jan 21, 2020

service Sentry\SentryBundle\EventListener\ConsoleListener is triggering the chain which cause error.
deps looks like
Sentry\SentryBundle\EventListener\ConsoleListener -> Sentry\State\HubInterface -> Sentry\ClientInterface -> Sentry\ClientBuilderInterface -> Sentry\Options
finally during Options class instantiation Symfony\Component\OptionsResolver is fired up by Options's constructor with options declared in Options::configureOptions

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

Ok, so I fear that the issue is not solvable... The listener is used to attach Sentry to console commands, which lint:container is in itself. This means that Sentry is not only being linted but used too, so that's why the error is (incorrectly) triggered.

It's the same vicious cycle that you have when doing cache:clear.

@knyk
Copy link
Author

knyk commented Jan 21, 2020

when doing cache:clear everything works fine. same on running custom application's command. only lint:container has that issue

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

@nicolas-grekas any suggestion here? Is this solvable in any way?

@nicolas-grekas
Copy link

I don't have enough insights to be helpful, a reproducer would be a good start.
Apparently, requiring the package and running the command is not enough.

BTW, installing the package adds a bunch of guzzle+psr+php-http packages... what a mess... :)

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

The suggested transport is Guzzle, but you can replace to use anything you want, Symfony Client included.

To reproduce, probably adding this config and then run lint:container should be enough:

sentry:
  dsn: "%env(SENTRY_DSN)%"

@nicolas-grekas
Copy link

nicolas-grekas commented Jan 21, 2020

To reproduce, probably adding this config and then run lint:container should be enough:

That's what the recipe installs by default - and when I cannot reproduce, so that's not enough.

The suggested transport is Guzzle

It's more than suggested: it's a required dependency of sentry/sdk, via php-http/guzzle6-adapter :(

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

sentry/sdk is a metapackage that has a suggested transport, you can replace it, see #246.

As for the reproduction, it seems strange to me. Which Symfony version are you using? @knyk which version are you using?

@knyk
Copy link
Author

knyk commented Jan 21, 2020

i can confirm that just by installing the bundle i can't reproduce it.
installed on sf4.4 and sf5

error occurs on my application on sf4.4. i'm now trying to reproduce it on fresh installation of symfony

@knyk
Copy link
Author

knyk commented Jan 21, 2020

Ok so problem is when linter finds an error. It throws exception which sentry bundle is trying to send but it can't because of? This is the place i don't know why it can't, probably doing lint:container doesn't build container like it do when doing any other command.

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

Oh understood! So the listener (and in turn Sentry's Options class) is instantiated and fired only when needed, so when there's an error. So if you solve all the errors, the Sentry error goes away; is that correct?

@knyk
Copy link
Author

knyk commented Jan 21, 2020

Correct, but problem is You don't know what errors have to be solved ;)
The question is: should Sentry be informed about an error occurred while linting container?? It is heavy designed to be used with CI/CD process so developer knows well if anything goes wrong.

@Jean85
Copy link
Contributor

Jean85 commented Jan 21, 2020

It's designed to catch any error in console commands too, but I don't know how you could disable this behavior in any way without risking to alter inadvertently the behavior in prod too.

@Jean85
Copy link
Contributor

Jean85 commented Mar 23, 2020

Closing as this seems to be not fixable. I can also add this:

it is not critical but DSN as env variable is very required thing because if you have many environments you can't just hard code dsn into yaml config

Since newer version of Sentry server, you can use the new DSN which does no longer contains secret values, so hardcoding it in the YAML config is now doable.

@Jean85 Jean85 closed this as completed Mar 23, 2020
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

3 participants