Add scripts/deploy_static_site.sh

This commit is contained in:
2026-04-18 23:29:23 -03:00
parent 5b050c4a21
commit 0d0a930afb
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env bash
#
# Deploy static files using release directories and an atomic symlink switch.
#
# This pattern reduces partial deployments because files are copied to a new
# release directory first. The live path changes only when the copy succeeds.
#
# Usage:
# bash deploy_static_site.sh --source ./dist --releases /var/www/releases --current /var/www/current
# bash deploy_static_site.sh --source ./dist --releases /var/www/releases --current /var/www/current --keep 10
#
# Options:
# --source DIR Directory containing built static files.
# --releases DIR Directory that stores timestamped releases.
# --current PATH Symlink path used by the web server.
# --keep N Number of releases to keep. Default: 5.
# --help Show this help message.
set -Eeuo pipefail
source_dir=""
releases_dir=""
current_link=""
keep_releases="5"
usage() {
sed -n '2,22p' "$0" | sed 's/^# \{0,1\}//'
}
log() {
printf '[%s] %s\n' "$(date -Is)" "$*"
}
while [[ "$#" -gt 0 ]]; do
case "$1" in
--source)
source_dir="${2:-}"
shift 2
;;
--releases)
releases_dir="${2:-}"
shift 2
;;
--current)
current_link="${2:-}"
shift 2
;;
--keep)
keep_releases="${2:-}"
[[ "$keep_releases" =~ ^[0-9]+$ ]] || { printf 'ERROR: --keep must be an integer.\n' >&2; exit 1; }
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
printf 'ERROR: unknown option: %s\n' "$1" >&2
usage >&2
exit 1
;;
esac
done
[[ -d "$source_dir" ]] || { printf 'ERROR: source directory does not exist: %s\n' "$source_dir" >&2; exit 1; }
[[ -n "$releases_dir" ]] || { printf 'ERROR: --releases is required.\n' >&2; exit 1; }
[[ -n "$current_link" ]] || { printf 'ERROR: --current is required.\n' >&2; exit 1; }
mkdir -p "$releases_dir"
release_id="$(date +%Y%m%d-%H%M%S)"
release_path="${releases_dir}/${release_id}"
log "Creating release directory: ${release_path}"
mkdir -p "$release_path"
log "Copying files from ${source_dir}"
if command -v rsync >/dev/null 2>&1; then
rsync -a --delete "${source_dir}/" "${release_path}/"
else
cp -a "${source_dir}/." "$release_path/"
fi
log "Switching current symlink to ${release_path}"
ln -sfn "$release_path" "$current_link"
log "Removing old releases, keeping the newest ${keep_releases}."
find "$releases_dir" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' \
| sort -nr \
| awk -v keep="$keep_releases" 'NR > keep {print $2}' \
| xargs -r rm -rf
log "Deployment completed successfully."