Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

130 rader
2.9 KiB

  1. #!/usr/bin/env bash
  2. set -Eeuo pipefail
  3. APP_NAME="${APP_NAME:-pc_nuxt}"
  4. BRANCH="${BRANCH:-}"
  5. NUXT_PUBLIC_API_BASE="${NUXT_PUBLIC_API_BASE:-https://api.aionline.cc}"
  6. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  7. export NUXT_PUBLIC_API_BASE
  8. cd "$SCRIPT_DIR"
  9. log() {
  10. printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
  11. }
  12. require_command() {
  13. if ! command -v "$1" >/dev/null 2>&1; then
  14. log "Missing command: $1"
  15. exit 1
  16. fi
  17. }
  18. validate_api_base() {
  19. node - "$NUXT_PUBLIC_API_BASE" <<'NODE'
  20. const value = process.argv[2]
  21. let url
  22. try {
  23. url = new URL(value)
  24. } catch {
  25. console.error(`[pc_nuxt] Invalid NUXT_PUBLIC_API_BASE: ${value || '(empty)'}`)
  26. process.exit(1)
  27. }
  28. const hostname = url.hostname.toLowerCase()
  29. const isPrivate = hostname === 'localhost'
  30. || hostname === '0.0.0.0'
  31. || /^127\./.test(hostname)
  32. || hostname === '[::1]'
  33. || hostname.endsWith('.local')
  34. || /^10\./.test(hostname)
  35. || /^192\.168\./.test(hostname)
  36. || /^169\.254\./.test(hostname)
  37. || /^172\.(1[6-9]|2\d|3[01])\./.test(hostname)
  38. if (!['http:', 'https:'].includes(url.protocol) || isPrivate) {
  39. console.error(`[pc_nuxt] Production API must be a public http(s) URL: ${value}`)
  40. process.exit(1)
  41. }
  42. NODE
  43. }
  44. validate_tls_security() {
  45. if [ "${NODE_TLS_REJECT_UNAUTHORIZED:-}" = "0" ]; then
  46. log "Refusing deployment: NODE_TLS_REJECT_UNAUTHORIZED=0 disables TLS certificate verification."
  47. exit 1
  48. fi
  49. }
  50. ensure_clean_worktree() {
  51. if [ -n "$(git status --porcelain)" ]; then
  52. log "Working tree is not clean. Commit/stash/clean changes before deploy."
  53. git status --short
  54. exit 1
  55. fi
  56. }
  57. resolve_branch() {
  58. if [ -z "$BRANCH" ]; then
  59. BRANCH="$(git rev-parse --abbrev-ref HEAD)"
  60. fi
  61. if [ "$BRANCH" = "HEAD" ]; then
  62. log "Cannot detect git branch. Please run with BRANCH=main ./restart.sh"
  63. exit 1
  64. fi
  65. }
  66. pull_latest_code() {
  67. log "Pull latest code from origin/$BRANCH"
  68. ensure_clean_worktree
  69. git fetch origin "$BRANCH"
  70. git pull --ff-only origin "$BRANCH"
  71. }
  72. install_dependencies() {
  73. log "Install dependencies"
  74. pnpm install --frozen-lockfile
  75. }
  76. build_app() {
  77. log "Build Nuxt app"
  78. pnpm run build
  79. if [ ! -f ".output/server/index.mjs" ]; then
  80. log "Build output missing: .output/server/index.mjs"
  81. exit 1
  82. fi
  83. }
  84. restart_app() {
  85. log "Reload app with pm2 ecosystem config"
  86. mkdir -p logs
  87. APP_NAME="$APP_NAME" pm2 startOrReload ecosystem.config.cjs --env production --update-env
  88. pm2 save >/dev/null 2>&1 || true
  89. }
  90. main() {
  91. require_command git
  92. require_command node
  93. require_command pnpm
  94. require_command pm2
  95. validate_tls_security
  96. validate_api_base
  97. resolve_branch
  98. log "Deploy start: $APP_NAME"
  99. log "Node: $(node -v 2>/dev/null || echo 'unknown')"
  100. log "pnpm: $(pnpm -v)"
  101. log "pm2: $(pm2 -v)"
  102. log "API: $NUXT_PUBLIC_API_BASE"
  103. pull_latest_code
  104. install_dependencies
  105. build_app
  106. restart_app
  107. log "Deploy done: $APP_NAME"
  108. }
  109. main "$@"