hephaestus/scripts/smoke-test-s3.sh
2026-09-12 00:07:28 +02:00

75 lines
3.3 KiB
Bash

#!/usr/bin/env bash
# Verify sia.storage's S3 gateway handles the operations Forgejo needs for LFS.
# Requires: awscli >= 2.x, `xxd`, and env vars from ../.env
#
# Blocks LFS support if any step fails:
# 1. PutObject (small: avatar)
# 2. Multipart upload (large: 100 MB LFS-shaped blob, 3 parts)
# 3. GetObject (read-back)
# 4. HeadObject (metadata)
# 5. ListObjectsV2 (pagination)
# 6. DeleteObject (cleanup)
#
# Usage: ./smoke-test-s3.sh
set -euo pipefail
# shellcheck disable=SC1091
[[ -f ../.env ]] && source ../.env
: "${SIA_STORAGE_ENDPOINT:?SIA_STORAGE_ENDPOINT not set}"
: "${SIA_STORAGE_ACCESS_KEY:?SIA_STORAGE_ACCESS_KEY not set}"
: "${SIA_STORAGE_SECRET_KEY:?SIA_STORAGE_SECRET_KEY not set}"
: "${SIA_STORAGE_BUCKET:?SIA_STORAGE_BUCKET not set}"
export AWS_ACCESS_KEY_ID="$SIA_STORAGE_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="$SIA_STORAGE_SECRET_KEY"
export AWS_DEFAULT_REGION=us-east-1
S3="aws s3api --endpoint-url https://${SIA_STORAGE_ENDPOINT}"
S3CLI="aws s3 --endpoint-url https://${SIA_STORAGE_ENDPOINT}"
KEY_SMALL="smoke/small.bin"
KEY_LARGE="smoke/large-100mb.bin"
step() { printf "\n\033[1;36m▸ %s\033[0m\n" "$*"; }
ok() { printf " \033[32m✓\033[0m %s\n" "$*"; }
die() { printf " \033[31m✗ %s\033[0m\n" "$*"; exit 1; }
trap 'rm -f /tmp/smoke-small /tmp/smoke-large /tmp/smoke-large-back' EXIT
step "1. PutObject — small blob"
head -c 4096 /dev/urandom > /tmp/smoke-small
SMALL_HASH=$(sha256sum /tmp/smoke-small | cut -d' ' -f1)
$S3CLI cp /tmp/smoke-small "s3://${SIA_STORAGE_BUCKET}/${KEY_SMALL}" >/dev/null || die "PutObject failed"
ok "uploaded (sha256=${SMALL_HASH:0:12}…)"
step "2. Multipart upload — 100 MB in 3 parts (this is the critical LFS test)"
head -c 104857600 /dev/urandom > /tmp/smoke-large
LARGE_HASH=$(sha256sum /tmp/smoke-large | cut -d' ' -f1)
# Force multipart with a small threshold + chunk size
aws configure set default.s3.multipart_threshold 25MB
aws configure set default.s3.multipart_chunksize 33MB
$S3CLI cp /tmp/smoke-large "s3://${SIA_STORAGE_BUCKET}/${KEY_LARGE}" >/dev/null || die "multipart PUT failed"
ok "multipart upload succeeded (sha256=${LARGE_HASH:0:12}…)"
step "3. GetObject — read-back the large blob"
$S3CLI cp "s3://${SIA_STORAGE_BUCKET}/${KEY_LARGE}" /tmp/smoke-large-back >/dev/null || die "GET failed"
BACK_HASH=$(sha256sum /tmp/smoke-large-back | cut -d' ' -f1)
[[ "$BACK_HASH" == "$LARGE_HASH" ]] || die "checksum mismatch after multipart round-trip"
ok "checksum matches"
step "4. HeadObject"
SIZE=$($S3 head-object --bucket "$SIA_STORAGE_BUCKET" --key "$KEY_LARGE" --query 'ContentLength' --output text) || die "HEAD failed"
[[ "$SIZE" == "104857600" ]] || die "ContentLength mismatch: $SIZE"
ok "size = $SIZE"
step "5. ListObjectsV2 — prefix scan"
COUNT=$($S3 list-objects-v2 --bucket "$SIA_STORAGE_BUCKET" --prefix "smoke/" --query 'length(Contents)' --output text) || die "LIST failed"
[[ "$COUNT" -ge 2 ]] || die "expected >=2 objects under smoke/, got $COUNT"
ok "found $COUNT objects"
step "6. DeleteObject — cleanup"
$S3 delete-object --bucket "$SIA_STORAGE_BUCKET" --key "$KEY_SMALL" >/dev/null
$S3 delete-object --bucket "$SIA_STORAGE_BUCKET" --key "$KEY_LARGE" >/dev/null
ok "deleted test objects"
printf "\n\033[1;32mAll checks passed. sia.storage is safe to use as Forgejo's LFS backend.\033[0m\n"