Deploying your app or website on a server with git

Published in code on February 06th, 2023.

How many times have you run the same commands over and over again during your deployments?

There's an easy way to combine everything as one.

This article comes right after the one where I've explained how to setup a git repository on your own server and has as a prerequisite everything I've presented there. 

*It also applies only to single node servers. This is an important disclaimer, as you'd want to look directly into a proper CI/CD pipeline if you're using clustered servers. But not every website or application has to use a load balancer and span <insert_geeky_devops_terms_here>, so let's get going ðŸ˜Š.

The magic, taking place

The idea is to standardise your process and add every command you usually run on your server into one single file that you'll trigger once per deployment.

The first step is to SSH into your server and create a new shell script:

cd <your_app>
vi run_deployment

You can name the file in any other way you wish.

Put your application down

A good practice would be to bring down your application, so that it cannot be accessed by end users throughout your deployment. This works in a scenario where ideally you'd have a 503 page layout available, with a proper message for your users, that you can quickly activate with a CLI command.

In case you're using Laravel, you may do the following:

php artisan down

Fetch your code

In order to pull-in your most recent commits onto the server, you may consider doing something like:

git reset --hard
git clean -df
git pull origin <branch>

The first command would reset all your files on the server which are part of the version control, while the second will clean every untracked file as well. Use these carefully. There are multiple reasons why your host might contain modified tracked files or new untracked files and you should decide the applicability of these commands on a project and / or server level. Also, you'll need to make sure that your .gitignore is up-to-date.

Then you'll fetch & merge the content from your chosen <branch>. Replace this with your branch of choice, depending on the environment where you're performing these actions.

Install your dependencies

If you are using composer, npm or similar, you may consider installing your newest dependencies by running:

composer install
npm install

together with any relevant parameters into your env. For example, if you're deploying the app in production, you might want to append --no-dev to your composer command.

Build your code

Here you'd trigger the right script(s) defined into your system, like in the package.json file, that will build your .js, .css and any other assets available.

npm run build

Run your application-specific scripts

Another category of operations you might be performing for every deployment are database migrations, clearing the cache or restarting your queues. Once again, applicable for Laravel, you might have something like:

php artisan migrate

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan permission:cache-reset

php artisan queue:restart
php artisan horizon:terminate

Bring your application up

Just do the opposite of the first command, clear the 503 and bring the application back up for your users. For Laravel, this would be:

php artisan up

One file, all commands

Add these or any other commands that might be applicable to your case into your own run_deployment file and you'd end up with something like this:

# Put the application down
php artisan down

# Fetch the code
git reset --hard
git clean -df
git pull origin <branch>

# Install dependencies
composer install --optimize-autoloader --no-dev
npm install

# Build the code
npm run build

# Migrate the database
php artisan migrate

# Clear the cache
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan permission:cache-reset

# Restart the queues
php artisan queue:restart
php artisan horizon:terminate

# Put the application up
php artisan up

Save the file. 

Trigger the deployment

Now, with every planned deployment, you'll have to cd into the right directory and trigger one command. Your deployment actions will then run in full and the right order.

bash run_deployment

This will make things much much faster. Of course, you might want to think about certain edge cases exclusive to you project (like running seeders, maybe restarting your workers because of a new queue, etc.) whenever such would apply and I'm sure you'd be able to fit the steps in somewhere along the way.