@@ -14,16 +14,17 @@ cmd_deploy() {
1414 info " Deploying $APP_TYPE to $SSH_USER @$SSH_HOST ..."
1515
1616 # Create remote directory
17- ssh -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " " mkdir -p $REMOTE_PATH "
17+ remote_exec " mkdir -p $REMOTE_PATH "
1818
1919 if [ " $APP_TYPE " = " backend" ]; then
20- deploy_backend
20+ deploy_backend " $SKIP_BUILD "
2121 else
2222 deploy_frontend " $SKIP_BUILD "
2323 fi
2424}
2525
2626deploy_backend () {
27+ local SKIP_BUILD=$1
2728 info " Deploying backend application..."
2829
2930 # Check if package.json exists
@@ -54,37 +55,52 @@ Deployment blocked to prevent port conflict."
5455 fi
5556
5657 if [ " $ZERO_DOWNTIME " = " true" ]; then
57- deploy_backend_zero_downtime
58+ deploy_backend_zero_downtime " $SKIP_BUILD "
5859 else
59- deploy_backend_legacy
60+ deploy_backend_legacy " $SKIP_BUILD "
6061 fi
6162}
6263
6364deploy_backend_legacy () {
65+ local SKIP_BUILD=$1
6466 info " Using legacy deployment (non-zero-downtime)..."
6567
6668 # Rsync application files
6769 info " Syncing files to server..."
68- rsync -avz --progress \
70+ remote_rsync -avz --progress \
6971 --exclude ' node_modules' \
7072 --exclude ' .env' \
7173 --exclude ' .git' \
7274 --exclude ' .gitignore' \
7375 --exclude ' shipnode.conf' \
7476 --exclude ' *.log' \
75- -e " ssh -p $SSH_PORT " \
7677 ./ " $SSH_USER @$SSH_HOST :$REMOTE_PATH /"
7778
7879 success " Files synced"
7980
80- # Install dependencies
81+ # Install dependencies and build
8182 info " Installing dependencies..."
82- ssh -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
83+ remote_exec bash << ENDSSH
8384 set -e
8485 cd $REMOTE_PATH
8586 $PKG_INSTALL_CMD
87+
88+ # Build if package.json has build script and not skipping
89+ if [ "$SKIP_BUILD " = false ]; then
90+ if jq -e '.scripts.build' package.json >/dev/null 2>&1; then
91+ echo "Building application..."
92+ $PKG_RUN_CMD
93+ fi
94+ fi
95+
96+ # Link .env into build/ for frameworks that resolve from build dir (AdonisJS)
97+ if [ -d build ] && [ -f .env ]; then
98+ ln -sf $REMOTE_PATH /.env build/.env
99+ fi
86100ENDSSH
87101
102+ success " Dependencies installed and build complete"
103+
88104 # Run pre-deploy hook
89105 if ! run_pre_deploy_hook " $REMOTE_PATH " ; then
90106 error " Pre-deploy hook failed, aborting deployment"
@@ -96,9 +112,9 @@ ENDSSH
96112 # Always regenerate ecosystem file to ensure it's up to date
97113 info " Generating PM2 ecosystem config..."
98114 generate_ecosystem_file " $PKG_MANAGER " " $PM2_APP_NAME " " $REMOTE_PATH " \
99- | ssh -T -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " " cat > $REMOTE_PATH /ecosystem.config.cjs"
115+ | remote_exec " cat > $REMOTE_PATH /ecosystem.config.cjs"
100116
101- ssh -T -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
117+ remote_exec bash << ENDSSH
102118 set -e
103119 pm2 startOrReload $REMOTE_PATH /ecosystem.config.cjs --update-env
104120 pm2 save
@@ -118,12 +134,13 @@ ENDSSH
118134}
119135
120136deploy_backend_zero_downtime () {
137+ local SKIP_BUILD=$1
121138 info " Using zero-downtime deployment..."
122139
123140 # Acquire deployment lock
124141 info " Acquiring deployment lock..."
125142 acquire_deploy_lock
126- trap release_deploy_lock EXIT
143+ trap ' release_deploy_lock; stop_ssh_multiplex ' EXIT
127144 success " Lock acquired"
128145
129146 # Generate release timestamp
@@ -142,21 +159,20 @@ deploy_backend_zero_downtime() {
142159
143160 # Rsync to new release directory
144161 info " Syncing files to release directory..."
145- rsync -avz --progress \
162+ remote_rsync -avz --progress \
146163 --exclude ' node_modules' \
147164 --exclude ' .env' \
148165 --exclude ' .git' \
149166 --exclude ' .gitignore' \
150167 --exclude ' shipnode.conf' \
151168 --exclude ' *.log' \
152- -e " ssh -p $SSH_PORT " \
153169 ./ " $SSH_USER @$SSH_HOST :$release_path /"
154170
155171 success " Files synced to $release_path "
156172
157- # Link shared resources and install dependencies
173+ # Link shared resources, install dependencies, and build
158174 info " Setting up release environment..."
159- ssh -T -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
175+ remote_exec bash << ENDSSH
160176 set -e
161177 cd $release_path
162178
@@ -167,6 +183,19 @@ deploy_backend_zero_downtime() {
167183
168184 # Install dependencies
169185 $PKG_INSTALL_CMD
186+
187+ # Build if package.json has build script and not skipping
188+ if [ "$SKIP_BUILD " = false ]; then
189+ if jq -e '.scripts.build' package.json >/dev/null 2>&1; then
190+ echo "Building application..."
191+ $PKG_RUN_CMD
192+ fi
193+ fi
194+
195+ # Link .env into build/ for frameworks that resolve from build dir (AdonisJS)
196+ if [ -d build ] && [ -f .env ]; then
197+ ln -sf $release_path /.env build/.env
198+ fi
170199ENDSSH
171200
172201 success " Release prepared"
@@ -186,9 +215,9 @@ ENDSSH
186215 # Always regenerate ecosystem file to ensure it's up to date
187216 info " Generating PM2 ecosystem config..."
188217 generate_ecosystem_file " $PKG_MANAGER " " $PM2_APP_NAME " " $REMOTE_PATH /current" \
189- | ssh -T -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " " cat > $REMOTE_PATH /shared/ecosystem.config.cjs"
218+ | remote_exec " cat > $REMOTE_PATH /shared/ecosystem.config.cjs"
190219
191- ssh -T -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
220+ remote_exec bash << ENDSSH
192221 set -e
193222 pm2 startOrReload $REMOTE_PATH /shared/ecosystem.config.cjs --update-env
194223 pm2 save
@@ -262,8 +291,7 @@ deploy_frontend_legacy() {
262291
263292 # Rsync build directory
264293 info " Syncing $BUILD_DIR to server..."
265- rsync -avz --progress --delete \
266- -e " ssh -p $SSH_PORT " \
294+ remote_rsync -avz --progress --delete \
267295 " $BUILD_DIR /" " $SSH_USER @$SSH_HOST :$REMOTE_PATH /"
268296
269297 success " Frontend deployed"
@@ -291,7 +319,7 @@ deploy_frontend_zero_downtime() {
291319
292320 # Acquire deployment lock
293321 acquire_deploy_lock
294- trap release_deploy_lock EXIT
322+ trap ' release_deploy_lock; stop_ssh_multiplex ' EXIT
295323
296324 # Generate release timestamp
297325 local timestamp=$( generate_release_timestamp)
@@ -304,8 +332,7 @@ deploy_frontend_zero_downtime() {
304332
305333 # Rsync build output to release directory
306334 info " Syncing $BUILD_DIR to release directory..."
307- rsync -avz --progress --delete \
308- -e " ssh -p $SSH_PORT " \
335+ remote_rsync -avz --progress --delete \
309336 " $BUILD_DIR /" " $SSH_USER @$SSH_HOST :$release_path /"
310337
311338 success " Files synced to $release_path "
@@ -340,7 +367,7 @@ deploy_frontend_zero_downtime() {
340367configure_caddy_backend () {
341368 info " Configuring Caddy reverse proxy for $DOMAIN ..."
342369
343- ssh -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
370+ remote_exec bash << ENDSSH
344371 set -e
345372
346373 # Create conf.d directory for per-app configs
@@ -394,7 +421,7 @@ configure_caddy_frontend() {
394421 # Derive app name from remote path for config file naming
395422 local APP_NAME=$( basename " $REMOTE_PATH " )
396423
397- ssh -p " $SSH_PORT " " $SSH_USER @ $SSH_HOST " bash << ENDSSH
424+ remote_exec bash << ENDSSH
398425 set -e
399426
400427 # Create conf.d directory for per-app configs
0 commit comments