CaiWuXiTong/deploy/install-release-protection.sh

44 lines
2.0 KiB
Bash

#!/bin/sh
# Caller holds the production deployment lock. Does not restart any service.
set -eu
REMOTE_DIR="${1:-/opt/caiwuxitong}"
SOURCE_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
LEGACY_STUB="$SOURCE_DIR/retired-activation.sh"
[ "$(id -u)" -eq 0 ] || { echo 'Release protection must be installed as root' >&2; exit 1; }
[ -f "$LEGACY_STUB" ] || { echo 'Missing retired activation stub' >&2; exit 1; }
is_immutable() { lsattr -d "$1" 2>/dev/null | awk '{print $1}' | grep -q i; }
needs_install=0
for legacy in activate-release.sh activate-incremental-release.sh; do
if cmp -s "$LEGACY_STUB" "$REMOTE_DIR/$legacy" && is_immutable "$REMOTE_DIR/$legacy"; then
continue
fi
if is_immutable "$REMOTE_DIR/$legacy"; then
echo "Unexpected immutable legacy entry point: $legacy; verify it before changing protection" >&2
exit 1
fi
needs_install=1
done
[ "$needs_install" -eq 1 ] || exit 0
# Test support on an owned temporary file before touching either entry point.
probe="$(mktemp "$REMOTE_DIR/.release-protection.XXXXXX")"
cleanup_probe() { chattr -i "$probe" 2>/dev/null || true; rm -f "$probe"; }
trap cleanup_probe EXIT
chattr +i "$probe" || { echo 'Filesystem cannot protect legacy entry points; no application was changed' >&2; exit 1; }
chattr -i "$probe"
backup="$REMOTE_DIR/runtime/private/release-protection/$(date -u +%Y%m%dT%H%M%SZ)-$$"
umask 077
mkdir -p "$backup"
for legacy in activate-release.sh activate-incremental-release.sh; do
if cmp -s "$LEGACY_STUB" "$REMOTE_DIR/$legacy" && is_immutable "$REMOTE_DIR/$legacy"; then
continue
fi
[ ! -f "$REMOTE_DIR/$legacy" ] || cp -p "$REMOTE_DIR/$legacy" "$backup/$legacy"
install -m 700 "$LEGACY_STUB" "$REMOTE_DIR/.$legacy.next"
mv "$REMOTE_DIR/.$legacy.next" "$REMOTE_DIR/$legacy"
chattr +i "$REMOTE_DIR/$legacy"
cmp -s "$LEGACY_STUB" "$REMOTE_DIR/$legacy" && is_immutable "$REMOTE_DIR/$legacy"
done
echo 'Legacy activation paths protected; current application and databases were not restarted'