Menu
Public repository / f6049706f41de2783cd0b02e328a67dc7392412f
AkurAI-EC2 / install.sh
Latest change 6c8df1c27074216aaa5c9e88744bdb87fd2c522e - fix: install lifecycle helper from writable CLI directory by Ólafur Búi Ólafsson
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
usage: ./install.sh [--copy|--symlink] [--dry-run]
Install bin/akurai-ec2 to ~/.local/bin/akurai-ec2.
--copy install a standalone copy (default — the AkurAI Build worker
sandbox cannot traverse symlinks out of ~/.local/bin; a symlink
install breaks every deploy job that shells out to akurai-ec2)
--symlink install a development symlink (explicit opt-in only)
--dry-run print the actions without changing anything
EOF
}
die() {
printf 'install.sh: %s\n' "$*" >&2
exit 1
}
run() {
if [ "$dry_run" -eq 1 ]; then
printf '+'
printf ' %q' "$@"
printf '\n'
else
"$@"
fi
}
mode="copy"
dry_run=0
while [ $# -gt 0 ]; do
case "$1" in
--symlink)
mode="symlink"
;;
--copy)
mode="copy"
;;
--dry-run)
dry_run=1
;;
-h|--help)
usage
exit 0
;;
*)
die "unknown argument: $1"
;;
esac
shift
done
script_dir="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
src="$script_dir/bin/akurai-ec2"
helper_sources=(
"$script_dir/libexec/akurai-ec2-manifest.py"
"$script_dir/libexec/akurai-ec2-dns.py"
"$script_dir/libexec/akurai-ec2-retire-app.py"
)
target="${AKURAI_EC2_INSTALL_TARGET:-$HOME/.local/bin/akurai-ec2}"
target_dir="$(dirname -- "$target")"
helper_target_dir="$(dirname -- "$target_dir")/libexec"
helper_target="$helper_target_dir/akurai-ec2-manifest.py"
workspace_source="$script_dir/libexec/akurai-ec2-workspace.py"
workspace_target="$target_dir/akurai-ec2-workspace.py"
[ -f "$src" ] || die "source script not found: $src"
if [ "$mode" = "copy" ]; then
for helper_src in "${helper_sources[@]}"; do
[ -f "$helper_src" ] || die "helper not found: $helper_src"
done
[ -f "$workspace_source" ] || die "workspace helper not found: $workspace_source"
fi
src_resolved="$(readlink -f -- "$src")"
timestamp="$(date +%Y%m%d%H%M%S)"
backup=""
run mkdir -p -- "$target_dir"
run chmod 755 -- "$src"
if [ "$mode" = "symlink" ] && [ -L "$target" ]; then
target_resolved="$(readlink -f -- "$target" 2>/dev/null || true)"
if [ "$target_resolved" = "$src_resolved" ]; then
printf 'already linked: %s -> %s\n' "$target" "$src"
exit 0
fi
fi
if [ "$mode" = "copy" ] && [ -f "$target" ] && [ ! -L "$target" ] && [ -x "$target" ] \
&& cmp -s -- "$src" "$target"; then
helpers_current=1
for helper_src in "${helper_sources[@]}"; do
helper_target="$helper_target_dir/$(basename -- "$helper_src")"
if [ ! -f "$helper_target" ] || [ ! -x "$helper_target" ] \
|| ! cmp -s -- "$helper_src" "$helper_target"; then
helpers_current=0
break
fi
done
if [ ! -f "$workspace_target" ] || [ ! -x "$workspace_target" ] \
|| ! cmp -s -- "$workspace_source" "$workspace_target"; then
helpers_current=0
fi
if [ "$helpers_current" -eq 1 ]; then
printf 'already installed: %s\n' "$target"
exit 0
fi
fi
if [ -e "$target" ]; then
backup="$target.bak.$timestamp"
# Copy through a symlink so every snapshot is a regular, immutable file.
run install -m 755 -- "$target" "$backup"
run rm -- "$target"
printf 'backed up existing target to %s\n' "$backup"
elif [ -L "$target" ]; then
# Containerized installers may see a host symlink whose source is not mounted.
run rm -- "$target"
printf 'removed broken symlink: %s\n' "$target"
fi
if [ "$mode" = "copy" ]; then
run mkdir -p -- "$helper_target_dir"
run install -m 755 -- "$src" "$target"
for helper_src in "${helper_sources[@]}"; do
helper_target="$helper_target_dir/$(basename -- "$helper_src")"
if [ -f "$helper_target" ] && [ -x "$helper_target" ] && cmp -s -- "$helper_src" "$helper_target"; then
printf 'unchanged helper: %s\n' "$helper_target"
continue
fi
run install -m 755 -- "$helper_src" "$helper_target"
printf 'installed helper: %s\n' "$helper_target"
done
if [ -f "$workspace_target" ] && [ -x "$workspace_target" ] \
&& cmp -s -- "$workspace_source" "$workspace_target"; then
printf 'unchanged workspace helper: %s\n' "$workspace_target"
else
run install -m 755 -- "$workspace_source" "$workspace_target"
printf 'installed workspace helper: %s\n' "$workspace_target"
fi
printf 'installed copy: %s\n' "$target"
else
run ln -s -- "$src" "$target"
printf 'installed symlink: %s -> %s\n' "$target" "$src"
fi
# Keep the five newest regular snapshots; never treat a symlink as a rollback
# artifact even if an older installer left one behind.
backup_candidates=("$target".bak.*)
backups=()
for backup_candidate in "${backup_candidates[@]}"; do
if [ -f "$backup_candidate" ] && [ ! -L "$backup_candidate" ]; then
backups+=("$backup_candidate")
fi
done
while [ "${#backups[@]}" -gt 5 ]; do
run rm -- "${backups[0]}"
backups=("${backups[@]:1}")
done