Files
kefu/im/deploy/baota-publish-admin.sh
T
2026-09-03 08:38:17 +08:00

68 lines
2.4 KiB
Bash

#!/usr/bin/env bash
# Publish the admin build without restarting Go or changing BaoTa/Nginx routes.
set -euo pipefail
umask 0022
archive=$(realpath -- "${1:?Usage: baota-publish-admin.sh /tmp/build.zip SHA256}")
expected=${2:?Missing archive SHA256}
[[ $EUID -eq 0 && $archive == /tmp/*.zip && -f $archive ]]
[[ $expected =~ ^[a-fA-F0-9]{64}$ ]]
[[ $(sha256sum "$archive" | cut -d ' ' -f 1) == "${expected,,}" ]]
root=/www/wwwroot/im.bchongw.com
releases=/www/wwwroot/xingyu-admin/releases
entry=$root/admin
[[ -L $entry ]]
previous=$(readlink -f -- "$entry")
[[ $previous == "$releases/"* && -f $previous/index.html ]]
[[ -f /www/server/panel/vhost/nginx/go_xingyu_im.conf ]]
/www/server/nginx/sbin/nginx -t
# Accept only relative archive paths. The ZIP is built locally and SHA-256
# checked above; reject path traversal before extracting into a new version.
while IFS= read -r item; do
case "$item" in
/*|*\\*|../*|*/../*|*/..|..|*:*) exit 1 ;;
esac
done < <(unzip -Z1 "$archive")
version=$(date +%Y%m%d-%H%M%S)
release=$releases/$version
next=$root/admin.next-$version
[[ ! -e $next && ! -L $next ]]
mkdir -m 0755 -- "$release"
unzip -q "$archive" -d "$release"
[[ -f $release/index.html && -f $release/_app.config.js ]]
grep -q '/admin/jse/' "$release/index.html"
grep -q '"/admin/v1"' "$release/_app.config.js"
# Keep the previous hashed chunks reachable for tabs opened before deployment.
# Never overwrite files in the new build or copy the old HTML/runtime config.
for directory in js jse css; do
[[ -d $release/$directory && -d $previous/$directory ]]
cp -an -- "$previous/$directory/." "$release/$directory/"
done
chown -R www:www -- "$release"
find "$release" -type d -exec chmod 0755 {} +
find "$release" -type f -exec chmod 0644 {} +
switched=false
rollback() {
if [[ $switched == true ]]; then
ln -s -- "$previous" "$next"
mv -Tf -- "$next" "$entry"
printf 'ROLLED_BACK=%s\n' "$previous" >&2
fi
}
trap rollback ERR
ln -s -- "$release" "$next"
mv -Tf -- "$next" "$entry"
switched=true
cmp -s "$release/index.html" <(curl -fsS --max-time 20 "https://im.bchongw.com/admin/?release=$version")
cmp -s "$release/_app.config.js" <(curl -fsS --max-time 20 "https://im.bchongw.com/admin/_app.config.js?release=$version")
curl -fsS --max-time 20 https://im.bchongw.com/healthz
curl -fsS --max-time 20 -o /dev/null https://im.bchongw.com/app/
trap - ERR
printf '\nADMIN_PUBLISHED=%s\nPREVIOUS_RELEASE=%s\nARCHIVE_SHA256=%s\n' "$release" "$previous" "${expected,,}"