You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

130 rivejä
2.9 KiB

  1. #!/usr/bin/env bash
  2. if [ -z "${BASH_VERSION:-}" ]; then
  3. exec bash "$0" "$@"
  4. fi
  5. set -Eeuo pipefail
  6. APP_NAME="${APP_NAME:-pc_nuxt}"
  7. BRANCH="${BRANCH:-}"
  8. NUXT_PUBLIC_API_BASE="${NUXT_PUBLIC_API_BASE:-https://api.aionline.cc}"
  9. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  10. export NUXT_PUBLIC_API_BASE
  11. cd "$SCRIPT_DIR"
  12. log() {
  13. printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
  14. }
  15. require_command() {
  16. if ! command -v "$1" >/dev/null 2>&1; then
  17. log "Missing command: $1"
  18. exit 1
  19. fi
  20. }
  21. validate_api_base() {
  22. node - "$NUXT_PUBLIC_API_BASE" <<'NODE'
  23. const value = process.argv[2]
  24. let url
  25. try {
  26. url = new URL(value)
  27. } catch {
  28. console.error(`[pc_nuxt] Invalid NUXT_PUBLIC_API_BASE: ${value || '(empty)'}`)
  29. process.exit(1)
  30. }
  31. const hostname = url.hostname.toLowerCase()
  32. const isPrivate = hostname === 'localhost'
  33. || hostname === '0.0.0.0'
  34. || /^127\./.test(hostname)
  35. || hostname === '[::1]'
  36. || hostname.endsWith('.local')
  37. || /^10\./.test(hostname)
  38. || /^192\.168\./.test(hostname)
  39. || /^169\.254\./.test(hostname)
  40. || /^172\.(1[6-9]|2\d|3[01])\./.test(hostname)
  41. if (!['http:', 'https:'].includes(url.protocol) || isPrivate) {
  42. console.error(`[pc_nuxt] Production API must be a public http(s) URL: ${value}`)
  43. process.exit(1)
  44. }
  45. NODE
  46. }
  47. validate_tls_security() {
  48. if [ "${NODE_TLS_REJECT_UNAUTHORIZED:-}" = "0" ]; then
  49. log "Refusing deployment: NODE_TLS_REJECT_UNAUTHORIZED=0 disables TLS certificate verification."
  50. exit 1
  51. fi
  52. }
  53. resolve_branch() {
  54. if [ -z "$BRANCH" ]; then
  55. BRANCH="$(git rev-parse --abbrev-ref HEAD)"
  56. fi
  57. if [ "$BRANCH" = "HEAD" ]; then
  58. log "Cannot detect git branch. Please run with BRANCH=main ./restart.sh"
  59. exit 1
  60. fi
  61. }
  62. sync_latest_code() {
  63. log "Force sync code from origin/$BRANCH"
  64. git fetch origin "$BRANCH"
  65. if [ -n "$(git status --porcelain)" ]; then
  66. log "Discard local working tree changes before deploy"
  67. git status --short
  68. fi
  69. git reset --hard "origin/$BRANCH"
  70. git clean -fd
  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. sync_latest_code
  104. install_dependencies
  105. build_app
  106. restart_app
  107. log "Deploy done: $APP_NAME"
  108. }
  109. main "$@"