Skip to content

Deploy

Deploy #33

Workflow file for this run

name: Deploy
# Triggers:
# - Automatically after CI workflow completes successfully on main
# - Manually via workflow_dispatch for hotfixes or rollbacks
on:
workflow_run:
workflows: ["CI"]
types: [completed]
branches: [main]
workflow_dispatch:
inputs:
environment:
description: "Target environment"
required: true
default: "production"
type: choice
options: [production, staging]
run_migrations:
description: "Run database migrations"
required: true
default: true
type: boolean
run_scout_import:
description: "Re-index Typesense (slow — only if schema changed)"
required: true
default: false
type: boolean
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false # never cancel an in-flight deploy
jobs:
deploy:
name: Deploy to ${{ github.event.inputs.environment || 'production' }}
runs-on: ubuntu-latest
# Only deploy if CI succeeded (or triggered manually)
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
environment: ${{ github.event.inputs.environment || 'production' }}
steps:
- name: Checkout
uses: actions/checkout@v4
# ── Build frontend assets on CI runner (npm not available on server) ──
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
tools: composer:v2
coverage: none
- name: Install PHP dependencies
run: composer install --no-dev --no-interaction --no-scripts --prefer-dist
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install Node dependencies
run: npm ci
- name: Build frontend assets
run: npm run build
# ── SSH deploy ──────────────────────────────────────────
# Required GitHub secrets:
# DEPLOY_HOST — server hostname or IP (e.g. aljebal-albeedos.com)
# DEPLOY_PORT — SSH port (e.g. 21098)
# DEPLOY_USER — SSH username (e.g. aljedkrq)
# DEPLOY_KEY — private SSH key (RSA or Ed25519)
# DEPLOY_PATH — absolute path to the app on the server
# DEPLOY_PHP — path to PHP binary on server (e.g. /home/aljedkrq/php84)
# ────────────────────────────────────────────────────────
- name: Setup SSH agent
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
- name: Add server to known hosts
run: ssh-keyscan -p ${{ secrets.DEPLOY_PORT }} -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts
- name: Pull latest code & install PHP dependencies
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
DEPLOY_PHP: ${{ secrets.DEPLOY_PHP }}
run: |
ssh -p $DEPLOY_PORT $DEPLOY_USER@$DEPLOY_HOST << EOF
set -e
PHP="${DEPLOY_PHP:-php}"
cd $DEPLOY_PATH
echo "==> Pulling latest code"
git pull origin main
echo "==> Installing PHP dependencies"
COMPOSER=\$(which composer 2>/dev/null || echo "\$HOME/bin/composer")
\$PHP \$COMPOSER install --no-dev --no-interaction --optimize-autoloader --prefer-dist
EOF
- name: Upload built assets
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
run: |
rsync -az --delete -e "ssh -p $DEPLOY_PORT" \
public/build/ \
$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/public/build/
- name: Finalize deploy
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
DEPLOY_PHP: ${{ secrets.DEPLOY_PHP }}
RUN_MIGRATIONS: ${{ github.event.inputs.run_migrations || 'true' }}
RUN_SCOUT_IMPORT: ${{ github.event.inputs.run_scout_import || 'false' }}
run: |
ssh -p $DEPLOY_PORT $DEPLOY_USER@$DEPLOY_HOST << EOF
set -e
PHP="${DEPLOY_PHP:-php}"
cd $DEPLOY_PATH
echo "==> Caching configuration"
\$PHP artisan config:cache
\$PHP artisan route:cache
\$PHP artisan view:cache
\$PHP artisan event:cache
if [ "\$RUN_MIGRATIONS" = "true" ]; then
echo "==> Running database migrations"
\$PHP artisan migrate --force
fi
echo "==> Restarting queue workers"
\$PHP artisan queue:restart
if [ "\$RUN_SCOUT_IMPORT" = "true" ]; then
echo "==> Re-indexing Typesense"
\$PHP artisan scout:flush "App\Domain\Product\Models\Product"
\$PHP artisan scout:import "App\Domain\Product\Models\Product"
\$PHP artisan scout:flush "App\Domain\Category\Models\Category"
\$PHP artisan scout:import "App\Domain\Category\Models\Category"
\$PHP artisan scout:flush "App\Domain\Order\Models\Order"
\$PHP artisan scout:import "App\Domain\Order\Models\Order"
fi
echo "==> Done (\$(ls $DEPLOY_PATH/public/build/assets/ | wc -l) assets)"
EOF
- name: Notify on failure
if: failure()
run: |
echo "::error::Deployment failed. Check the logs above."
# Add Slack/email notification here if needed