diff --git a/forgejo-release.sh b/forgejo-release.sh index 1c01f37..dc3dfdf 100755 --- a/forgejo-release.sh +++ b/forgejo-release.sh @@ -12,6 +12,7 @@ if ${VERBOSE:-false}; then set -x; fi : ${DOWNLOAD_LATEST:=false} : ${TMP_DIR:=$(mktemp -d)} : ${GNUPGHOME:=$TMP_DIR} +: ${REUSE_RELEASE:=false} : ${OVERRIDE:=false} : ${HIDE_ARCHIVE_LINK:=false} : ${RETRY:=1} @@ -22,6 +23,7 @@ RELEASE_NOTES_ASSISTANT_VERSION=v1.7.3 # renovate: datasource=forgejo-releases d TAG_FILE="$TMP_DIR/tag$$.json" TAG_URL=$(echo "$TAG" | sed 's/\//%2F/g') +RELEASE_FILE="$TMP_DIR/release.json" export GNUPGHOME @@ -68,6 +70,98 @@ delete_tag() { fi } +get_release() { + api_json GET repos/$REPO/releases/tags/"$TAG_URL" >"$RELEASE_FILE" +} + +delete_existing_asset() { + local release_id="$1" + local asset_name="$2" + local assets_file="$TMP_DIR/assets-$release_id.json" + local asset_id + + api_json GET repos/$REPO/releases/"$release_id"/assets >"$assets_file" + + asset_id=$( + jq --raw-output \ + --arg name "$asset_name" \ + '.[] | select(.name == $name) | .id' \ + <"$assets_file" | + head -n 1 + ) + + if test -n "$asset_id" && test "$asset_id" != "null"; then + echo "Deleting existing asset $asset_name" + api_json DELETE \ + repos/$REPO/releases/"$release_id"/assets/"$asset_id" \ + >/dev/null + fi +} + +upload_assets() { + local release_id="$1" + local replace_existing="${2:-false}" + local file + local asset_name + local encoded_asset_name + + if test "$SKIP_ASSETS" = "true"; then + return + fi + + if ! compgen -G "$RELEASE_DIR/*" >/dev/null; then + echo "No assets found in $RELEASE_DIR" + return + fi + + for file in "$RELEASE_DIR"/*; do + test -f "$file" || continue + + asset_name="${file##*/}" + + if test "$replace_existing" = "true"; then + delete_existing_asset "$release_id" "$asset_name" + fi + + encoded_asset_name="$(printf '%s' "$asset_name" | jq -sRr @uri)" + + echo "Uploading asset $asset_name" + + if ! api POST "repos/$REPO/releases/$release_id/assets?name=$encoded_asset_name" -H "Content-Type: multipart/form-data" -F "attachment=@$file" >"$TMP_DIR/release-$encoded_asset_name.json"; then + if ${VERBOSE:-false}; then + echo "Response:" + jq . <"$TMP_DIR/release-$encoded_asset_name.json" + fi + return 1 + fi + done +} + +reuse_release() { + if test "$REUSE_RELEASE" != "true"; then + return 1 + fi + + if ! get_release; then + echo "No existing release found for $TAG; creating a new release" + rm -f "$RELEASE_FILE" + return 1 + fi + + local release_id + release_id=$(jq --raw-output .id <"$RELEASE_FILE") + + if test -z "$release_id" || test "$release_id" = "null"; then + echo "Existing release for $TAG has no valid ID" + return 1 + fi + + echo "Reusing release $TAG with ID $release_id" + echo "The release title, body and settings will be preserved" + + upload_assets "$release_id" true +} + upload_release() { if $PRERELEASE || echo "${TAG}" | grep -qi '\-rc'; then prerelease="true" @@ -77,6 +171,11 @@ upload_release() { echo "Uploading as Stable" fi ensure_tag + + if reuse_release; then + return + fi + jq -n --arg title "$TITLE" --arg body "$RELEASENOTES" --arg tag "$TAG" --arg pre $prerelease '{"draft": true, "name": $title, "body": $body, "prerelease": $pre | test("true"), "tag_name": $tag }' >"$TMP_DIR"/release-payload.json if ${VERBOSE:-false}; then echo "Payload:" @@ -89,22 +188,9 @@ upload_release() { fi exit 1 fi - if [ "$SKIP_ASSETS" == 'false' ]; then - release_id=$(jq --raw-output .id <"$TMP_DIR"/release.json) - for file in "$RELEASE_DIR"/*; do - # https://dev.to/pkutaj/how-to-use-jq-for-uri-encoding-2o5 - # https://unix.stackexchange.com/questions/94295/shellcheck-is-advising-not-to-use-basename-why/94307#94307 - # url encode some chars - asset_name="$(echo -n "${file##*/}" | jq -sRr @uri)" - if ! api POST "repos/$REPO/releases/$release_id/assets?name=$asset_name" -H "Content-Type: multipart/form-data" -F "attachment=@$file" >"$TMP_DIR/release-$asset_name.json"; then - if ${VERBOSE:-false}; then - echo "Response:" - cat "$TMP_DIR/release-$asset_name.json" | jq - fi - exit 1 - fi - done - fi + + release_id=$(jq --raw-output .id <"$TMP_DIR"/release.json) + upload_assets "$release_id" false maybe_use_release_note_assistant release_draft false } @@ -150,6 +236,13 @@ maybe_override() { if test "$OVERRIDE" = "false"; then return fi + + if test "$REUSE_RELEASE" = "true"; then + echo "override is ignored because reuse-release is enabled" + echo "reuse-release takes precedence to preserves the release" + return + fi + api_json DELETE repos/$REPO/releases/tags/"$TAG_URL" >&/dev/null || true if get_tag && ! matched_tag; then delete_tag