Skip to content

Deployments

Deployments of applications happen through forge its logic. This means that

By default, Forge will give you a starters deployment script. This will, in most cases, deploy your application. However, due to the nature of our projects, we want some more secret sauce to deploy our applications.

Normal Deploy script

bash
cd $FORGE_SITE_ROOT

$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader

npm ci
npm run build

if [ -f artisan ]; then
    $FORGE_PHP artisan migrate --force
fi

touch /tmp/fpmlock 2>/dev/null || true
( flock -w 10 9 || exit 1
    echo 'Reloading PHP FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9</tmp/fpmlock

As you can see, this deployment script, just assumes that there is nothing special. However, most of the time, we use an arsenal of packages and versions, e.g. Inertia, Wayfinder, ...

This means that we need to tell the script exactly what we use and which version

Extended deploy script

A lot of times, we will use a specific NodeJS version for an application it's front-end. It's bad practice to just run npm install && npm run build on whatever version the server has. This can lead to discrepancies and compatibility issues with the build. Which is why, we use NVM to set the correct version on the server before building the assets.

Server side steps (only once or per user when isolated):

  1. Install NVM: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash (make sure you use the latest tag)
  2. Run the following command to make nvm available in the terminal:
bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

Deploy script with NVM

bash
cd $FORGE_SITE_PATH

git pull origin $FORGE_SITE_BRANCH

$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader

if [ -f artisan ]; then
    $FORGE_PHP artisan optimize:clear
    #$FORGE_PHP artisan wayfinder:generate # comment out if used
fi

# Detect if there is an .nvmrc file present, so we can use that
if [[ -f .nvmrc ]]; then

    source ~/.nvm/nvm.sh
    
    # Check if nvm use is "possible", if it's not installed, the version in the .nvmrc will be installed.
    if ! nvm use; then
      nvm install
    fi

    # Install and compile
    npm ci || npm install
    npm run build

    # revert to the old version
    echo "Reverting to nvm default version"
    nvm use default

else

    # No nvmrc found, using the server-wide version
    npm ci || npm install
    npm run buil
  
fi

if [ -f artisan ]; then
    $FORGE_PHP artisan optimize
    $FORGE_PHP artisan migrate --force
    #$FORGE_PHP artisan queue:restart # comment out if used
    #$FORGE_PHP artisan wayfinder:generate # comment out if used
fi

# Prevent concurrent php-fpm reloads...
touch /tmp/fpmlock 2>/dev/null || true
( flock -w 10 9 || exit 1
    echo 'Reloading PHP FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9</tmp/fpmlock

To be clear: This script needs an .nvmrc file, containing the version of nodejs. If there is no .nvmrc file present, the nodejs version installed on the server will be used.

if the nodejs version is not present, it will be installed the first deployment. So now you will build in the version you specify.

This allows us to run multiple projects on a single server and still build in the correct target nodejs version.

Zero downtime deployment with nvm

bash
$CREATE_RELEASE()

cd $FORGE_RELEASE_DIRECTORY

$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader

# Detect if there is an .nvmrc file present, so we can use that
if [[ -f .nvmrc ]]; then

    source ~/.nvm/nvm.sh
    
    # Check if nvm use is "possible", if it's not installed, the version in the .nvmrc will be installed.
    if ! nvm use; then
      nvm install
    fi

    # Install and compile
    npm ci || npm install
    npm run build

    # revert to the old version
    echo "Reverting to nvm default version"
    nvm use default

else

    # No nvmrc found, using the server-wide version
    npm ci || npm install
    npm run buil
  
fi

if [ -f artisan ]; then
    $FORGE_PHP artisan optimize
    $FORGE_PHP artisan storage:link # important (!)
    $FORGE_PHP artisan migrate --force
    #$FORGE_PHP artisan wayfinder:generate # comment out if used
fi

$ACTIVATE_RELEASE()

$RESTART_QUEUES()

Restart deamons

bash
# Restart your daemon (replace 12345 with your daemon's ID)...
sudo supervisorctl restart daemon-12345:*