GithubHelp home page GithubHelp logo

envoy-deploy's Introduction

Laravel Envoy Deploy

This repository includes an Envoy.blade.php script that is designed to provide a basic "zero-downtime" deployment option using the open-source Laravel Envoy tool.

Requirements

This Envoy script is designed to be used with Laravel 7+ projects and can be used within the Laravel root, or downloaded separately and included in your Laravel project.

Installation

Your must have Envoy installed using the Composer global command:

composer global require "laravel/envoy"

Standalone

To download and run out-with your Laravel project, clone this directory and do a composer install.

Laravel

Laravel 9+

To use within an existing Laravel 8+ project, you simply need to download the version 5 Envoy.blade.php file to your project root:

wget https://raw.githubusercontent.com/papertank/envoy-deploy/master/Envoy.blade.php

Laravel 7+

To use within an existing Laravel 7+ project, you simply need to download the version 4 Envoy.blade.php file to your project root:

wget https://raw.githubusercontent.com/papertank/envoy-deploy/v4/Envoy.blade.php

Laravel 5-6

To use within an existing Laravel 5 or 6 project, you simply need to download the version 2 Envoy.blade.php file to your project root:

wget https://raw.githubusercontent.com/papertank/envoy-deploy/v2/Envoy.blade.php

Setup

Config

Envoy Deploy uses DotEnv to fetch your server and repository details. If you are installing within a Laravel project, there will already be a .env file in the root, otherwise simply create one.

The following configuration items are required:

  • DEPLOY_SERVER
  • DEPLOY_REPOSITORY
  • DEPLOY_PATH

For example, deploying the standard Laravel repository on a Forge server, we might use:

[email protected]
DEPLOY_REPOSITORY=https://github.com/laravel/laravel.git
DEPLOY_PATH=/home/forge/example.com
DEPLOY_HEALTH_CHECK=https://example.forge.com

The DEPLOY_PATH (server path) should already be created in your server and must be a blank directory.

Host

Envoy Deploy uses symlinks to ensure that your server is always running from the latest deployment. As such you need to setup your Apache or Nginx host to point towards the host/current/public directory rather than simply host/public.

For example:

server {
    listen 80;
    server_name example.com;
    root /home/forge/example.com/current/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
    }

    location ~ /\.ht {
        deny all;
    }
}

Usage

Init

When you're happy with the config, run the init task on your local machine by running the following.

envoy run init

You only need to run the init task once.

The init task creates a .env file in your root path (from your .env.example file), so make sure and update the environment variables appropriately. Once you have run the init task, you should proceed to run the deploy task (below).

Deploy

Each time you want to deploy simply run the deploy task on your local machine in the repository direcory

envoy run deploy

You can specify the Laravel environment (e.g. for artisan:migrate command) and git branch as options

envoy run deploy --branch=develop --env=development

Deploy with Cleanup

If you could like to deploy your repository and cleanup any old deployments at the same time, you can run

envoy run deploy --cleanup

This will run the deploy script and then delete any old deployments older than 48 hours, leaving at least 4.

You can also run the cleanup script independently (without deploying) using

envoy run deployment_cleanup

Deploy with Maintenance Mode

Although this script is designed to use zero-downtime deployments, you can activate Laravel's maintenance mode while deploying by using the down option:

envoy run deploy --down

Health Check

If you would like to perform a health check (for 200 response) after deploying, simply add your site's URL in the .env file:

DEPLOY_HEALTH_CHECK=https://example.forge.com

Rollback

To rollback to the previous deployment (e.g. when a health check fails), you can simply run

envoy run rollback

Commands

envoy run init

Initialise server for deployments

Options
    --env=ENVIRONMENT        The environment to use. (Default: "production")
    --branch=BRANCH          The git branch to use. (Default: "master")

envoy run deploy

Run new deployment

Options
    --env=ENVIRONMENT        The environment to use. (Default: "production")
    --branch=BRANCH          The git branch to use. (Default: "master")
    --cleanup                Whether to cleanup old deployments
    --down					 Enable maintenance mode

envoy run deployment_cleanup

Delete any old deployments, leaving just the last 4.

envoy run rollback

In case the health check does not work, you can rollback and it will use the previous deploy.

How it Works

Your $path directory will look something like this after you init and then deploy.

releases/
current -> ./releases/20220103125914
storage/
.env

As you can see, the current directory is symlinked to the latest deployment folder

Inside one of your deployment folders looks like the following (excluded some laravel folders for space)

app/
artisan
boostrap/
composer.json
.env -> ../.env
storage -> ../storage
vendor/

The deployment folder .env file and storage directory are symlinked to the parent folders in the main (parent) path.

Optional Features

Restart Queue Workers

If you use Laravel's queue daemon, you should set the following environment variable to true to automatically run php artisan artisan queue:restart

DEPLOY_RESTART_QUEUE=true

Alternatively, if you use Laravel Horizon for your Redis queue management, you should set the value to horizon to automatically php artisan horizon:terminate

DEPLOY_RESTART_QUEUE="horizon"

Reload PHP FPM

If you use something like OPCache, you should reload the PHP FPM service at the end of each deployment.

Simply update the following environment variable to your PHP-FPM service name, which will automatically run sudo -S service php8.1-fpm reload

DEPLOY_PHP_FPM="php8.1-fpm"

Multiple PHP Versions

If you use multiple PHP versions on your server (e.g. with Laravel Forge) and are not with the default version, you should update your environment variables to specify the version and binaries. For example:

DEPLOY_PHP_CMD="/usr/bin/php7.4"
DEPLOY_COMPOSER_CMD="/usr/bin/php7.4 /usr/local/bin/composer"
DEPLOY_PHP_FPM="php7.4-fpm"

Laravel Mix / NPM

If you use Laravel mix / npm dependencies in your project, you should add the (disabled by default) deployment_npm task to the deploy story. For example:

@story('deploy')
	deployment_start
	deployment_links
	deployment_composer
	deployment_npm
	deployment_migrate
	deployment_cache
	deployment_symlink
	deployment_reload
	deployment_finish
	health_check
	deployment_option_cleanup
@endstory

If you only use Laravel mix for asset compilation and don't use any node scripts after deployment, you can update your deployment script to remove the node_modules folder and save some disk space on old deployments:

@task('deployment_npm')
	echo "Installing npm dependencies..."
	cd {{ $release }}
	npm install --no-audit --no-fund --no-optional
	echo "Running npm..."
	npm run {{ $env }} --silent
	rm -rf {{ $release }}/node_modules
@endtask

Disclaimer

Before using on live server, it is best to test on a local VM (like Laravel Homestead) first.

Changes

V5.0

  • Added $php and $composer variables to allow binary paths to be updated.
  • Added $releases variable for /releases path.
  • Added optional $php_fpm variable (DEPLOY_PHP_FPM env variable) to reload FPM service.
  • Added --down option to enable maintenance mode.
  • Added deployment_reload task.
  • Added $restartQueue variable (DEPLOY_RESTART_QUEUE env variable) to restart queue / horizon.

V4.1

  • Added fastcgi_param SCRIPT_FILENAME and DOCUMENT_ROOT variables (for better nginx symlink handling).

V4.0

  • Added optional deployment_npm task (disabled by default).
  • Tidied up deployments into releases folder.
  • Removed deploy_cleanup story to simplify - use 'envoy run deploy --cleanup'.
  • Removed storage/public link and replaced with 'php artisan storage:link' command.

V3.0

  • Updated DotEnv to "^4.0" for Laravel 7 compatibility.

V2.2

  • Added health_check task and config.
  • Added rollback task to update current to previous deployment.
  • Updated cleanup to delete old deploys and leave last 4.
  • Removed deployment_optimize task (no longer needed for Laravel 5 projects).
  • Updated deployment_composer to use --prefer-dist --optimize-autoloader options.

V2.1 - Updated init to only initialize (rather than deploy).

v2.0 - Switched to using DotEnv (removing envoy.config.php) and cleaned up tasks/stories.

v1.0.1 - Added cleanup task and deploy_cleanup macro after changing cleanup command.

Contributing

Please submit improvements and fixes :)

Credits

Author

Papertank Limited

envoy-deploy's People

Contributors

badchoice avatar davidrushton avatar mallchin avatar marco-acorte avatar wtom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

envoy-deploy's Issues

Generated deployment folder how to DocumentRoot

The generated deployed folder can be

20150317110501/
20150317114500/
current -> ./20150317114500
storage/
.env

and you set as root folder root /home/forge/example.com/current/public;

Should not be the root path root /home/forge/example.com/current/20150317114500/public;??

I am using apache and facing this issue because for each deploymend the folder name is changed and root must be changed.

I guess the symbolic link should be created with the command
ln -nfs {{ $release_dir }}/* {{ $app_path }}/current

How to avoid unnecessary migrate:rollback

It's not a real issue, just a discussion to improve this fantastic product

with this deployment system made with Laravel Envoy we can manage the rollback (restore previous src folder) but not the rollback of the migration/s

It is not complete in my opinion because it should also rollback the (possible) migrations performed previously

The problem from cmdline is that I can't immediately understand if there have been migrations (should I check the migrations table before and after? sich)

Do any of you have forge/envoyer? How do THEY do it in this case?

New deploy finished success but changes not seems

After run envoy run deploy all tasks run successfully.
New release folder created and new code seems inside both release folder and current folder.

what kind of permissions must have folders and files

2

Dotenv must be an instance of repositoryInterface

Hi There,

Why is this happening?

My laravel version is 7

╰ envoy run deploy
PHP Fatal error:  Uncaught TypeError: Argument 1 passed to Dotenv\Dotenv::create() must be an instance of Dotenv\Repository\RepositoryInterface, string given, called in /mnt/d/Personal Documents/Career/Bluefit/repos/salt-backend/Envoy9fa9ff7f759fea3ad676b08c50729eca.php on line 15 and defined in /mnt/d/Personal Documents/Career/Bluefit/repos/salt-backend/vendor/vlucas/phpdotenv/src/Dotenv.php:62
Stack trace:

It was fine for me on laravel 6.. probably because the dotenv version is changed in laravel 7?

Thanks

storage symlink causes git to think there's a new file

I followed your instructions and have done the "init" so far. However, when I go to my server to make sure everything is setup properly and to adjust my .env file, I noticed that git thinks that the storage dir is now a new file:

$ git st
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	storage
nothing added to commit but untracked files present (use "git add" to track)

Have you come across this as well? If so, is there a good solution here? If I add this "untracked file" to the repo, I'm afraid it will screw things up on my local development box.

Storage folder does not serve for correct project directory

Hi guys, after the deployment, i found that my application storage folder pointed to old folder but the current folder already point to latest version.

I got three version of project in root directory

--- 20211111060137/ old version 1
--- 20211111064441/ old version 2
--- 20211111072800/ -> current
--- Envoy.blade.php
--- storage/

My project showed that current was point to latest project now

current -> /home/vagrant/code/homestead/20211111072800/

When checking the storage folder. The storage/public was not linked to latest project, instead it link with the old project
Inside my storage/

public -> /home/vagrant/code/homestead/20211111060137/storage/app/public/

I was expected storage/public should link to the latest project, which is 20211111072800, but now is not, any idea?

How do you define multiple environments?

Hi,

How do you define multiple environments? I managed to just change the current parameters in the envoy.config.php file but I would like to be able to chose the deployment environment obv. and I don't see how you should define it.

Thx

Config:clear required for reading ENV variables

After each deploy using this script, my app doesn't seem to properly read environment variables.

While my app can read from the database no problem (using env variables), it's unable to read an API key I have stored in the same .env file. When I print out env variables in a class (also DB ones), they always return NULL.

I was only able to fix the problem by adding php {{ $release }}/artisan config:clear --quiet in the deployment_finish task, just before the echo "Deployment ({{ $date }}) finished". Adding the same command in the deployment_cache didn't do the trick, I guess the config needs to cleared after the ln -nfs command?

Won't investigate more for now but you might want to look in to it.

Thanks

Deployment path does not begin with /

Is anyone having this issue?

It never happened to me prior. I'm using laravel 8, it was fine on 7 before (i also upgraded the dotenv versioning)

❯ envoy run init

In Envoyca58753152131a6f645fe0e2e835f55f.php line 31:

  Careful - your deployment path does not begin with /

Cleanup doesn't work

The ls -1d 20* | head -n -5 | xargs -d \'\n\' sudo rm -Rf; doesn't work. It seems there is an issue with the '\n'. If i output the command I get the following: ls -1d 20* | head --lines=-1 | xargs -d n sudo rm -Rf

Laravel 5.5 - Passport

Acording Laravel Passport we should run this in order to generate passport keys on production, once .gitignore wont version *.keys files.

php artisan passport:keys

What kind of script change is necessary to handle this?

Rollback

It would be nice to have an option to easily rollback if something is messed up

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.