From 83854779c88155085dca4b06bff7f133da6b8923 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 19 Jul 2026 18:21:47 -0700 Subject: [PATCH] fix(publish): pass multipart JSON via files, not inline -F values curl's -F parses ; and , inside inline values as attribute separators. Any changelog containing them - every HTML entity does - truncated the JSON part, so CurseForge rejected metadata as invalid JSON and Hangar failed to read the request. The Claude-Session: https://claude.ai/code/session_01RJmrCPRxnwMnWQvGKpEpGY --- .github/workflows/publish-platforms.yml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-platforms.yml b/.github/workflows/publish-platforms.yml index f95540f..c492d6f 100644 --- a/.github/workflows/publish-platforms.yml +++ b/.github/workflows/publish-platforms.yml @@ -255,15 +255,20 @@ jobs: # publishes against every version CurseForge does accept. echo "CurseForge gameVersion ids: $(echo "$GV" | jq -c '.')" for attempt in $(seq 1 25); do - META=$(jq -n \ + # Pass the metadata via a file (curl's ` cf_meta.json HTTP=$(curl -sS -o cf_resp.json -w '%{http_code}' -X POST \ "https://minecraft.curseforge.com/api/projects/${CF_ID}/upload-file" \ -H "X-Api-Token: ${CURSEFORGE_TOKEN}" \ - -F "metadata=${META};type=application/json" \ + -F "metadata=/dev/null) if [ "$HTTP" -ge 200 ] && [ "$HTTP" -lt 300 ]; then @@ -335,9 +340,11 @@ jobs: | jq -r '.token') if [ -z "$JWT" ] || [ "$JWT" = "null" ]; then echo "::error::Hangar auth failed"; exit 1; fi - # 2. Build the versionUpload JSON. + # 2. Build the versionUpload JSON. Written to a file because an inline + # -F value treats `;` and `,` as attribute separators, so a changelog + # containing them gets truncated and Hangar fails to read the request. PAPER_JSON=$(echo "$PV" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))') - UPLOAD=$(jq -n \ + jq -n \ --arg v "$VERSION" \ --arg ch "$CHANNEL" \ --arg desc "$CHANGELOG" \ @@ -345,13 +352,14 @@ jobs: '{version:$v, channel:$ch, description:$desc, pluginDependencies:{}, platformDependencies:{PAPER:$paper}, - files:[{platforms:["PAPER"]}]}') + files:[{platforms:["PAPER"]}]}' \ + > hangar_upload.json # 3. Upload (versionUpload part + the jar as the files part). HTTP=$(curl -sS -o hangar_resp.json -w '%{http_code}' -X POST \ "https://hangar.papermc.io/api/v1/projects/${OWNER}/${SLUG}/upload" \ -H "Authorization: ${JWT}" \ - -F "versionUpload=${UPLOAD};type=application/json" \ + -F "versionUpload=/dev/null)" if [ "$HTTP" -lt 200 ] || [ "$HTTP" -ge 300 ]; then