From bd6eec88affd9fbc670404203fc7eab39f378bff Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Mon, 25 May 2026 22:11:53 -0500 Subject: [PATCH] feat(ci): checksums as [filename].sha256 assets, not in release body Upload per-file .sha256 checksum files alongside packages instead of embedding SHA-256 in the release description. Format: "hash filename" matching standard sha256sum output. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .mokogitea/workflows/auto-release.yml | 40 +++++++++++++++++---------- .mokogitea/workflows/pre-release.yml | 9 +++++- CHANGELOG.md | 3 ++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index 351ee438..0d6611d2 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -480,16 +480,31 @@ jobs: fi done - # -- Upload both to release tag ---------------------------------- - curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @"/tmp/${ZIP_NAME}" \ - "${API_BASE}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" > /dev/null 2>&1 || true + # -- Create per-file .sha256 checksum files ------------------------- + echo "${SHA256_ZIP} ${ZIP_NAME}" > "/tmp/${ZIP_NAME}.sha256" + echo "${SHA256_TAR} ${TAR_NAME}" > "/tmp/${TAR_NAME}.sha256" - curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @"/tmp/${TAR_NAME}" \ - "${API_BASE}/releases/${RELEASE_ID}/assets?name=${TAR_NAME}" > /dev/null 2>&1 || true + # -- Upload packages + checksums to release tag -------------------- + for ASSET in "${ZIP_NAME}" "${TAR_NAME}" "${ZIP_NAME}.sha256" "${TAR_NAME}.sha256"; do + [ ! -f "/tmp/${ASSET}" ] && continue + # Delete existing asset with same name + ASSET_ID=$(echo "$ASSETS" | python3 -c " + import sys,json + assets = json.load(sys.stdin) + for a in assets: + if a['name'] == '${ASSET}': + print(a['id']); break + " 2>/dev/null || true) + [ -n "$ASSET_ID" ] && curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ + "${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true + # Upload + curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary @"/tmp/${ASSET}" \ + "${API_BASE}/releases/${RELEASE_ID}/assets?name=${ASSET}" > /dev/null 2>&1 || true + done + + # (tar upload handled in the loop above) # -- Update updates.xml with both download formats --------------- if [ -f "updates.xml" ]; then @@ -615,15 +630,12 @@ jobs: [ -z "$CHANGELOG" ] && CHANGELOG=$(sed -n '/^## /,/^## /p' CHANGELOG.md | sed '$d' | sed '1d' | head -30) fi - # Build release body (single header, no duplicate from changelog) + # Build release body (changelog only — checksums attached as .sha256 files) BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n" if [ -n "$CHANGELOG" ]; then BODY="${BODY}${CHANGELOG}\n\n" fi - BODY="${BODY}---\n\n### Checksums\n\n" - BODY="${BODY}| File | SHA-256 |\n|------|--------|\n" - [ -n "$SHA256_ZIP" ] && BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n" - [ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n" + BODY="${BODY}---\n\nChecksum files attached as \`*.sha256\` assets.\n" # Get release ID and update body RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index d0d5e249..c737ad01 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -236,7 +236,7 @@ jobs: BODY="## ${VERSION} ($(date +%Y-%m-%d)) **Channel:** ${STABILITY} - **SHA-256:** \`${SHA256}\`" + Checksum file attached as \`${ZIP_NAME}.sha256\`." # Delete existing release EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \ @@ -268,6 +268,13 @@ jobs: "${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \ --data-binary "@build/${ZIP_NAME}" + # Upload per-file checksum + echo "${SHA256} ${ZIP_NAME}" > "build/${ZIP_NAME}.sha256" + curl -sS -X POST -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + "${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}.sha256" \ + --data-binary "@build/${ZIP_NAME}.sha256" + echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})" - name: Update updates.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index ebe4d9e3..72266737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly) - Clean up extracted temp directory on success or failure - Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it +- CI: auto-release fetches updates.xml from main before building (preserves all channels) +- CI: version_check.php --fix runs after version bump in both workflows +- CI: checksums attached as `[filename].sha256` files instead of in release body ### Changed - CI: auto-release uses stream tag `stable` instead of version tag `vXX`