95 lines
2.5 KiB
Bash
95 lines
2.5 KiB
Bash
#!/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."
|
|
|