Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

126 linhas
2.8 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. resolve_branch() {
  51. if [ -z "$BRANCH" ]; then
  52. BRANCH="$(git rev-parse --abbrev-ref HEAD)"
  53. fi
  54. if [ "$BRANCH" = "HEAD" ]; then
  55. log "Cannot detect git branch. Please run with BRANCH=main ./restart.sh"
  56. exit 1
  57. fi
  58. }
  59. sync_latest_code() {
  60. log "Force sync code from origin/$BRANCH"
  61. git fetch origin "$BRANCH"
  62. if [ -n "$(git status --porcelain)" ]; then
  63. log "Discard local working tree changes before deploy"
  64. git status --short
  65. fi
  66. git reset --hard "origin/$BRANCH"
  67. git clean -fd
  68. }
  69. install_dependencies() {
  70. log "Install dependencies"
  71. pnpm install --frozen-lockfile
  72. }
  73. build_app() {
  74. log "Build Nuxt app"
  75. pnpm run build
  76. if [ ! -f ".output/server/index.mjs" ]; then
  77. log "Build output missing: .output/server/index.mjs"
  78. exit 1
  79. fi
  80. }
  81. restart_app() {
  82. log "Reload app with pm2 ecosystem config"
  83. mkdir -p logs
  84. APP_NAME="$APP_NAME" pm2 startOrReload ecosystem.config.cjs --env production --update-env
  85. pm2 save >/dev/null 2>&1 || true
  86. }
  87. main() {
  88. require_command git
  89. require_command node
  90. require_command pnpm
  91. require_command pm2
  92. validate_tls_security
  93. validate_api_base
  94. resolve_branch
  95. log "Deploy start: $APP_NAME"
  96. log "Node: $(node -v 2>/dev/null || echo 'unknown')"
  97. log "pnpm: $(pnpm -v)"
  98. log "pm2: $(pm2 -v)"
  99. log "API: $NUXT_PUBLIC_API_BASE"
  100. sync_latest_code
  101. install_dependencies
  102. build_app
  103. restart_app
  104. log "Deploy done: $APP_NAME"
  105. }
  106. main "$@"