From 03d2e6b1f2310c2da21cbaa95826ba2241b91535 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Wed, 22 Apr 2026 19:40:46 +0300 Subject: [PATCH] ci(release): publish .sha256 sidecars alongside release assets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The in-app update service (`ledgrab.core.update.update_service`) refuses to install any downloaded artifact that has no published sha256 — either as a sibling `.sha256` asset on the Gitea release, or embedded in the release body. The release workflow uploaded the ZIP, setup.exe, and Linux tarball but never published checksums, so every auto-update 500'd with "Update checksum unavailable; install aborted". Generate sha256sum sidecars for the Windows ZIP, Windows setup.exe, and Linux tar.gz and upload them next to the primary asset on each tagged release. Existing v0.4.x releases stay broken — ship v0.4.2 (or manually upload sidecars to v0.4.1) to unblock in-app updates. --- .gitea/workflows/release.yml | 56 ++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 68092b2..b2b32ea 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -191,11 +191,21 @@ jobs: echo "Uploaded: $NAME" } + # Publish an asset plus its .sha256 sidecar. The in-app update + # service refuses to install without a published checksum, so + # every artifact needs its hash uploaded alongside. + upload_with_sha256() { + local FILE="$1" + upload_asset "$FILE" + (cd "$(dirname "$FILE")" && sha256sum "$(basename "$FILE")" > "$(basename "$FILE").sha256") + upload_asset "$FILE.sha256" + } + ZIP_FILE=$(ls build/LedGrab-*.zip | head -1) - [ -f "$ZIP_FILE" ] && upload_asset "$ZIP_FILE" + [ -f "$ZIP_FILE" ] && upload_with_sha256 "$ZIP_FILE" SETUP_FILE=$(ls build/LedGrab-*-setup.exe 2>/dev/null | head -1) - [ -f "$SETUP_FILE" ] && upload_asset "$SETUP_FILE" + [ -f "$SETUP_FILE" ] && upload_with_sha256 "$SETUP_FILE" # ── Linux tarball ────────────────────────────────────────── build-linux: @@ -242,26 +252,34 @@ jobs: run: | RELEASE_ID="${{ needs.create-release.outputs.release_id }}" BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}" + + upload_asset() { + local FILE="$1" + local NAME + 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=$NAME" \ + -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$FILE" + echo "Uploaded: $NAME" + } + 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" + if [ -f "$TAR_FILE" ]; then + upload_asset "$TAR_FILE" + (cd "$(dirname "$TAR_FILE")" && sha256sum "$(basename "$TAR_FILE")" > "$(basename "$TAR_FILE").sha256") + upload_asset "$TAR_FILE.sha256" 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 ─────────────────────────────────────────── build-docker: needs: create-release