Files
jabali-panel/scripts/deploy.sh

324 lines
8.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DEPLOY_HOST="${DEPLOY_HOST:-192.168.100.50}"
DEPLOY_USER="${DEPLOY_USER:-root}"
DEPLOY_PATH="${DEPLOY_PATH:-/var/www/jabali}"
WWW_USER="${WWW_USER:-www-data}"
NPM_CACHE_DIR="${NPM_CACHE_DIR:-}"
GITEA_REMOTE="${GITEA_REMOTE:-gitea}"
GITEA_URL="${GITEA_URL:-}"
GITHUB_REMOTE="${GITHUB_REMOTE:-origin}"
GITHUB_URL="${GITHUB_URL:-}"
PUSH_BRANCH="${PUSH_BRANCH:-}"
SKIP_SYNC=0
SKIP_COMPOSER=0
SKIP_NPM=0
SKIP_MIGRATE=0
SKIP_CACHE=0
DELETE_REMOTE=0
DRY_RUN=0
PUSH_GITEA=0
PUSH_GITHUB=0
SET_VERSION=""
usage() {
cat <<'EOF'
Usage: scripts/deploy.sh [options]
Options:
--host HOST Remote host (default: 192.168.100.50)
--user USER SSH user (default: root)
--path PATH Remote path (default: /var/www/jabali)
--www-user USER Remote runtime user (default: www-data)
--skip-sync Skip rsync sync step
--skip-composer Skip composer install
--skip-npm Skip npm install/build
--skip-migrate Skip php artisan migrate
--skip-cache Skip cache clear/rebuild
--delete Pass --delete to rsync (dangerous)
--dry-run Dry-run rsync only
--push-gitea Push current branch to Gitea before deploy
--gitea-remote NAME Gitea git remote name (default: gitea)
--gitea-url URL Push to this URL instead of a named remote
--push-github Push current branch to GitHub before deploy
--github-remote NAME GitHub git remote name (default: origin)
--github-url URL Push to this URL instead of a named remote
--version VALUE Set VERSION to a specific value before push
-h, --help Show this help
Environment overrides:
DEPLOY_HOST, DEPLOY_USER, DEPLOY_PATH, WWW_USER, NPM_CACHE_DIR, GITEA_REMOTE, GITEA_URL, GITHUB_REMOTE, GITHUB_URL, PUSH_BRANCH
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--host)
DEPLOY_HOST="$2"
shift 2
;;
--user)
DEPLOY_USER="$2"
shift 2
;;
--path)
DEPLOY_PATH="$2"
shift 2
;;
--www-user)
WWW_USER="$2"
shift 2
;;
--skip-sync)
SKIP_SYNC=1
shift
;;
--skip-composer)
SKIP_COMPOSER=1
shift
;;
--skip-npm)
SKIP_NPM=1
shift
;;
--skip-migrate)
SKIP_MIGRATE=1
shift
;;
--skip-cache)
SKIP_CACHE=1
shift
;;
--delete)
DELETE_REMOTE=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--push-gitea)
PUSH_GITEA=1
shift
;;
--gitea-remote)
GITEA_REMOTE="$2"
shift 2
;;
--gitea-url)
GITEA_URL="$2"
shift 2
;;
--push-github)
PUSH_GITHUB=1
shift
;;
--github-remote)
GITHUB_REMOTE="$2"
shift 2
;;
--github-url)
GITHUB_URL="$2"
shift 2
;;
--version)
SET_VERSION="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1"
usage
exit 1
;;
esac
done
REMOTE="${DEPLOY_USER}@${DEPLOY_HOST}"
ensure_clean_worktree() {
if ! git -C "$ROOT_DIR" diff --quiet || ! git -C "$ROOT_DIR" diff --cached --quiet; then
echo "Working tree is dirty. Commit or stash changes before pushing."
exit 1
fi
}
get_current_version() {
sed -n 's/^VERSION=//p' "$ROOT_DIR/VERSION"
}
bump_version() {
local current new base num
current="$(get_current_version)"
if [[ -n "$SET_VERSION" ]]; then
new="$SET_VERSION"
else
if [[ "$current" =~ ^(.+-rc)([0-9]+)?$ ]]; then
base="${BASH_REMATCH[1]}"
num="${BASH_REMATCH[2]}"
if [[ -z "$num" ]]; then
num=1
else
num=$((num + 1))
fi
new="${base}${num}"
elif [[ "$current" =~ ^(.+?)([0-9]+)$ ]]; then
new="${BASH_REMATCH[1]}$((BASH_REMATCH[2] + 1))"
else
echo "Cannot auto-bump VERSION from '$current'. Use --version to set it explicitly."
exit 1
fi
fi
if [[ "$new" == "$current" ]]; then
echo "VERSION is already '$current'. Use --version to set a new value."
exit 1
fi
printf 'VERSION=%s\n' "$new" > "$ROOT_DIR/VERSION"
perl -0pi -e "s/JABALI_VERSION=\\\"\\$\\{JABALI_VERSION:-[^\\\"]+\\}\\\"/JABALI_VERSION=\\\"\\$\\{JABALI_VERSION:-$new\\}\\\"/g" "$ROOT_DIR/install.sh"
git -C "$ROOT_DIR" add VERSION install.sh
if ! git -C "$ROOT_DIR" diff --cached --quiet; then
git -C "$ROOT_DIR" commit -m "Bump VERSION to $new"
fi
}
prepare_push() {
ensure_clean_worktree
bump_version
}
push_remote() {
local label="$1"
local remote_name="$2"
local remote_url="$3"
local target
if [[ -n "$remote_url" ]]; then
target="$remote_url"
else
if ! git -C "$ROOT_DIR" remote get-url "$remote_name" >/dev/null 2>&1; then
echo "$label remote '$remote_name' not found. Use --${label,,}-url or --${label,,}-remote."
exit 1
fi
target="$remote_name"
fi
if [[ -z "$PUSH_BRANCH" ]]; then
PUSH_BRANCH="$(git -C "$ROOT_DIR" rev-parse --abbrev-ref HEAD)"
fi
git -C "$ROOT_DIR" push "$target" "$PUSH_BRANCH"
}
rsync_project() {
local -a rsync_opts
rsync_opts=(-az --info=progress2)
if [[ "$DELETE_REMOTE" -eq 1 ]]; then
rsync_opts+=(--delete)
fi
if [[ "$DRY_RUN" -eq 1 ]]; then
rsync_opts+=(--dry-run)
fi
rsync "${rsync_opts[@]}" \
--exclude ".git/" \
--exclude "node_modules/" \
--exclude "vendor/" \
--exclude "storage/" \
--exclude "bootstrap/cache/" \
--exclude "public/build/" \
--exclude ".env" \
--exclude ".env.*" \
--exclude "database/*.sqlite" \
--exclude "database/*.sqlite-wal" \
--exclude "database/*.sqlite-shm" \
"$ROOT_DIR/" \
"${REMOTE}:${DEPLOY_PATH}/"
}
remote_run() {
ssh -o StrictHostKeyChecking=no "$REMOTE" "bash -lc '$1'"
}
remote_run_www() {
ssh -o StrictHostKeyChecking=no "$REMOTE" "bash -lc 'cd \"$DEPLOY_PATH\" && sudo -u \"$WWW_USER\" -H bash -lc \"$1\"'"
}
ensure_remote_permissions() {
local parent_dir
parent_dir="$(dirname "$DEPLOY_PATH")"
if [[ -z "$NPM_CACHE_DIR" ]]; then
NPM_CACHE_DIR="${parent_dir}/.npm"
fi
remote_run "mkdir -p \"$DEPLOY_PATH/storage\" \"$DEPLOY_PATH/bootstrap/cache\" \"$DEPLOY_PATH/public/build\" \"$DEPLOY_PATH/node_modules\" \"$DEPLOY_PATH/database\" \"$NPM_CACHE_DIR\""
remote_run "chown -R \"$WWW_USER\":\"$WWW_USER\" \"$DEPLOY_PATH/storage\" \"$DEPLOY_PATH/bootstrap/cache\" \"$DEPLOY_PATH/public\" \"$DEPLOY_PATH/public/build\" \"$DEPLOY_PATH/node_modules\" \"$DEPLOY_PATH/database\" \"$NPM_CACHE_DIR\""
remote_run "if [[ -f \"$DEPLOY_PATH/auth.json\" ]]; then chown \"$WWW_USER\":\"$WWW_USER\" \"$DEPLOY_PATH/auth.json\" && chmod 600 \"$DEPLOY_PATH/auth.json\"; fi"
}
echo "Deploying to ${REMOTE}:${DEPLOY_PATH}"
if [[ "$PUSH_GITEA" -eq 1 ]]; then
prepare_push
echo "Pushing to Gitea..."
push_remote "Gitea" "$GITEA_REMOTE" "$GITEA_URL"
fi
if [[ "$PUSH_GITHUB" -eq 1 ]]; then
if [[ "$PUSH_GITEA" -ne 1 ]]; then
prepare_push
fi
echo "Pushing to GitHub..."
push_remote "GitHub" "$GITHUB_REMOTE" "$GITHUB_URL"
fi
if [[ "$SKIP_SYNC" -eq 0 ]]; then
echo "Syncing project files..."
rsync_project
fi
if [[ "$DRY_RUN" -eq 1 ]]; then
echo "Dry run complete. No remote commands executed."
exit 0
fi
echo "Ensuring remote permissions..."
ensure_remote_permissions
if [[ "$SKIP_COMPOSER" -eq 0 ]]; then
echo "Installing composer dependencies..."
remote_run_www "composer install --no-interaction --prefer-dist --optimize-autoloader"
fi
if [[ "$SKIP_NPM" -eq 0 ]]; then
echo "Building frontend assets..."
remote_run_www "npm ci"
remote_run_www "npm run build"
fi
if [[ "$SKIP_MIGRATE" -eq 0 ]]; then
echo "Running migrations..."
remote_run_www "php artisan migrate --force"
fi
if [[ "$SKIP_CACHE" -eq 0 ]]; then
echo "Refreshing caches..."
remote_run_www "php artisan optimize:clear"
remote_run_www "php artisan config:cache"
remote_run_www "php artisan route:cache"
remote_run_www "php artisan view:cache"
fi
echo "Deploy complete."