An Interest In:
Web News this Week
- April 18, 2024
- April 17, 2024
- April 16, 2024
- April 15, 2024
- April 14, 2024
- April 13, 2024
- April 12, 2024
Zero-Downtime Deployment with Laravel Forge
Deploying web applications can be a repetitive and error-prone task. In this blog post, we'll introduce a Bash script designed to automate the deployment process for a web application hosted on a server. Let's dive into the details of the script and how it streamlines the deployment workflow.
Setup
Before diving into the deployment process, let's set up some initial configurations:
DOMAIN=example.comPROJECT_REPO="your_github_repo_name"AMOUNT_KEEP_RELEASES=5RELEASE_NAME=$(date +%s--%Y_%m_%d--%H_%M_%S)RELEASES_DIRECTORY=~/$DOMAIN/releasesDEPLOYMENT_DIRECTORY=$RELEASES_DIRECTORY/$RELEASE_NAME
These variables define crucial aspects such as the domain name, project repository, and the number of releases to keep.
Deployment Process
Cloning Repository and Setup
The script starts by creating a unique release directory and clones the project repository into it:
cd /home/forge/$DOMAINmkdir -p "$RELEASES_DIRECTORY" && cd "$RELEASES_DIRECTORY"git clone "$PROJECT_REPO" "$RELEASE_NAME"cd "$RELEASE_NAME"git checkout "$FORGE_SITE_BRANCH"git fetch origin "$FORGE_SITE_BRANCH"git reset --hard FETCH_HEAD
Environment Setup
Next, the script copies the .env
file from the project directory:
printf '
Copy ./.env file
'ENV_FILE=~/"$DOMAIN"/.envif [ -f "$ENV_FILE" ]; then cp $ENV_FILE ./.envelse printf '
Error: .env file is missing at %s.' "$ENV_FILE" && exit 1fi
Running Laravel Commands
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader( flock -w 10 9 || exit 1 echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlockif [ -f artisan ]; then $FORGE_PHP artisan migrate --forcefi
Dependency Installation and Build
The script installs NPM dependencies and generates necessary files:
printf '
Installing NPM dependencies based on \"./package-lock.json\"
'npm installprintf '
Generating JS App files
'npm run build
Linking Deployment Directory
The script links the deployment directory to the current directory:
printf '
!!! Link Deployment Directory !!!
'echo "$RELEASE_NAME" >> $RELEASES_DIRECTORY/.successesif [ -d ~/$DOMAIN/current ] && [ ! -L ~/$DOMAIN/current ]; then rm -rf ~/$DOMAIN/currentfiln -s -n -f -T "$DEPLOYMENT_DIRECTORY/public" ~/$DOMAIN/current
Clean Up
Lastly, the script performs clean-up tasks:
printf '
Delete failed releases:
'# Code for deleting failed releasesprintf '
Delete old successful releases:
'# Code for deleting old successful releasesprintf '
Status - stored releases:
'# Code for displaying stored releasesprintf '
Deployment DONE: %s
' "$DEPLOYMENT_DIRECTORY"
Full Script
# SETUP #DOMAIN=yourdomain.comPROJECT_REPO="[email protected]:your-team/repo.git"AMOUNT_KEEP_RELEASES=5RELEASE_NAME=$(date +%s--%Y_%m_%d--%H_%M_%S)RELEASES_DIRECTORY=~/$DOMAIN/releasesDEPLOYMENT_DIRECTORY=$RELEASES_DIRECTORY/$RELEASE_NAME# stop script on error signal (-e) and undefined variables (-u)set -euprintf '
Starting deployment %s
' "$RELEASE_NAME"cd /home/forge/$DOMAINmkdir -p "$RELEASES_DIRECTORY" && cd "$RELEASES_DIRECTORY"printf '
Clone GIT project from %s and checkout branch %s
' "$PROJECT_REPO" "$FORGE_SITE_BRANCH"git clone "$PROJECT_REPO" "$RELEASE_NAME"cd "$RELEASE_NAME"git checkout "$FORGE_SITE_BRANCH"git fetch origin "$FORGE_SITE_BRANCH"git reset --hard FETCH_HEADprintf '
Copy ./.env file
'ENV_FILE=~/"$DOMAIN"/.envif [ -f "$ENV_FILE" ]; then cp $ENV_FILE ./.envelse printf '
Error: .env file is missing at %s.' "$ENV_FILE" && exit 1fi$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader( flock -w 10 9 || exit 1 echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlockif [ -f artisan ]; then $FORGE_PHP artisan migrate --forcefiprintf '
Installing NPM dependencies based on \"./package-lock.json\"
'npm installprintf '
Generating JS App files
'npm run buildprintf '
!!! Link Deployment Directory !!!
'echo "$RELEASE_NAME" >> $RELEASES_DIRECTORY/.successesif [ -d ~/$DOMAIN/current ] && [ ! -L ~/$DOMAIN/current ]; then rm -rf ~/$DOMAIN/currentfiln -s -n -f -T "$DEPLOYMENT_DIRECTORY/public" ~/$DOMAIN/current# Clean Upcd $RELEASES_DIRECTORYprintf '
Delete failed releases:
'if grep -qvf .successes <(ls -1)then grep -vf .successes <(ls -1) grep -vf .successes <(ls -1) | xargs rm -rfelse echo "No failed releases found."fiprintf '
Delete old successful releases:
'AMOUNT_KEEP_RELEASES=$((AMOUNT_KEEP_RELEASES-1))LINES_STORED_RELEASES_TO_DELETE=$(find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@%f
' | head -n -"$AMOUNT_KEEP_RELEASES" | wc -l)if [ "$LINES_STORED_RELEASES_TO_DELETE" != 0 ]; then find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@%f
' | sort -t $'' -g | head -n -"$AMOUNT_KEEP_RELEASES" | cut -d $'' -f 2- find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@%f
' | sort -t $'' -g | head -n -"$AMOUNT_KEEP_RELEASES" | cut -d $'' -f 2- | xargs -I {} sed -i -e '/{}/d' .successes find . -maxdepth 1 -mindepth 1 -type d ! -name "$RELEASE_NAME" -printf '%T@%f
' | sort -t $'' -g | head -n -"$AMOUNT_KEEP_RELEASES" | cut -d $'' -f 2- | xargs rm -rfelse AMOUNT_KEEP_RELEASES=$((AMOUNT_KEEP_RELEASES+1)) LINES_STORED_RELEASES_TOTAL=$(find . -maxdepth 1 -mindepth 1 -type d -printf '%T@%f
' | wc -l) printf 'There are only %s successfully stored releases, which is less than or equal to your
defined %s releases to keep, so none of them got deleted.' "$LINES_STORED_RELEASES_TOTAL" "$AMOUNT_KEEP_RELEASES"fiprintf '
Status - stored releases:
'find . -maxdepth 1 -mindepth 1 -type d -printf '%T@%f
' | sort -nr | cut -f 2-printf '
Deployment DONE: %s
' "$DEPLOYMENT_DIRECTORY"
Conclusion
Automation is key to improving deployment efficiency and reducing errors. By using this Bash script, you can streamline the deployment process for your web applications, saving time and ensuring consistency.
Original Link: https://dev.to/karakhanyans/zero-downtime-deployment-with-laravel-forge-3ho6
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To