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
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/fpmlockAs 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):
- Install NVM:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash(make sure you use the latest tag) - Run the following command to make nvm available in the terminal:
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 nvmDeploy script with NVM
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/fpmlockTo 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
$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
# Restart your daemon (replace 12345 with your daemon's ID)...
sudo supervisorctl restart daemon-12345:*