Zero time deployment process for Magento2

The Magento 2 production deployment flow helps a store reach maximum performance by minimizing downtime during deployment. The length of time your production site is in maintenance mode depends on the size of the site, the number of changes applied during the deployment, and the configuration for static content deployment. One of the challenges with automating deployment is the cut-over itself, taking software from the final stage of testing to live production. You usually need to do this quickly in order to minimize downtime. You need to find a proper solution to prevent downtime during deployment that may be lengthy in some cases. 

One of these solutions is Envoyer.

What is Envoyer?

Envoyer is a deployment tool used to deploy PHP applications. Envoyer allows us to deploy code changes quickly and without any downtime. The changes are made available once the build is complete, without impacting the active codebase. This means that your application and the customers using it are not even aware of the fact that a new version has been pushed. 

Envoyer works well with major repository management platforms including Bitbucket. Other benefits include unlimited deployments and team members. Since Magento 2 is a PHP-based application you can easily use Envoyer service.

How does it work?

Envoyer deploys your Bitbucket repository to a "releases" directory on your server. Each system of "releases" folders represents a single commit in your Bitbucket repo history. Every time the deploy system gets triggered for a build, it creates a new folder in "releases" and clones the repo just at that commit into that folder. The name of the folder is time-stamped with the time of the deployment to keep it unique (e.g. releases/20200414223645)

Then it runs your full deployment script in there. Envoyer works through its build commands such as running composer install, compile dependency injection, deploy static content, linking shared folders, etc. Also, you can add your own build commands. Once Envoyer is done, the "current" directory is symlinked over to the latest release folder which is named based on the timestamp. The public folder at any time is just a symlink to one of several available folders in releases.

Besides, to work properly you'll need to set up the document root on your server to point to this "current" folder which will always reference the latest version of your codebase.

The standard structure of folders is:

Note that any files/folders that need to persist across releases need to exist at the root level and need to be symlinked into each release. 

For example, Magento 2 has such files as env.php and config.php. The env.php file includes database credentials, backend URL, cache types state, and other configuration information. The config.php file contains module information. These files are located in the app/etc/ directory and shouldn't be versioned since they are specific to an environment. How to handle such files will be described below.

Connect your Bitbucket project

Bitbucket repository

In order to start using Envoyer you have to create a repository with your project:

After signing up for Envoyer, you should add a project to your account. Projects are tied to a source control Bitbucket repository.

Add server access

After creating a project, you may add as many servers as you like to the project. Fill out all the required fields and save the server.

After adding a server, you will be given an SSH key to add to your server. You should add the SSH key to the authorized_keys file for the users you want to connect. Copy that key and add it to ~/.ssh/authorized_keys on your server.

The servers statuses can be checked in project dashboard on Servers tab:

After proper configuration you can start using Envoyer.

Deployment hooks customization

Envoyer gives you the ability to run deployment hooks during different stages of the deployment process. Envoyer has four steps in its deploy process, and you can run custom scripts before or after each of these steps:

clone new release

install composer dependencies

activate new release

purge old releases

You can configure the specific hook by clicking the gear button next to any of the steps:

These allow you to customize your entire deployment plan. You may add hooks that run before or after any step in your deployment. You may also specify the servers on which each hook is executed.

Let's consider deployment hooks which must be added for Magento 2 deployment.

Deployment process in action

Before configuring deployment hooks you can create a shared folder in your root directory to handle specific files (env.php, config.php, etc…) or folders which were mentioned earlier. This directory holds files and folders shared between releases. Usually, it is everything that has not changed between releases. The list of shared files directly depends on your project. For instance, we already know that app/etc/env.php, app/etc/config.php and pub/media should be shared.

Example of standard directories structure:

A little bit about Envoyer variables. Envoyer provides smart variables which should make your deployment easier. Each variable provides access to the information for which it is responsible. The use of variables will ensure the correct execution of operations and ensure proper access to the required data. For instance, the {{project}} variable provides access to the project’s root (the directory which contains current, releases). Within your deployment hook script, you may use the {{release}} Envoyer variable to access the most current release directory. More about variables you can find on Envoyer

In this article, we will consider the Activate New Release (before and after hooks) step in the deployment process provided by Envoyer.

The hook is a term used to indicate a code insertion into some standard operation to provide customization. You are allowed to execute your custom script prior/after an application build/deployment operations. Such implementation allows to completely automate your solution delivery by setting all the required application customizations within a single service panel to subsequently apply them all at once during a single deploy action. Hooks provide a broad range of opportunities for developers, which allow to automate many processes and get a ready-to-work application without any manual steps required. 

The name for each hook can be given depending on what it is responsible for.

Option Run As in hook configuration is the user under which all commands will be executed. Before executing, make sure that the specified user has access to the commands that will be listed.

Activate new release before hooks

  1. Upload the production files so they could be copied on deployment.
  1. Move into the folder for the code that is being deployed and setup correct permissions:
  1. Move into the folder for the code that is being deployed and install composer dependencies:
  1. Move into the folder for the code that is being deployed and upgrade the database data and schema:

Not familiar with Magento CLI? Get started with Magento 2 command-line configuration.

Please note, when you run the setup:upgrade (or setup:db-data:upgrade, setup:db-schema:upgrade in most recent Magento 2 versions) command Magento 2 is going to update the affected tables in the database. Since this deployment has not been activated yet, we have a moment where we could have a potential mismatch between the code and what is in these tables, which could cause an error. So we need to enable/disable maintenance mode before/after this command on this step.

  1. Move into the folder for the code that is being deployed and compile DI:

More about Magento 2 DI – Dependency injection

  1. Move into the folder for the code that is being deployed and deploy static content:

If you're using different languages, be sure to add them here. The static view files deployment command enables you to write static files to the Magento 2 file system when the Magento 2 application is set for production mode

More about Magento 2 deploy static content – Deploy static view files

Activate new release after hooks

Move into the folder for the code that is being deployed, ?lean Magento 2 cache, enable all cache types to finalize deployment process:

If you have other external services connected to Magento 2 — for example Cloudflare — you may need to clear the cache. So you can easily add-hook script for this (make sure you use your own API credentials to perform this request):

The configuration deployment hooks can be completed at this point.

Envoyer deployments may be triggered in three ways: manually, using “push to deploy”, or by making a request to the certain URL available in your project dashboard:

If you want it to automatically deploy your code every time, you add a new commit to your Bitbucket branch, go to Settings/Source Control and check "Deploy When Code Is Pushed":

If you've set everything up correctly your code will be pushed to the server, all deployment hooks will run, and a symlink will be created from the "current" folder on your server to this release and then you should see a "Finished" status with next to the deployment on the project dashboard:

You can also get additional information related to deployment by clicking the arrow button next to the deployment status:

If there's an error during one of the steps of the deployment process Envoyer will notice it and cancel the whole deployment, which will not damage the release used at the moment.

Deployment hook commands may vary depending on your Magento 2 store environment but basically you will use the standard commands described above. This article describes the major opportunities of the Magento 2 Envoyer service without downtime. So, feel free to research and discover new features.

In conclusion…

Magento 2 deployment might be lengthy. But it doesn’t mean that the store needs to be down for minutes. A proper deployment procedure needs to be done to minimize downtime or even make it zero. Envoyer handles this without any problems.