diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml index e712f5c8843..5d31e55ca2d 100644 --- a/.github/workflows/tag-release.yml +++ b/.github/workflows/tag-release.yml @@ -54,6 +54,8 @@ jobs: RELEASE_URL: ${{ github.event.release.html_url || github.event.inputs.release_url }} RELEASE_TAG: ${{ github.event.release.tag_name || github.event.inputs.release_tag }} run: | + set -euo pipefail + # Construct the Discord message with the release title and body message="**SpacetimeDB ${RELEASE_TAG}**" message+=$'\n\n' @@ -63,26 +65,46 @@ jobs: message+=$'\n\n' message+="${RELEASE_BODY}" - # Use jq to construct the JSON payload for the webhook - data="$(jq --null-input \ - --arg content "$message" \ - '.content=$content')" + # Send a single chunk to Discord, exiting on HTTP error. + post_chunk() { + local chunk="$1" + local data + data="$(jq --null-input --arg content "$chunk" \ + '.content=$content | .allowed_mentions={"parse":["roles","users"]}')" + if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then + echo "=== DRY RUN chunk ===" + echo "$data" | jq . + else + curl --fail-with-body -X POST \ + -H 'Content-Type: application/json' \ + -d "$data" \ + "${DISCORD_WEBHOOK_URL}" + fi + } + + # Split message into chunks of at most 2000 characters, breaking on newlines. + MAX=2000 + current_chunk="" + while IFS= read -r line || [ -n "$line" ]; do + # +1 for the newline we append after each line + candidate="${current_chunk}${line}"$'\n' + if [ "${#candidate}" -gt "$MAX" ]; then + if [ -n "$current_chunk" ]; then + post_chunk "$current_chunk" + current_chunk="" + fi + # If a single line exceeds the limit, bail out loudly rather than silently truncating. + if [ "$((${#line} + 1))" -gt "$MAX" ]; then + echo "ERROR: A single line is longer than ${MAX} characters and cannot be posted to Discord." >&2 + exit 1 + fi + current_chunk="${line}"$'\n' + else + current_chunk="$candidate" + fi + done <<< "$message" - # Dry run: just print what would be sent - if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then - echo "=== DRY RUN - Message that would be sent to Discord ===" - echo "JSON payload:" - echo "$data" | jq . - echo "" - echo "Formatted message preview:" - echo "$message" - echo "" - echo "=== End of dry run ===" - else - # Send the webhook - echo "Sending Discord notification..." - curl -X POST \ - -H 'Content-Type: application/json' \ - -d "$data" \ - "${DISCORD_WEBHOOK_URL}" + # Post any remaining content + if [ -n "$current_chunk" ]; then + post_chunk "$current_chunk" fi