publish-script: split RCLONE_BUCKET out of BUCKET_PATH

The previous form passed rclone paths like releases:banger/v0.1.0/,
which rclone parses as bucket=banger, key=v0.1.0/... — wrong, because
the actual R2 bucket is named "releases" (BUCKET_PATH was meant as
an in-bucket key prefix only). Uploads 403'd because the token has
no view of a bucket called "banger".

Introduce RCLONE_BUCKET as a separate env var (default: "releases")
and route every rclone copy through ${RCLONE_REMOTE}:${RCLONE_BUCKET}/${BUCKET_PATH}.
The public URLs in the manifest stay unchanged: BASE_URL is the
bucket's public custom domain, so the bucket name is implicit there.

The defaults now resolve to the live setup:
  rclone target:  releases:releases/banger/<version>/<file>
  public URL:     https://releases.thaloco.com/banger/<version>/<file>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-29 13:35:53 -03:00
parent 12f7a92bb4
commit 6fdebd929e
No known key found for this signature in database
GPG key ID: 33112E6833C34679

View file

@ -10,14 +10,23 @@
# Environment overrides:
# COSIGN_KEY path to the cosign private key (default: cosign.key)
# RCLONE_REMOTE rclone remote name (default: releases)
# RCLONE_BUCKET R2 bucket name (rclone target) (default: releases)
# BUCKET_PATH object-key prefix in the bucket (default: banger)
# BASE_URL public URL prefix for objects (default: https://releases.thaloco.com)
# SKIP_UPLOAD set to 1 to stage everything locally without rclone upload
#
# rclone path layout:
# ${RCLONE_REMOTE}:${RCLONE_BUCKET}/${BUCKET_PATH}/...
# i.e. defaults resolve to releases:releases/banger/v0.1.0/<file>.
# Public URLs in the manifest are ${BASE_URL}/${BUCKET_PATH}/<version>/<file>
# (BASE_URL is the bucket's public custom domain, so the bucket name
# itself is implicit there).
#
# Prerequisites:
# * cosign in PATH (https://github.com/sigstore/cosign)
# * rclone in PATH, configured with a remote named ${RCLONE_REMOTE}
# pointing at the R2 bucket served at ${BASE_URL}.
# that targets the R2 account hosting ${RCLONE_BUCKET}, which is
# publicly served at ${BASE_URL}.
# * A cosign keypair already generated. The public key MUST already
# be embedded in internal/updater/verify_signature.go's
# BangerReleasePublicKey constant — running this script with a
@ -50,10 +59,13 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
COSIGN_KEY="${COSIGN_KEY:-cosign.key}"
RCLONE_REMOTE="${RCLONE_REMOTE:-releases}"
RCLONE_BUCKET="${RCLONE_BUCKET:-releases}"
BUCKET_PATH="${BUCKET_PATH:-banger}"
BASE_URL="${BASE_URL:-https://releases.thaloco.com}"
SKIP_UPLOAD="${SKIP_UPLOAD:-0}"
RCLONE_DEST_BASE="$RCLONE_REMOTE:$RCLONE_BUCKET/$BUCKET_PATH"
command -v cosign >/dev/null || die "cosign not in PATH"
command -v rclone >/dev/null || die "rclone not in PATH"
command -v sha256sum >/dev/null || die "sha256sum not in PATH"
@ -186,13 +198,13 @@ if [[ "$SKIP_UPLOAD" == "1" ]]; then
exit 0
fi
log "uploading to $RCLONE_REMOTE:$BUCKET_PATH/$VERSION/"
rclone copy "$TARBALL_PATH" "$RCLONE_REMOTE:$BUCKET_PATH/$VERSION/"
rclone copy "$OUT_DIR/SHA256SUMS" "$RCLONE_REMOTE:$BUCKET_PATH/$VERSION/"
rclone copy "$OUT_DIR/SHA256SUMS.sig" "$RCLONE_REMOTE:$BUCKET_PATH/$VERSION/"
log "uploading to $RCLONE_DEST_BASE/$VERSION/"
rclone copy "$TARBALL_PATH" "$RCLONE_DEST_BASE/$VERSION/"
rclone copy "$OUT_DIR/SHA256SUMS" "$RCLONE_DEST_BASE/$VERSION/"
rclone copy "$OUT_DIR/SHA256SUMS.sig" "$RCLONE_DEST_BASE/$VERSION/"
log "uploading manifest"
rclone copy "$NEW_MANIFEST" "$RCLONE_REMOTE:$BUCKET_PATH/"
rclone copy "$NEW_MANIFEST" "$RCLONE_DEST_BASE/"
log "done. verify with:"
log " curl -fsSL $BASE_URL/$BUCKET_PATH/manifest.json | jq ."