Linux CPU sidecar: PyPI's default torch on Linux includes CUDA (~800MB). UV_NO_SOURCES only bypasses our custom CUDA index but still gets CUDA-enabled torch from PyPI. Now explicitly installs CPU-only torch from pytorch.org/whl/cpu after sync. Same fix applied to Windows. New cleanup-releases.yml workflow (manual trigger): - Configurable: keep N app releases, keep N sidecar releases - Dry run mode (default) shows what would be deleted without deleting - Protects v1.4.0 (last pre-Tauri release) - Shows release sizes in MB Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
103 lines
3.9 KiB
YAML
103 lines
3.9 KiB
YAML
name: Cleanup Old Releases
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
keep_app_releases:
|
|
description: 'Number of app releases to keep'
|
|
required: false
|
|
default: '3'
|
|
keep_sidecar_releases:
|
|
description: 'Number of sidecar releases to keep'
|
|
required: false
|
|
default: '2'
|
|
dry_run:
|
|
description: 'Dry run (show what would be deleted without deleting)'
|
|
required: false
|
|
default: 'true'
|
|
|
|
jobs:
|
|
cleanup:
|
|
name: Cleanup Old Releases
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Cleanup releases
|
|
env:
|
|
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
|
|
run: |
|
|
REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
|
KEEP_APP="${{ inputs.keep_app_releases }}"
|
|
KEEP_SIDECAR="${{ inputs.keep_sidecar_releases }}"
|
|
DRY_RUN="${{ inputs.dry_run }}"
|
|
|
|
echo "=== Cleanup Configuration ==="
|
|
echo "Keep app releases: ${KEEP_APP}"
|
|
echo "Keep sidecar releases: ${KEEP_SIDECAR}"
|
|
echo "Dry run: ${DRY_RUN}"
|
|
echo ""
|
|
|
|
# Fetch all releases
|
|
ALL_RELEASES=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \
|
|
"${REPO_API}/releases?limit=50")
|
|
|
|
# ── App releases (v* tags, not sidecar-v*) ──
|
|
echo "=== App Releases ==="
|
|
APP_RELEASES=$(echo "$ALL_RELEASES" | jq -c '[.[] | select(.tag_name | startswith("v")) | select(.tag_name | startswith("sidecar") | not)]')
|
|
APP_TOTAL=$(echo "$APP_RELEASES" | jq 'length')
|
|
echo "Found ${APP_TOTAL} app releases, keeping ${KEEP_APP}"
|
|
|
|
if [ "$APP_TOTAL" -gt "$KEEP_APP" ]; then
|
|
echo "$APP_RELEASES" | jq -c ".[$KEEP_APP:][]" | while read -r release; do
|
|
ID=$(echo "$release" | jq -r '.id')
|
|
TAG=$(echo "$release" | jq -r '.tag_name')
|
|
SIZE=$(echo "$release" | jq '[.assets[]?.size // 0] | add // 0')
|
|
SIZE_MB=$(echo "scale=1; $SIZE / 1048576" | bc 2>/dev/null || echo "?")
|
|
|
|
# Protect v1.4.0 (last pre-Tauri release)
|
|
if [ "$TAG" = "v1.4.0" ]; then
|
|
echo " PROTECT ${TAG} (${SIZE_MB} MB)"
|
|
continue
|
|
fi
|
|
|
|
if [ "$DRY_RUN" = "true" ]; then
|
|
echo " WOULD DELETE ${TAG} (ID: ${ID}, ${SIZE_MB} MB)"
|
|
else
|
|
echo " DELETING ${TAG} (ID: ${ID}, ${SIZE_MB} MB)..."
|
|
curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \
|
|
"${REPO_API}/releases/${ID}"
|
|
fi
|
|
done
|
|
else
|
|
echo " Nothing to clean up"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# ── Sidecar releases (sidecar-v* tags) ──
|
|
echo "=== Sidecar Releases ==="
|
|
SIDECAR_RELEASES=$(echo "$ALL_RELEASES" | jq -c '[.[] | select(.tag_name | startswith("sidecar-v"))]')
|
|
SIDECAR_TOTAL=$(echo "$SIDECAR_RELEASES" | jq 'length')
|
|
echo "Found ${SIDECAR_TOTAL} sidecar releases, keeping ${KEEP_SIDECAR}"
|
|
|
|
if [ "$SIDECAR_TOTAL" -gt "$KEEP_SIDECAR" ]; then
|
|
echo "$SIDECAR_RELEASES" | jq -c ".[$KEEP_SIDECAR:][]" | while read -r release; do
|
|
ID=$(echo "$release" | jq -r '.id')
|
|
TAG=$(echo "$release" | jq -r '.tag_name')
|
|
SIZE=$(echo "$release" | jq '[.assets[]?.size // 0] | add // 0')
|
|
SIZE_MB=$(echo "scale=1; $SIZE / 1048576" | bc 2>/dev/null || echo "?")
|
|
|
|
if [ "$DRY_RUN" = "true" ]; then
|
|
echo " WOULD DELETE ${TAG} (ID: ${ID}, ${SIZE_MB} MB)"
|
|
else
|
|
echo " DELETING ${TAG} (ID: ${ID}, ${SIZE_MB} MB)..."
|
|
curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \
|
|
"${REPO_API}/releases/${ID}"
|
|
fi
|
|
done
|
|
else
|
|
echo " Nothing to clean up"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Done ==="
|