285 lines
6.8 KiB
Bash
285 lines
6.8 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
PROJECTS_DIR="${PROJECTS_DIR:-/home/deploy/projects}"
|
|
DOMAIN="${DOMAIN:-localhost}"
|
|
PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-http://${DOMAIN}}"
|
|
TARGET=""
|
|
NGINX_ONLY=false
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--nginx-only) NGINX_ONLY=true ;;
|
|
*) TARGET="$arg" ;;
|
|
esac
|
|
done
|
|
|
|
safe_name() {
|
|
echo "$1" | sed 's/[^A-Za-z0-9._-]/-/g'
|
|
}
|
|
|
|
env_get() {
|
|
local file="$1"
|
|
local key="$2"
|
|
|
|
if [ -f "$file" ]; then
|
|
grep -E "^${key}=" "$file" | tail -n1 | cut -d '=' -f2- | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//"
|
|
fi
|
|
}
|
|
|
|
env_set() {
|
|
local file="$1"
|
|
local key="$2"
|
|
local value="$3"
|
|
|
|
touch "$file"
|
|
|
|
if grep -qE "^${key}=" "$file"; then
|
|
sed -i "s|^${key}=.*|${key}=${value}|g" "$file"
|
|
else
|
|
echo "${key}=${value}" >> "$file"
|
|
fi
|
|
}
|
|
|
|
detect_type() {
|
|
local project_dir="$1"
|
|
|
|
if [ ! -f "$project_dir/artisan" ]; then
|
|
echo "nao-laravel"
|
|
return
|
|
fi
|
|
|
|
if [ -f "$project_dir/package.json" ]; then
|
|
if grep -qiE '"(@inertiajs/vue3|vue|@vitejs/plugin-vue)"' "$project_dir/package.json"; then
|
|
echo "laravel-vue"
|
|
elif grep -qiE '"vite"|'"'@laravel/vite-plugin'" "$project_dir/package.json"; then
|
|
echo "laravel-blade-vite"
|
|
else
|
|
echo "laravel-node"
|
|
fi
|
|
else
|
|
echo "laravel-blade"
|
|
fi
|
|
}
|
|
|
|
has_npm_build() {
|
|
node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.build ? 0 : 1)" >/dev/null 2>&1
|
|
}
|
|
|
|
reload_nginx_if_running() {
|
|
if pgrep nginx >/dev/null 2>&1; then
|
|
nginx -t && nginx -s reload
|
|
fi
|
|
}
|
|
|
|
generate_nginx_config() {
|
|
local project="$1"
|
|
local project_dir="$2"
|
|
local safe_project
|
|
safe_project="$(safe_name "$project")"
|
|
|
|
cat > "/etc/nginx/sites-dynamic/${safe_project}.conf" <<EOF
|
|
# Gerado automaticamente pela Laravel Stack
|
|
# Projeto: ${project}
|
|
# Pasta: ${project_dir}
|
|
|
|
location = /${project} {
|
|
return 301 /${project}/;
|
|
}
|
|
|
|
location ^~ /${project}/ {
|
|
alias ${project_dir}/public/;
|
|
index index.php index.html;
|
|
try_files \$uri \$uri/ /${project}/index.php?\$query_string;
|
|
}
|
|
|
|
location ~ ^/${project}/index\.php(/|$) {
|
|
internal;
|
|
|
|
include fastcgi_params;
|
|
fastcgi_pass 127.0.0.1:9000;
|
|
fastcgi_index index.php;
|
|
|
|
fastcgi_param SCRIPT_FILENAME ${project_dir}/public/index.php;
|
|
fastcgi_param DOCUMENT_ROOT ${project_dir}/public;
|
|
|
|
# Importante para Laravel funcionar em subpasta /${project}
|
|
fastcgi_param SCRIPT_NAME /${project}/index.php;
|
|
fastcgi_param PHP_SELF /${project}/index.php;
|
|
fastcgi_param REQUEST_URI \$request_uri;
|
|
|
|
fastcgi_param HTTPS \$fastcgi_https;
|
|
fastcgi_read_timeout 300;
|
|
fastcgi_buffer_size 32k;
|
|
fastcgi_buffers 16 16k;
|
|
}
|
|
|
|
location ~ ^/${project}/.*\.php$ {
|
|
return 404;
|
|
}
|
|
EOF
|
|
}
|
|
|
|
deploy_project() {
|
|
local project="$1"
|
|
local project_dir="$PROJECTS_DIR/$project"
|
|
local safe_project
|
|
local type
|
|
local env_file
|
|
local project_url
|
|
local run_migrations
|
|
|
|
safe_project="$(safe_name "$project")"
|
|
env_file="$project_dir/.env"
|
|
project_url="${PUBLIC_BASE_URL%/}/${project}"
|
|
|
|
echo ""
|
|
echo "================================================"
|
|
echo " Deployando: $project"
|
|
echo " URL: $project_url"
|
|
echo "================================================"
|
|
|
|
if [ ! -d "$project_dir" ]; then
|
|
echo "✗ Pasta $project_dir não encontrada"
|
|
return 1
|
|
fi
|
|
|
|
if [ ! -f "$project_dir/artisan" ]; then
|
|
echo "⚠ $project ignorado: não encontrei artisan. Não parece Laravel."
|
|
return 0
|
|
fi
|
|
|
|
if [ ! -f "$project_dir/public/index.php" ]; then
|
|
echo "✗ $project sem public/index.php"
|
|
return 1
|
|
fi
|
|
|
|
type="$(detect_type "$project_dir")"
|
|
echo "$type" > "$project_dir/.project-type"
|
|
|
|
echo "→ Tipo identificado: $type"
|
|
|
|
generate_nginx_config "$project" "$project_dir"
|
|
echo "✓ Nginx criado: /${project}"
|
|
|
|
if [ "$NGINX_ONLY" = "true" ]; then
|
|
return 0
|
|
fi
|
|
|
|
cd "$project_dir"
|
|
|
|
if [ ! -f "$env_file" ] && [ -f "$project_dir/.env.example" ]; then
|
|
echo "→ .env não encontrado, copiando .env.example"
|
|
cp "$project_dir/.env.example" "$env_file"
|
|
fi
|
|
|
|
if [ -f "$env_file" ]; then
|
|
env_set "$env_file" "APP_URL" "$project_url"
|
|
env_set "$env_file" "ASSET_URL" "/${project}"
|
|
else
|
|
echo "⚠ Sem .env. Crie $env_file antes de usar banco/cache em produção."
|
|
fi
|
|
|
|
echo "→ composer install..."
|
|
composer install \
|
|
--no-dev \
|
|
--prefer-dist \
|
|
--no-interaction \
|
|
--optimize-autoloader
|
|
|
|
if [ -f "$env_file" ]; then
|
|
app_key="$(env_get "$env_file" "APP_KEY")"
|
|
if [ -z "$app_key" ] || [ "$app_key" = "null" ]; then
|
|
echo "→ Gerando APP_KEY..."
|
|
php artisan key:generate --force
|
|
fi
|
|
fi
|
|
|
|
echo "→ Limpando caches Laravel..."
|
|
php artisan optimize:clear || true
|
|
|
|
if [ -f "package.json" ]; then
|
|
echo "→ Dependências front-end encontradas."
|
|
|
|
if [ -f "package-lock.json" ]; then
|
|
echo "→ npm ci..."
|
|
npm ci --no-audit --no-fund
|
|
else
|
|
echo "→ npm install..."
|
|
npm install --no-audit --no-fund
|
|
fi
|
|
|
|
if has_npm_build; then
|
|
echo "→ npm run build..."
|
|
ASSET_URL="/${project}" VITE_BASE="/${project}/build/" npm run build
|
|
else
|
|
echo "⚠ package.json sem script build. Pulando build."
|
|
fi
|
|
else
|
|
echo "→ Sem package.json. Projeto identificado como Blade/PHP puro."
|
|
fi
|
|
|
|
echo "→ storage:link..."
|
|
php artisan storage:link || true
|
|
|
|
run_migrations="$(env_get "$env_file" "RUN_MIGRATIONS")"
|
|
if [ "$run_migrations" = "true" ]; then
|
|
echo "→ RUN_MIGRATIONS=true, rodando migrations..."
|
|
php artisan migrate --force
|
|
fi
|
|
|
|
echo "→ Otimizando Laravel..."
|
|
php artisan config:cache || true
|
|
php artisan route:cache || {
|
|
echo "⚠ route:cache falhou, limpando cache de rotas."
|
|
php artisan route:clear || true
|
|
}
|
|
php artisan view:cache || true
|
|
php artisan event:cache || true
|
|
|
|
echo "→ Ajustando permissões..."
|
|
mkdir -p storage bootstrap/cache
|
|
chown -R www-data:www-data storage bootstrap/cache public || true
|
|
chmod -R ug+rwX storage bootstrap/cache || true
|
|
|
|
echo "✓ $project deployado em /$project"
|
|
}
|
|
|
|
deploy_all() {
|
|
local found=0
|
|
|
|
for project_dir in "$PROJECTS_DIR"/*/; do
|
|
[ -d "$project_dir" ] || continue
|
|
project="$(basename "$project_dir")"
|
|
found=$((found + 1))
|
|
deploy_project "$project" || true
|
|
done
|
|
|
|
if [ "$found" -eq 0 ]; then
|
|
echo "Nenhum projeto encontrado em $PROJECTS_DIR"
|
|
fi
|
|
}
|
|
|
|
mkdir -p "$PROJECTS_DIR" /etc/nginx/sites-dynamic
|
|
|
|
if [ -n "$TARGET" ]; then
|
|
deploy_project "$TARGET"
|
|
else
|
|
deploy_all
|
|
fi
|
|
|
|
echo ""
|
|
echo "→ Recarregando Nginx se estiver em execução..."
|
|
reload_nginx_if_running || true
|
|
|
|
echo ""
|
|
echo "================================================"
|
|
echo " Deploy concluído!"
|
|
for project_dir in "$PROJECTS_DIR"/*/; do
|
|
[ -d "$project_dir" ] || continue
|
|
project="$(basename "$project_dir")"
|
|
type="$(cat "$project_dir/.project-type" 2>/dev/null || echo '?')"
|
|
echo " ✓ /$project → $type"
|
|
done
|
|
echo "================================================"
|