Php multiple db environment with git & phpfog - php

I have a plain(no framework) php app. I want to deploy my app to PhpFog.
The problem is the config(host,dbname) is different.
How to create a db config for development and production environment?

You could use environment variables to do this. PHPFog provides a way to set environment variables in the App Console > Env. Variables tab for your app.
Simply create all the environment variables that you need on both your local machine and on the App Console:
Example:
Local Machine: Edit your .bash_profile
APP_HOST=localhost
APP_DATABASE=mydatabase
PHPfog App Console:
APP_HOST=production.mysqlserver.com
APP_DATABASE=proddatabase
Then access them from your php app:
$db_host = getenv("APP_HOST");
$db_name = getenv("APP_DATABASE");

You can put your config.php in your .gitignore or another solution is to have two branches on your local repository. One to work locally and one to push. Then you define a special merge strategy:
Let's say you want to exclude the file config.php
On branch A:
Create a file named '.gitattributes' in the same dir, with this line:
config.php merge=ours. This tells git what strategy to use when mergin
the file. In this case it always keep your version, ie. the version on
the branch you are merging into.
Add the .gitattributes file and commit
On branch B: repeat steps 1-2
Try merging now. Your file should be left untouched.

Related

.env files in Github Actions CI/CD workflows: how to provide these into the workflow

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.

How to switch between Symfony Environments?

I got my Symfony 3.4 application deployed using PROD environment following this guide: https://symfony.com/doc/3.4/deployment.html (seems that, by default, was running on PROD, since I does not selected any environment during installation...)
In the near future, this machine will take the PRE-PRODUCTION role, so I created a new environment called pre for my application following this guide: http://symfony.com/doc/3.4/configuration/environments.html#creating-a-new-environment
Now I'm wondering how to switch this machine to new PRE environment.
I read these guides, but I'm still confused:
1) http://symfony.com/doc/3.4/configuration/environments.html#executing-an-application-in-different-environments
2) http://symfony.com/doc/3.4/setup/web_server_configuration.html
On the current machine, I'm using Apache; but for production, and following updates, I'll considere to start using NGINX. So, both options are appreciated.
If you've followed the instructions in the documentation you've entered:
Because you'll want this environment to be accessible via a browser, you should also create a front controller for it. Copy the web/app.php file to web/app_benchmark.php and edit the environment to be benchmark
then you have app_pre.php front controller with this line:
$kernel = new AppKernel('pre', false);
Just point your Apache web server to use app_pre.php instead of app.php as the front controller and your environment is switched.

How to change different configuration settings between environments in PHP?

I have a a few php files which I call via AJAX calls. They all have a URL to my config.php. Now I've the problem that I always have to change the URLs to that config file by hand when I deploy a new version on my server.
Local Path:
define('__ROOT__', $_SERVER["DOCUMENT_ROOT"].'/mywebsite');
Server Path:
define('__ROOT__', $_SERVER["DOCUMENT_ROOT"].'/../dev.my-website.tld/Modules/');
I want to track changes in all of these PHP files. I'm searching for a solution to automatically change this path.
E.g.
This is my current workflow:
Local Environment:
(path version A)
do changes in the code
git add, git commit, git merge, git push to my server
Server:
git reset --hard
change path to version B
You are trying to run different code bases between development and live, which is not recommended -- they should be identical. The way I tackle this is to use an environment variable to specify which of several config files should be loaded.
In my Apache vhost I do something like this:
SetEnv ENVIRONMENT_NAME local
And then I use a function to read the environment name:
function getEnvironmentName()
{
$envKeyName = 'ENVIRONMENT_NAME';
$envName = isset($_SERVER[$envKeyName]) ? $_SERVER[$envKeyName] : null;
if (!$envName)
{
throw new \Exception('No environment name found, cannot proceed');
}
return $envName;
}
That environment name can then be used in a config file to include, or to retrieve values from a single array keyed on environment.
I often keep environment-specific settings in a folder called configs/, but you can store them anywhere it makes sense in your app. So for example you could have this file:
// This is /configs/local.php
return array(
'path' => '/mywebsite',
// As many key-values as you want
);
You can then do this (assuming your front controller is one level deep in your project, e.g. in /web/index.php):
$root = dirname(__DIR__);
$config = include($root . '/configs/' . getEnvironmentName() . '.php');
You'll then have access to the appropriate per-environment settings in $config.
A pure git way to achieve this would be filters. Filters are quite cool but often overlooked. Think of filters as a git way of keyword expansion that you could fully control.
The checked in version of your file would for example look like this:
define('__ROOT__', 'MUST_BE_REPLACED_BY_SMUDGE');
Then set up two filters:
on your local machine, you'd set up a smudge filter that replaces
'MUST_BE_REPLACED_BY_SMUDGE'
with
$_SERVER["DOCUMENT_ROOT"].'/mywebsite'
on your server, you'd set up a smudge filter that replaces
'MUST_BE_REPLACED_BY_SMUDGE'
with
$_SERVER["DOCUMENT_ROOT"].'/../dev.my-website.tld/Modules/'
on both machines, the clean filter would restore the line to be
define('__ROOT__', 'MUST_BE_REPLACED_BY_SMUDGE');
Further information about filters could be found in this answer and in the Git Book.

Artisan unable to use $_SERVER variables from database config file

I am currently deploying a Laravel project on my shared hosting account. It is an open project and hosted on GitHub as a public repository. As a result I'm using dynamic variables set by an .htaccess file in my database.php configuration file for my production environment. This allows me to also update my deployment using a git pull command on my host which helps speed up work.
The database.php file has something similar to
$database = $_SERVER['DBNAME'];
$database_user = $_SERVER['DBUSER'];
This is much like what is done when deploying to PagodaBox & works perfectly fine for the application with all things functioning as expected in the browser, no complaints.
The problem I have is that artisan is unable to use these variables and will attempt instead to connect to the database using what I believe to empty variables when processing a migrate instruction. I get an error that artisan tried to connect to the databases with no password. I have been calling artisan using --env=production and have tested this but found that it will only work if the database.php file has the variables specified explicitly instead of as environment variables.
Is there a way of causing artisan to "see" these environment variables?
answers that have proved useful to me so far:
http://forums.laravel.io/viewtopic.php?pid=8455
and
Environment driven database settings in Laravel?
Because Artisan is a CLI PHP request - the request never hits the .htaccess file - and therefore your variables are never set.
As a workaround - you could define the variables inside the artisan file itself on line 3 (just after the <?php)
$_SERVER['DBNAME'] = 'test';
$_SERVER['DBUSER'] = 'something';
edit: I just noticed you said this is public hosted on github - so you wont want to include your username/password in the file? Maybe put the artisan file as part of the .gitignore group - so you dont push/pull that single file?
The capability to set up environment variables is built in to Laravel, so there's no reason to do it in .htaccess. Laravel's built-in way works with artisan without any trouble.
See this part of the docs about environment variables you would like to protect.
http://laravel.com/docs/configuration#protecting-sensitive-configuration
Quoting:
... create a .env.local.php file within the root of your project [...] The .env.local.php should return an array of key-value pairs, much like a typical Laravel configuration file:
<?php
return array(
'TEST_STRIPE_KEY' => 'super-secret-sauce',
);
All of the key-value pairs returned by this file will automatically be available via the $_ENV and $_SERVER PHP "superglobals". You may now reference these globals from within your configuration files:
'key' => $_ENV['TEST_STRIPE_KEY']
Be sure to add the .env.local.php file to your .gitignore file. This will allow other developers on your team to create their own local environment configuration, as well as hide your sensitive configuration items from source control.
Add your private environment variables
<?php
return array(
'MY_SECRET_KEY' => 'super-secret-sauce',
);

What is the right way to maintain a "version for the server" - with only config files changed, in Git?

I sometimes work with Codeigniter, and after I'm done developing on the local site, I need to migrate the files to the server. All the files in the /config/ folder need to be changed to match the Server settings. It's not right to make an entire commit for these changes, do I simply make Git ignore these files altogether, or is there a way to track these changes and apply them with Git at the right moment?
You could keep versioned:
two "value config files", with the right values for each environment
a template config file, with value placeholder in it (for instance, ##PORT_NUMBER##)
a script able to generate the actual config file depending on the current environment
a content filter driver which, on checkout, will trigger the script in order to generate the right config file.
Note: that supposes your template config file has a recognizable content (the filter doesn't have a name or path of the file). See "Git equivalent of subversion's $URL$ keyword expansion" for more on the limitation of git content filter driver).
It depends on Your needs. In my company we use other approach.
We've created several environments (where the asterix is internal project name):
devel - site runs on domain **.local.com*
test - site run on domain test.*.company.com
beta - beta.*.company.com
production - every other domain.
Based on the domain name we switch automatically configurations.
Basicly config file looks like:
<?php
return array(
'_env' => array(
'devel' => array(
// config for devel
),
'production' => array(
// config for production
)
)
);
?>
Some frameworks (AFAIR Zend) set the environment name in Virtual Host config (or .htaccess). You should look at: zend framework auto switch production staging test .. etc
Have You looked at CI documentation? There's a section about it.
Create two folders in the config folder. One is called development and the other is production. Now copy config.php, database.php etc to each of these folders. Now when you are on production server, CodeIgniter will first check the production folder for the files. If it is not there, then it uses the default file in the config folder. And if you are on development environment, CodeIgniter will first check the development folder.
If you want to keep any config file identical to the production and development environment, keep it in config folder.
If you want to set the environment then add the following code in .htaccess file:
#This code for Development Environment
SetEnv CI_ENV development
and
#This code for Production Environment
SetEnv CI_ENV production

Categories