blob: 99129ad352c04ba8f35d8f1ef788c04780a0157e (
plain) (
blame)
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/usr/bin/env bash
# Upload web/ and verify every published artifact over the public URL.
#
# Usage:
# ./scripts/deploy.sh user@host:/srv/zagan.bet https://zagan.bet/
# ./scripts/deploy.sh /srv/staging http://127.0.0.1:8899/
# ./scripts/deploy.sh --verify-only user@host:/srv/zagan.bet https://zagan.bet/
#
# The target may be a local directory, which is handy for staging and for
# testing the verification itself. Old versions are left in place on purpose;
# prune them by hand when you want to drop them.
#
# Environment:
# DEPLOY_TARGET, DEPLOY_URL same as the two arguments
# SSH_PORT ssh port for a remote target
set -euo pipefail
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
cd "$ROOT"
die() { echo "deploy: $*" >&2; exit 1; }
VERIFY_ONLY=0
if [ "${1:-}" = "--verify-only" ]; then
VERIFY_ONLY=1
shift
fi
TARGET=${1:-${DEPLOY_TARGET:-}}
URL=${2:-${DEPLOY_URL:-}}
if [ -z "$TARGET" ] || [ -z "$URL" ]; then
cat >&2 <<'EOF'
usage: scripts/deploy.sh [--verify-only] <target> <url>
target user@host:/srv/zagan.bet or a local directory
url public URL of the page, e.g. https://zagan.bet/
--verify-only skips the upload and only checks the live page
environment:
DEPLOY_TARGET, DEPLOY_URL same as the two arguments
SSH_PORT ssh port for a remote target
EOF
exit 2
fi
for tool in rsync curl sha256sum; do
command -v "$tool" >/dev/null || die "$tool is required"
done
[ -f web/index.php ] || die "web/index.php is missing"
shopt -s nullglob
artifacts=(web/bin/client/zagan-bet-* web/bin/server/zagan-bet-*)
shopt -u nullglob
[ ${#artifacts[@]} -gt 0 ] || die "no artifacts in web/bin; run scripts/publish.sh first"
if [ "$VERIFY_ONLY" -eq 0 ]; then
echo "==> uploading web/ to $TARGET"
# --delay-updates writes to temp names and renames at the end, so a visitor
# never sees a half-written binary. Old versions are kept: no --delete.
RSYNC_FLAGS=(
-a --delay-updates --human-readable --chmod=D755,F644
--exclude=README.md --exclude=.gitignore
)
if [[ "$TARGET" == *:* ]]; then
host=${TARGET%%:*}
path=${TARGET#*:}
ssh_args=()
if [ -n "${SSH_PORT:-}" ]; then
ssh_args+=(-p "$SSH_PORT")
fi
ssh ${ssh_args[@]+"${ssh_args[@]}"} "$host" "mkdir -p $(printf '%q' "$path")"
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${ssh_args[*]:-}" web/ "$host:$path/"
else
mkdir -p "$TARGET"
rsync "${RSYNC_FLAGS[@]}" web/ "$TARGET/"
fi
fi
echo "==> verifying $URL"
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
curl -fsSL --max-time 30 "$URL" -o "$tmp/page.html" \
|| die "could not fetch $URL"
origin=$(printf '%s' "$URL" | sed -E 's#^(https?://[^/]+).*#\1#')
grep -oE '[0-9a-f]{64} [A-Za-z0-9._-]+' "$tmp/page.html" > "$tmp/sums" || true
[ -s "$tmp/sums" ] || die "no SHA-256 lines on the page (is index.php being served?)"
failed=0
verified=0
for local in "${artifacts[@]}"; do
[ -f "$local" ] || continue
file=$(basename "$local")
kind=$(basename "$(dirname "$local")")
local_hash=$(sha256sum "$local" | cut -d' ' -f1)
href=$(grep -oE "href=\"[^\"]*/bin/$kind/$file\"" "$tmp/page.html" | head -1 \
| sed 's/^href="//;s/"$//' || true)
if [ -z "$href" ]; then
echo " $file: not listed on the page"
failed=1
continue
fi
shown=$(awk -v name="$file" '$2 == name { print $1 }' "$tmp/sums" | head -1)
if [ "$shown" != "$local_hash" ]; then
echo " $file: page shows ${shown:-nothing}, local is $local_hash"
failed=1
continue
fi
if ! curl -fsSL --max-time 120 "$origin$href" -o "$tmp/$file"; then
echo " $file: download failed"
failed=1
continue
fi
remote_hash=$(sha256sum "$tmp/$file" | cut -d' ' -f1)
if [ "$remote_hash" != "$local_hash" ]; then
echo " $file: downloaded bytes differ from local"
failed=1
continue
fi
echo " $file: ok"
verified=$((verified + 1))
done
[ "$failed" -eq 0 ] || die "verification failed"
echo "==> $verified artifact(s) verified at $URL"
|