#!/usr/bin/env bash # Upload files to the draft release for RELEASE_TAG. Platform builds hand their installers to # the draft this way, so releases never use GitHub Actions artifact storage. Needs only curl # and jq, which every release runner has (the macOS runner has no gh). set -euo pipefail : "${GH_TOKEN:?GH_TOKEN is required}" : "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required}" : "${RELEASE_TAG:?RELEASE_TAG is required}" if [[ $# -eq 0 ]]; then echo "Usage: upload-release-assets ..." >&2 exit 1 fi api="${GITHUB_API_URL:-https://api.github.com}" auth=(-H "Authorization: Bearer ${GH_TOKEN}" -H "Accept: application/vnd.github+json") # Draft releases have no tag URL yet, so find the one draft for this tag in the list. release="$(curl -fsSL "${auth[@]}" "$api/repos/$GITHUB_REPOSITORY/releases?per_page=100" | jq -c --arg tag "$RELEASE_TAG" \ '[.[] | select(.draft and .tag_name == $tag)] | if length == 1 then .[0] else error("expected one draft release for \($tag)") end')" upload_url="$(jq -r '.upload_url | sub("\\{.*\\}$"; "")' <<<"$release")" for file in "$@"; do name="$(basename "$file")" # A re-run replaces its own earlier upload instead of failing on the duplicate name; # GitHub stores spaces in asset names as dots. existing="$(jq -r --arg name "$name" '.assets[] | select(.name == $name or .name == ($name | gsub(" "; "."))) | .id' <<<"$release")" if [[ -n "$existing" ]]; then curl -fsSL -X DELETE "${auth[@]}" "$api/repos/$GITHUB_REPOSITORY/releases/assets/$existing" fi curl -fsSL "${auth[@]}" -H "Content-Type: application/octet-stream" --data-binary "@$file" \ "$upload_url?name=$(jq -rn --arg name "$name" '$name | @uri')" >/dev/null echo "Uploaded $name" done