From 7da5084337f6c93ca79f5adac145896951d314e2 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Wed, 25 Mar 2026 13:20:05 +0300 Subject: [PATCH] fix: prevent duplicate release assets on re-triggered CI workflows Gitea silently appends duplicate asset names. Added delete-before-upload logic to both Windows and Linux asset upload steps. --- .gitea/workflows/release.yml | 48 ++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index b053e74..924d39c 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -131,27 +131,31 @@ jobs: RELEASE_ID="${{ needs.create-release.outputs.release_id }}" BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}" - # Upload ZIP - ZIP_FILE=$(ls build/LedGrab-*.zip | head -1) - if [ -f "$ZIP_FILE" ]; then + # Upload helper — deletes existing asset with same name to prevent duplicates on re-run + upload_asset() { + local FILE="$1" + local NAME=$(basename "$FILE") + EXISTING_ID=$(curl -s "$BASE_URL/releases/$RELEASE_ID/assets" \ + -H "Authorization: token $GITEA_TOKEN" \ + | python3 -c "import sys,json; assets=json.load(sys.stdin); print(next((str(a['id']) for a in assets if a['name']=='$NAME'),''))" 2>/dev/null) + if [ -n "$EXISTING_ID" ]; then + curl -s -X DELETE "$BASE_URL/releases/$RELEASE_ID/assets/$EXISTING_ID" \ + -H "Authorization: token $GITEA_TOKEN" + echo "Replaced existing asset: $NAME" + fi curl -s -X POST \ - "$BASE_URL/releases/$RELEASE_ID/assets?name=$(basename "$ZIP_FILE")" \ + "$BASE_URL/releases/$RELEASE_ID/assets?name=$NAME" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/octet-stream" \ - --data-binary "@$ZIP_FILE" - echo "Uploaded: $(basename "$ZIP_FILE")" - fi + --data-binary "@$FILE" + echo "Uploaded: $NAME" + } + + ZIP_FILE=$(ls build/LedGrab-*.zip | head -1) + [ -f "$ZIP_FILE" ] && upload_asset "$ZIP_FILE" - # Upload installer SETUP_FILE=$(ls build/LedGrab-*-setup.exe 2>/dev/null | head -1) - if [ -f "$SETUP_FILE" ]; then - curl -s -X POST \ - "$BASE_URL/releases/$RELEASE_ID/assets?name=$(basename "$SETUP_FILE")" \ - -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/octet-stream" \ - --data-binary "@$SETUP_FILE" - echo "Uploaded: $(basename "$SETUP_FILE")" - fi + [ -f "$SETUP_FILE" ] && upload_asset "$SETUP_FILE" # ── Linux tarball ────────────────────────────────────────── build-linux: @@ -194,18 +198,26 @@ jobs: env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | - TAG="${{ gitea.ref_name }}" RELEASE_ID="${{ needs.create-release.outputs.release_id }}" BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}" TAR_FILE=$(ls build/LedGrab-*.tar.gz | head -1) TAR_NAME=$(basename "$TAR_FILE") + # Delete existing asset with same name to prevent duplicates on re-run + EXISTING_ID=$(curl -s "$BASE_URL/releases/$RELEASE_ID/assets" \ + -H "Authorization: token $GITEA_TOKEN" \ + | python3 -c "import sys,json; assets=json.load(sys.stdin); print(next((str(a['id']) for a in assets if a['name']=='$TAR_NAME'),''))" 2>/dev/null) + if [ -n "$EXISTING_ID" ]; then + curl -s -X DELETE "$BASE_URL/releases/$RELEASE_ID/assets/$EXISTING_ID" \ + -H "Authorization: token $GITEA_TOKEN" + echo "Replaced existing asset: $TAR_NAME" + fi + curl -s -X POST \ "$BASE_URL/releases/$RELEASE_ID/assets?name=$TAR_NAME" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/octet-stream" \ --data-binary "@$TAR_FILE" - echo "Uploaded: $TAR_NAME" # ── Docker image ───────────────────────────────────────────