68 lines
2.4 KiB
Bash
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,,}"
|