-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathremote-deploy.sh
More file actions
executable file
·77 lines (63 loc) · 2.11 KB
/
Copy pathremote-deploy.sh
File metadata and controls
executable file
·77 lines (63 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/env bash
set -Eeuo pipefail
artifact=${1:?Usage: remote-deploy.sh ARTIFACT RELEASE_ID}
release_id=${2:?Usage: remote-deploy.sh ARTIFACT RELEASE_ID}
app_root=${APP_ROOT:-/srv/example-app}
service_name=${SERVICE_NAME:-example-app}
health_url=${HEALTH_URL:-http://127.0.0.1:3000/health/ready}
keep_releases=${KEEP_RELEASES:-5}
if [[ ! "$release_id" =~ ^[a-f0-9]{7,64}$ ]]; then
echo "Release ID must be a Git commit SHA" >&2
exit 2
fi
if [[ ! -f "$artifact" ]]; then
echo "Artifact not found: $artifact" >&2
exit 2
fi
release_dir="$app_root/releases/$release_id"
previous_target=""
if [[ -L "$app_root/current" ]]; then
previous_target=$(readlink "$app_root/current")
fi
mkdir -p "$app_root/releases" "$release_dir"
# Reject absolute paths and parent traversal before extraction.
while IFS= read -r entry; do
if [[ "$entry" == /* || "$entry" == ".." || "$entry" == ../* || "$entry" == */../* ]]; then
echo "Unsafe archive entry: $entry" >&2
exit 3
fi
done < <(tar -tzf "$artifact")
tar -xzf "$artifact" -C "$release_dir"
cd "$release_dir"
if [[ -f package-lock.json ]]; then
npm ci --omit=dev
fi
if [[ -n "${MIGRATE_COMMAND:-}" ]]; then
bash -lc "$MIGRATE_COMMAND"
fi
ln -sfn "$release_dir" "$app_root/current.next"
mv -Tf "$app_root/current.next" "$app_root/current"
systemctl restart "$service_name"
healthy=false
for _ in {1..12}; do
if curl --fail --silent --show-error --max-time 5 "$health_url" >/dev/null; then
healthy=true
break
fi
sleep 5
done
if [[ "$healthy" != true ]]; then
echo "Health check failed; rolling back" >&2
if [[ -n "$previous_target" && -d "$previous_target" ]]; then
ln -sfn "$previous_target" "$app_root/current.next"
mv -Tf "$app_root/current.next" "$app_root/current"
systemctl restart "$service_name"
fi
exit 1
fi
find "$app_root/releases" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' \
| sort -rn \
| awk -v keep="$keep_releases" 'NR > keep { sub(/^[^ ]+ /, ""); print }' \
| while IFS= read -r old_release; do rm -rf -- "$old_release"; done
rm -f -- "$artifact" /tmp/remote-deploy.sh
echo "Release $release_id is healthy and active"