Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kb7vDj6PHwymeDeSUUk1eX
42 lines
1.4 KiB
Bash
Executable File
42 lines
1.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# Upload release artifacts to the omarchycn-releases R2 bucket, then verify each
|
|
# by anonymous public re-read (sha256 must match the local file).
|
|
# Usage: upload-release-r2.sh <version> <file...>
|
|
# Public URL shape: https://dl.zacharyzhang.com/<version>/<name>
|
|
# Credentials: ~/omarchycn-build/.r2.env (rclone S3 env config, mode 0600)
|
|
|
|
set -euo pipefail
|
|
|
|
BUCKET=omarchycn-releases
|
|
PUBLIC=https://dl.zacharyzhang.com
|
|
|
|
version="${1:?usage: upload-release-r2.sh <version> <file...>}"
|
|
shift
|
|
(($#)) || { echo "no files given" >&2; exit 1; }
|
|
|
|
source "$HOME/omarchycn-build/.r2.env"
|
|
|
|
for f in "$@"; do
|
|
[[ -f $f ]] || { echo "no such file: $f" >&2; exit 1; }
|
|
name=$(basename "$f")
|
|
echo "==> $name -> $PUBLIC/$version/$name"
|
|
rclone copyto --s3-upload-cutoff 200M --s3-chunk-size 100M --retries 6 "$f" "r2:$BUCKET/$version/$name"
|
|
want=$(sha256sum "$f" | cut -d' ' -f1)
|
|
got=$(curl -fsSL "$PUBLIC/$version/$name" | sha256sum | cut -d' ' -f1)
|
|
if [[ $want != "$got" ]]; then
|
|
echo "sha256 mismatch for $name: local $want public $got" >&2
|
|
exit 1
|
|
fi
|
|
echo "verified $want"
|
|
done
|
|
|
|
# Keep the newest two release prefixes (current + rollback), purge older ones
|
|
keep=2
|
|
mapfile -t versions < <(rclone lsf --dirs-only "r2:$BUCKET" | sed 's|/$||' | sort -V)
|
|
if ((${#versions[@]} > keep)); then
|
|
for old in "${versions[@]:0:${#versions[@]}-keep}"; do
|
|
echo "==> purge old release $old"
|
|
rclone purge "r2:$BUCKET/$old"
|
|
done
|
|
fi
|