Context
I have a simple Symfony2 project (only command line commands). This project includes an app/config.yml file, containing information used for dependency injection creation.
For example, app/config.yml contains:
github:
token: abcdefgh
And src/Foo/Resources/config/github.yml (services files) contains:
services:
github.client:
class: Github\Client
calls:
- ['authenticate', [%github.token%, null, 'http_token']]
The file app/config.yml is loaded by Application::__construct() function.
When I run app/console mycommand, it uses the defined token.
Needs
I need to be able to run my commands using different configurations.
For now, I replace manually the app/config.yml file, but it's crappy.
To do this, I thought about 2 possible solutions:
Be able to specify another app/config.yml file when I run app/console mycommand --f=app/config2.yml.
Have another configuration file for specific command usage, and use it with app/console mycommand --f=myconfig.yml. The thing is the dependency injection can not work or be updated after the application is run.
I don't know how to do one of this solution (or a third one, no matters). If it's a common behavior, can you point me some documentation or example to do something like this?
It is totally possible by using different environements, check out the doc :
http://symfony.com/doc/current/cookbook/configuration/environments.html
Typically you will specify the environement using --env=myenv.
Related
I use Github Actions workflows for my CI/CD processes for Node and PHP projects.
Within a workflow I clone my repository into Github Actions runner virtual machine. Then in order to run tests within a workflow I have to have the .env file in the cloned repository.
The problem is my .env file is not a part of repository (which is the ubuquitous practice).
To solve the problem I use what I consider a workaround: set up MY_PROJECT_ENV Github Action sercret variable, manually put there the content of my .env file and then dynamically create the .env file within my workflow with Linux console echo "${{ secrets.MY_PROJECT_ENV}}" > .env. This works.
But I would like to know are there other approaches for providing .env files to Github Actions workflows?
There are 3 ways to do this I know by now. I put the answer to my own question a year after in the different question. See there.
For the sake of SO rules and findablity I put here a summary.
You keep your .env file in the repository. Use dotenv actions to read your file into the workflow.
You keep the file out of the repository. Then you have 2 ways of getting .env variables:
2.1. as I wrote in my question above manually copy the file content to the GitHub actions secret variable and then in your workflow create the .env file from that variable.
2.2. Use the GitHub Actions API to create/update the secrets: write the NodeJS script on your machine (chances are you anyway use Webpack, Gulp or the like Node thing so you have Node installed).
The script should read the local .env files and write their content to the GH secrets. Of course you can write a custom console utilty to do this with any language you use in your project.
As easy as this :)
As you know .env doesn't mean to push to the remote repository.
You need to somehow add the environment variables to the machine that you're running the program.
In your case, you can add environment variables by using the .yaml file as below
steps:
- name: Hello Program
run: Hello $FIRST_NAME $LAST_NAME!
env:
FIRST_NAME: Akhil
LAST_NAME: Pentamsetti
for more information please visit github official doc about using the environment variables.
I do the following, which is simple and effective:
Add environment variables (either define them in the yaml file or as secrets) as needed
Keep .env.example in the repository, and run the following at the start of the CI job:
# Create the .env file
cp .env.example .env
# Install dependencies so we can run artisan commands
composer install ...
# generate an APP_KEY
php artisan key:generate
An alternative to this is to commit a .env.ci file to the repository with env vars specific to the CI environment, and run cp .env.ci .env when running tests. Sensitive keys should still be set as secrets.
You can technically provide all of your env vars between secrets / env's in the YAML file and have no .env file, but I like having a random APP_KEY set per test run to ensure there's nothing relying on a specific APP_KEY.
Environment Precedence
As an aside, here's how environment precedence works with Laravel in phpunit tests. This is laravel specific and may come at a surprise as it's not exactly how phpunit alone works outside of Laravel:
Env vars set in phpunit.xml always "win" (this is true in Laravel despite what phpunit's docs say about system env vars taking precedence over phpunit.xml file items)
System environment variations (in GitHub actions, these are ones set as an env var when running commands in the yaml file)
.env file items
Source: I created/run Chipper CI, a CI platform for Laravel.
I have a line in a sample Symfony app that reads:
$seo = $this->get('sonata.seo.page');
However the config.yml file reads:
sonata_seo:
page:
metas:
property: ... etc ...
I've read http://symfony.com/doc/current/service_container.html but I'm not clear how exactly the get('sonata.seo.page') works. Does it somehow equate to the key / values in the config file? i.e. does the underscore in sonata_seo get magically changed to a period?
You cannot access values in config.yml direcly, like values in parameters.yml.
That file can store configuration values for bundles thought.
Read more here
What it is 'getting' in this instance, usually within a controller action, is a Symfony Service.
In this instance, sonata.seo.page is a reference to a service, setup in the sonata-project/seo-bundle, which returns an instance of the SeoPage class. Normally, this information is set within your local configuration file (config.yml, or a file that it includes), but the service returns the class that allows you to change the values at runtime.
No service are (directly) defined inside config.yml. It's the bundle that define the service. With $this->get('sonata.seo.page'); you get those.
The config.yml file it's just used to customize the bundles.
The SeoBundle defines the semantic configuration section sonata_seo from config.yml and registers the own Extension of DI container.
Extension implements the load() method. Configuration values from sonata_seo are passed as its first argument.
Method loads various resources including service definition from Resources/config/service.xml:
<parameter key="sonata.seo.page.default.class">Sonata\SeoBundle\Seo\SeoPage</parameter>
...
<service id="sonata.seo.page.default" class="%sonata.seo.page.default.class%"/>
Next, extension set up sonata.seo.page definition with given configuration parameters.
This process will be invoked during the container compilation, when the service definition and its settings will be embedded in the container. Result of this process you can find in the dumped container in the cache directory.
This is a typical scheme of work for the Symfony bundles: define the configuration structure, make an extension, set up the services.
I use Symfony2 BehatBundle, version=v1.0.0 and I want to change the name of the main feature context file. Now when I run the behat using command:
app/console --env=test behat #NameOfMyBundle
file src/NameOfMyBundle/Features/Context/FeatureContext.php is used
I want to use custom main feature file, for example src/NameOfMyBundle/Features/Context/MyCustomContext.php but I don't know how. According to the behat documentation:
By convention, the context class should be called FeatureContext, but this could be easily changed through the cli configuration.
However, this configuration option is nowhere to be found. I tried something like:
app/console --env=test behat #NameOfMyBundle --context "MyCustomContext"
but it fails.
Does anyone know how to change this main feature context file (preferably, using cli)?
Thanks!
The context class can be changed in the configuration file: http://docs.behat.org/guides/7.config.html#context
Environment variables can be used as well: http://docs.behat.org/guides/7.config.html#environment-variable
The bundle is no longer maintained. Use the extension instead: http://docs.behat.org/en/latest/cookbooks/1.symfony2_integration.html#installing-and-enabling-symfony2-extension
I used the following command to generate the catalogs of my different Bundles and it worked well.
php app/console translation:update --dump-messages --force fr ProjectBlogBundle
But how should I do to translate the view that we can find on /app/Resources/views/* ?
Thanks,
If you check the command code, it looks like it's not possible: the bundle name is required and must be provided.
However, you can check this out.
Even though you can't automatically extract/update translation segments from those views, the runtime translation should work, provided that you use the same translation domain.
Even though this question is rather dated, I figured I might add this just for anybody else stumbling across this:
It seems that the desired functionality has been added in the meantime (Symfony 2.8+).
If you run the command like this:
$ app/console translation:update --help
Usage:
translation:update [options] [--] <locale> [<bundle>]
Arguments:
locale The locale
bundle The bundle name or directory where to load the messages, defaults to app/Resources folder
It seems the bundle name has become optionale and the command will default to app/Resources
I had the same problem, and the #Jan's answer helped me. So there is an example.
cd app/
php ./console console translation:update --dump-messages --force fr .
As . is a directory (the current directory), the translator will try to load the subdirectory /Resources, so here it will try to load app/Resources/.
I could not manage to find a way to include different security.yml files that would be included depending on Symfony2`s environment. For example I wanted to have an in-memory user provider for my acceptance tests, cause I don't really need to test my entities and stuff here, I only want to make an acceptance test for my views.
But, as it turned out, it's not an easy thing to do. I removed security.yml from includes in my config.yml, renamed it to security_prod.yml and created a security_test.yml which has the in_memory user provider. Then I've included security_prod.yml and security_test.yml in my production and testing configs respectively.
Yet it does not seem to work at all:
$ SYMFONY_ENV=test app/console cache:clear
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
You are not allowed to define new elements for path "security.providers". Please define all elements for this path in one config file.
$ SYMFONY_ENV=prod app/console cache:clear
[Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException]
Configuration path "security.access_control" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one
configuration section.
It appeared to me like the security.yml filename was hardcoded (which would be way too weird for Symfony), and it wasn't.
So the question is: how do I get multiple security.ymls with Symfony? And what could be causing this behaviour?
Instruction for those, who is looking for it (and do not red comments):
Create different config files for different environments: config_test.yml, config_dev.yml, config_prod.yml
Create different security files: security_test.yml, security_dev.yml, security_prod.yml
Import security_test.yml in config_test.yml and so on for other environments. Example for config_test.yml:
imports:
- { resource: security_test.yml }
Make sure you included security_*.yml only once (basically author did this mistake)