mirror of
https://github.com/aziis98/statuspage.git
synced 2026-10-06 14:45:01 +00:00
140 lines
3.6 KiB
Bash
Executable File
140 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
ASSETS="assets/screenshots"
|
|
LIGHT="$ASSETS/status.png"
|
|
DARK="$ASSETS/status-dark.png"
|
|
COLLAGE="$ASSETS/status-collage.png"
|
|
PORT="${PORT:-17645}"
|
|
URL="http://127.0.0.1:$PORT"
|
|
|
|
CHROMIUM="$(command -v chromium || command -v chromium-browser || true)"
|
|
if [ -z "$CHROMIUM" ]; then
|
|
echo "error: chromium not found (install chromium or chromium-browser)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if python3 -c 'import PIL' 2>/dev/null; then
|
|
HAVE_PIL=1
|
|
else
|
|
HAVE_PIL=0
|
|
echo "note: python3-PIL not found, skipping framing and collage" >&2
|
|
fi
|
|
|
|
echo "building frontend..."
|
|
bun run build
|
|
|
|
echo "building server..."
|
|
CGO_ENABLED=1 go build -o bin/statuspage ./server
|
|
|
|
cleanup() {
|
|
if [ -n "${SERVER_PID:-}" ]; then
|
|
kill "$SERVER_PID" 2>/dev/null || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo "starting mock server on $URL"
|
|
./bin/statuspage --mock --addr "127.0.0.1:$PORT" &
|
|
SERVER_PID=$!
|
|
|
|
for _ in $(seq 1 50); do
|
|
if curl -sf "$URL/api/status" >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 0.1
|
|
done
|
|
if ! curl -sf "$URL/api/status" >/dev/null 2>&1; then
|
|
echo "error: mock server did not come up" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$ASSETS"
|
|
|
|
# $1=theme $2=out $3=shadow $4=border
|
|
capture() {
|
|
local theme="$1" out="$2" shadow="$3" border="$4"
|
|
|
|
if [ -f "$out" ] &&
|
|
! find src index.html public server go.mod go.sum \
|
|
-type f -newer "$out" -print -quit 2>/dev/null | grep -q .; then
|
|
echo "up to date, skipping ($out)"
|
|
return
|
|
fi
|
|
|
|
"$CHROMIUM" --headless=new --disable-gpu --hide-scrollbars \
|
|
--window-size=1280,720 \
|
|
--force-device-scale-factor=2 \
|
|
--screenshot="$out" \
|
|
--virtual-time-budget=8000 \
|
|
"$URL/?theme=$theme" 2>/dev/null
|
|
|
|
# frame the capture: rounded corners, 2px border, hard offset shadow (2x for device scale)
|
|
if [ "$HAVE_PIL" = 1 ]; then
|
|
python3 - "$out" "$shadow" "$border" <<'PY'
|
|
import sys
|
|
from PIL import Image, ImageDraw
|
|
|
|
path = sys.argv[1]
|
|
img = Image.open(path).convert("RGB")
|
|
W, H = img.size
|
|
r = 16 # 0.5rem radius
|
|
b = 4 # 2px border
|
|
s = 12 # 0.35rem shadow offset
|
|
m = 24 # margin around the frame
|
|
BORDER = tuple(int(c) for c in sys.argv[3].split(","))
|
|
shadow_parts = [int(c) for c in sys.argv[2].split(",")]
|
|
if len(shadow_parts) == 3:
|
|
shadow_parts.append(255)
|
|
SHADOW = tuple(shadow_parts)
|
|
|
|
mask = Image.new("L", (W, H), 0)
|
|
ImageDraw.Draw(mask).rounded_rectangle([0, 0, W - 1, H - 1], radius=r, fill=255)
|
|
|
|
img_r = img.copy()
|
|
img_r.putalpha(mask)
|
|
|
|
bw, bh = W + 2 * b, H + 2 * b
|
|
canvas = Image.new("RGBA", (bw + 2 * m + s, bh + 2 * m + s), (0, 0, 0, 0))
|
|
d = ImageDraw.Draw(canvas)
|
|
d.rounded_rectangle(
|
|
[m + s, m + s, m + s + bw - 1, m + s + bh - 1], radius=r, fill=SHADOW)
|
|
d.rounded_rectangle(
|
|
[m, m, m + bw - 1, m + bh - 1], radius=r, fill=BORDER + (255,))
|
|
canvas.alpha_composite(img_r, (m + b, m + b))
|
|
|
|
canvas.save(path)
|
|
print(f"framed {path}")
|
|
PY
|
|
fi
|
|
echo "wrote $out"
|
|
}
|
|
|
|
capture light "$LIGHT" "0,0,0,136" "17,17,17"
|
|
capture dark "$DARK" "0,0,0,136" "58,64,58"
|
|
|
|
# collage: rebuild only when a variant is newer than the existing collage
|
|
if [ "$HAVE_PIL" = 1 ]; then
|
|
if [ -f "$COLLAGE" ] && [ "$COLLAGE" -nt "$LIGHT" ] && [ "$COLLAGE" -nt "$DARK" ]; then
|
|
echo "collage up to date, skipping ($COLLAGE)"
|
|
else
|
|
python3 - "$LIGHT" "$DARK" "$COLLAGE" <<'PY'
|
|
import sys
|
|
from PIL import Image
|
|
|
|
light = Image.open(sys.argv[1]).convert("RGBA")
|
|
dark = Image.open(sys.argv[2]).convert("RGBA")
|
|
W, H = light.size
|
|
ox, oy = 480, 160
|
|
canvas = Image.new("RGBA", (W + ox, H + oy), (0, 0, 0, 0))
|
|
canvas.alpha_composite(dark, (0, 0))
|
|
canvas.alpha_composite(light, (ox, oy))
|
|
canvas.thumbnail((1920, 1080), Image.LANCZOS)
|
|
canvas.save(sys.argv[3])
|
|
print(f"wrote {sys.argv[3]}")
|
|
PY
|
|
fi
|
|
fi
|