2

We have a Laravel deployment website set up under deploy.mysite.com which handles deployments for a multitude of other websites.

One other website I'm trying to deploy which is also a Laravel site resides under site2.myothersite.com.

Both are on the same server. Deploy calls a script on site2, this deploy script runs various commands after cd'ing to the project directory. We use the following to update the database structure.

php artisan migrate --force

Ordinarily when this is run directly via SSH when in the project root, it runs just fine.

However when this is run via the deployment script (using php exec() to run these commands) the process does work - however, instead of updating the project that we've cd'd into, it updates the database structure of the deployment site!

It seems as if the php artisan migrate command ignores the fact I've cd'd into another project and it takes the database values from the current directory.

How can I go about changing this behaviour?

Novocaine
  • 4,692
  • 4
  • 44
  • 66

5 Answers5

4

After playing around with multiple different solutions I eventually came to realise that the problem was the .env file from the project that I was in was setting the environment variables and then weren't being overwritten by anything therefore was then essentially running the code as the wrong site.

What I did to solve this

In my deploy script I manually loaded up the .env file and overwrote the environment variables with overload rather than just load. Note: This will only work on versions below V5.

$dotenv = Dotenv::create(__DIR__);
$dotenv->overload();

UPDATE for V5

As per @nibnut's comment, since dotenv V5 (now in Laravel 7.0) this loads the environment variables as immutable. In my case I'm happy to allow these to be mutable, in which case I can do the following instead of the above.

$dotenv = Dotenv::createMutable(__DIR__);
$dotenv->load();

https://github.com/vlucas/phpdotenv#immutability-and-repository-customization

This was all I had to do to get my original script working.

NOTE: as this is a laravel install at all ends, the dotenv package was already installed. This could be used for any project by installing it separately.

Novocaine
  • 4,692
  • 4
  • 44
  • 66
2

Rather than cd to the directory, you could change the command to something similar to this:

php /var/www/sitea/artisan migrate --force

That will run the artisan command for the provided directory.

George Hanson
  • 2,940
  • 1
  • 6
  • 18
  • This is something I have actually tried - I also double checked it just now, unfortunately I get the same result. I wiped the database first, and instead of creating the tables, it failed, telling me that a users table already exists (which it does on the deploy site), so even running the command as above it's still trying to run it on a different install. – Novocaine Oct 15 '18 at 13:27
  • Did you check to make sure the .env file in the site contains the correct database credentials? – George Hanson Oct 15 '18 at 13:31
1
$log = shell_exec("unset DB_HOST &&
       unset DB_PORT && 
       unset DB_PASSWORD && 
       unset DB_USERNAME && 
       unset DB_DATABASE && 
       composer dump-autoload &&
       cd /var/www/yourproject/ && php /var/www/yourproject/artisan migrate:fresh &&
       php /var/www/yourproject/artisan db:seed &&
       php /var/www/yourproject/artisan seed:translation");
Srneczek
  • 2,143
  • 1
  • 22
  • 26
1

novocaine's answer unfortunately no longer works in Laravel 7.x, since the DotEnv file is loaded immutable.

My current workaround is to create a temporary .env file in my project (i.e. ".env.temp") then use the --env argument when calling my artisan commands:

php artisan migrate --env=temp

This may not work for all use cases, but if you're calling artisan commands in project B from within project A, it should work fine.

nibnut
  • 3,072
  • 2
  • 15
  • 17
  • I've not ran this with a 7.x install yet, but this looks like a good solution – Novocaine Aug 03 '20 at 16:11
  • I've now ran into this problem and have updated my answer. Initialising as mutable can also work IF that's ok for your environment - `$dotenv = Dotenv::createMutable(__DIR__); $dotenv->load();` – Novocaine Aug 06 '20 at 15:01
  • Yep - the createMutable option works very well too - thanks for this! – nibnut Aug 12 '20 at 14:15
0

novocaine's answer involve reloading .env file. But you can also empty environment variables with env -i.

This method will avoid having some variables not overwritten due to different .env file variable name. For example, your deployment site may have a variable called DEPLOY_KEY in the .env that is non-existent on the .env of site2. Reloading .env file may leave the DEPLOY_KEY variable available on the site2 script. This may leads into security issues.

So, instead of running

exec('php artisan migrate --force');

you'll have just to add env -i:

exec('env -i php artisan migrate --force');

Source: https://unix.stackexchange.com/a/48995/375005