release: refuse upload over existing tag unless --replace
scripts/build-release.sh --upload now checks for an existing release at the given tag before POSTing a new one. If found and --replace is not set, errors out with a clear message. This prevents the silent-overwrite problem: a user on v2.9.7 running ./scripts/upgrade.sh sees "no update available" when the v2.9.7 release's tarball contents have silently changed. Version tags should be immutable once published. --replace is still available for deliberate test-bench iteration (DELETEs the existing release, then POSTs). Documented as destructive in the --help output and DEV_WORKFLOW.md. Bunker Admin
This commit is contained in:
parent
6e01d580b2
commit
c2f12aa2bf
@ -157,8 +157,17 @@ Packages only runtime files (~9 MB) — no source code, no node_modules:
|
||||
|
||||
# Preview contents without creating tarball
|
||||
./scripts/build-release.sh --dry-run
|
||||
|
||||
# --upload refuses to overwrite an existing tag. To deliberately replace
|
||||
# a release (destructive — users on that tag see no upgrade signal):
|
||||
./scripts/build-release.sh --tag v2.2.0 --upload --replace
|
||||
```
|
||||
|
||||
**Version hygiene:** bump the tag when changing release contents. Overwriting
|
||||
an existing release silently breaks upgrade checks for users already on that
|
||||
version — they see "no update available" even though the tarball they'd
|
||||
download differs.
|
||||
|
||||
The tarball contains:
|
||||
- `docker-compose.yml` (copy of `docker-compose.prod.yml` — image-only, no build blocks)
|
||||
- `.env.example`, `config.sh` (configuration wizard)
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
# --tag TAG Version tag (default: git describe or commit SHA)
|
||||
# --output DIR Output directory (default: ./releases/)
|
||||
# --upload Upload to Gitea Releases API after building
|
||||
# --replace Delete + recreate an existing release with this tag
|
||||
# (DESTRUCTIVE: users already on TAG see no upgrade signal)
|
||||
# --dry-run Show what would be included without creating tarball
|
||||
# --help Show this help
|
||||
#
|
||||
@ -28,6 +30,7 @@ TAG=""
|
||||
OUTPUT_DIR="${PROJECT_DIR}/releases"
|
||||
UPLOAD=false
|
||||
DRY_RUN=false
|
||||
REPLACE=false
|
||||
|
||||
# --- Colors ---
|
||||
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
|
||||
@ -48,6 +51,7 @@ while [[ $# -gt 0 ]]; do
|
||||
--tag) TAG="$2"; shift 2 ;;
|
||||
--output) OUTPUT_DIR="$2"; shift 2 ;;
|
||||
--upload) UPLOAD=true; shift ;;
|
||||
--replace) REPLACE=true; shift ;;
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--help|-h)
|
||||
sed -n '2,20p' "$0" | grep '^#' | sed 's/^# \?//'
|
||||
@ -223,6 +227,31 @@ if [[ "$UPLOAD" == "true" ]]; then
|
||||
warn "GITEA_REGISTRY_API_TOKEN not set — skipping upload"
|
||||
warn "Set GITEA_REGISTRY_API_TOKEN in .env and re-run with --upload"
|
||||
else
|
||||
# Refuse to overwrite an existing release unless --replace is explicit.
|
||||
# Silently overwriting a published tag breaks upgrade checks for users
|
||||
# already on that version (they see "no update available" even though
|
||||
# the tarball changed).
|
||||
EXISTING_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
"${GITEA_HOST}/api/v1/repos/admin/changemaker.lite/releases/tags/${TAG}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}")
|
||||
if [[ "$EXISTING_RESPONSE" == "200" ]]; then
|
||||
if [[ "$REPLACE" != "true" ]]; then
|
||||
error "Release ${TAG} already exists."
|
||||
error " Bump the version to a new tag, or pass --replace to delete and recreate."
|
||||
error " --replace is destructive: users on ${TAG} will see no upgrade signal but get different tarball contents."
|
||||
exit 1
|
||||
fi
|
||||
warn "Release ${TAG} exists — deleting first (--replace)"
|
||||
EXISTING_ID=$(curl -sf "${GITEA_HOST}/api/v1/repos/admin/changemaker.lite/releases/tags/${TAG}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null || echo "")
|
||||
if [[ -n "$EXISTING_ID" ]]; then
|
||||
curl -sf -X DELETE \
|
||||
"${GITEA_HOST}/api/v1/repos/admin/changemaker.lite/releases/${EXISTING_ID}" \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" >/dev/null
|
||||
success "Deleted existing release ${TAG} (id ${EXISTING_ID})"
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Creating Gitea release ${TAG}..."
|
||||
RELEASE_RESPONSE=$(curl -sf -X POST \
|
||||
"${GITEA_HOST}/api/v1/repos/admin/changemaker.lite/releases" \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user