mirror of
				https://code.forgejo.org/actions/forgejo-release.git
				synced 2025-11-04 06:41:57 +02:00 
			
		
		
		
	Merge pull request 'fix: override=true must not needlessly delete a tag' (#39) from limiting-factor/forgejo-release:wip-override into main
Reviewed-on: https://code.forgejo.org/actions/forgejo-release/pulls/39 Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
This commit is contained in:
		
						commit
						e2af55222e
					
				
					 2 changed files with 87 additions and 60 deletions
				
			
		| 
						 | 
				
			
			@ -19,26 +19,47 @@ if ${VERBOSE:-false}; then set -x; fi
 | 
			
		|||
: ${RETRY:=1}
 | 
			
		||||
: ${DELAY:=10}
 | 
			
		||||
 | 
			
		||||
TAG_FILE="$TMP_DIR/tag$$.json"
 | 
			
		||||
 | 
			
		||||
export GNUPGHOME
 | 
			
		||||
 | 
			
		||||
setup_tea() {
 | 
			
		||||
    if ! test -f "$BIN_DIR"/tea ; then
 | 
			
		||||
    ARCH=$(dpkg --print-architecture)
 | 
			
		||||
    curl -sL https://dl.gitea.io/tea/$TEA_VERSION/tea-$TEA_VERSION-linux-"$ARCH" > "$BIN_DIR"/tea
 | 
			
		||||
    chmod +x "$BIN_DIR"/tea
 | 
			
		||||
    if ! test -f "$BIN_DIR"/tea; then
 | 
			
		||||
        ARCH=$(dpkg --print-architecture)
 | 
			
		||||
        curl -sL https://dl.gitea.io/tea/$TEA_VERSION/tea-$TEA_VERSION-linux-"$ARCH" >"$BIN_DIR"/tea
 | 
			
		||||
        chmod +x "$BIN_DIR"/tea
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
get_tag() {
 | 
			
		||||
    if ! test -f "$TAG_FILE"; then
 | 
			
		||||
        if api GET repos/$REPO/tags/"$TAG" >"$TAG_FILE"; then
 | 
			
		||||
            echo "tag $TAG exists"
 | 
			
		||||
        else
 | 
			
		||||
            echo "tag $TAG does not exists"
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
    test -s "$TAG_FILE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
matched_tag() {
 | 
			
		||||
    if get_tag; then
 | 
			
		||||
        local sha=$(jq --raw-output .commit.sha <"$TAG_FILE")
 | 
			
		||||
        test "$sha" = "$SHA"
 | 
			
		||||
    else
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ensure_tag() {
 | 
			
		||||
    if api GET repos/$REPO/tags/"$TAG" > "$TMP_DIR"/tag.json ; then
 | 
			
		||||
    local sha=$(jq --raw-output .commit.sha < "$TMP_DIR"/tag.json)
 | 
			
		||||
    if test "$sha" != "$SHA" ; then
 | 
			
		||||
        cat "$TMP_DIR"/tag.json
 | 
			
		||||
        echo "the tag SHA in the $REPO repository does not match the tag SHA that triggered the build: $SHA"
 | 
			
		||||
        false
 | 
			
		||||
    fi
 | 
			
		||||
    if get_tag; then
 | 
			
		||||
        if ! matched_tag; then
 | 
			
		||||
            cat "$TAG_FILE"
 | 
			
		||||
            echo "the tag SHA in the $REPO repository does not match the tag SHA that triggered the build: $SHA"
 | 
			
		||||
            return 1
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
    api POST repos/$REPO/tags --data-raw '{"tag_name": "'"$TAG"'", "target": "'"$SHA"'"}'
 | 
			
		||||
        api POST repos/$REPO/tags --data-raw '{"tag_name": "'"$TAG"'", "target": "'"$SHA"'"}' >"$TAG_FILE"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,15 +71,15 @@ upload_release() {
 | 
			
		|||
    for file in "$RELEASE_DIR"/*; do
 | 
			
		||||
        assets=("${assets[@]}" -a "$file")
 | 
			
		||||
    done
 | 
			
		||||
    if $PRERELEASE || echo "${TAG}" | grep -qi '\-rc' ; then
 | 
			
		||||
    if $PRERELEASE || echo "${TAG}" | grep -qi '\-rc'; then
 | 
			
		||||
        releaseType="--prerelease"
 | 
			
		||||
        echo "Uploading as Pre-Release"
 | 
			
		||||
    else
 | 
			
		||||
        echo "Uploading as Stable"
 | 
			
		||||
    fi
 | 
			
		||||
    ensure_tag
 | 
			
		||||
    if ! "$BIN_DIR"/tea release create "${assets[@]}" --repo $REPO --note "$RELEASENOTES" --tag "$TAG" --title "$TITLE" --draft ${releaseType} >& "$TMP_DIR"/tea.log ; then
 | 
			
		||||
        if grep --quiet 'Unknown API Error: 500' "$TMP_DIR"/tea.log && grep --quiet services/release/release.go:194 "$TMP_DIR"/tea.log ; then
 | 
			
		||||
    if ! "$BIN_DIR"/tea release create "${assets[@]}" --repo $REPO --note "$RELEASENOTES" --tag "$TAG" --title "$TITLE" --draft ${releaseType} >&"$TMP_DIR"/tea.log; then
 | 
			
		||||
        if grep --quiet 'Unknown API Error: 500' "$TMP_DIR"/tea.log && grep --quiet services/release/release.go:194 "$TMP_DIR"/tea.log; then
 | 
			
		||||
            echo "workaround v1.20 race condition https://codeberg.org/forgejo/forgejo/issues/1370"
 | 
			
		||||
            sleep 10
 | 
			
		||||
            "$BIN_DIR"/tea release create "${assets[@]}" --repo $REPO --note "$RELEASENOTES" --tag "$TAG" --title "$TITLE" --draft ${releaseType}
 | 
			
		||||
| 
						 | 
				
			
			@ -90,29 +111,31 @@ maybe_use_release_note_assistant() {
 | 
			
		|||
sign_release() {
 | 
			
		||||
    local passphrase
 | 
			
		||||
    if test -s "$GPG_PASSPHRASE"; then
 | 
			
		||||
    passphrase="--passphrase-file $GPG_PASSPHRASE"
 | 
			
		||||
        passphrase="--passphrase-file $GPG_PASSPHRASE"
 | 
			
		||||
    fi
 | 
			
		||||
    gpg --import --no-tty --pinentry-mode loopback $passphrase "$GPG_PRIVATE_KEY"
 | 
			
		||||
    for asset in "$RELEASE_DIR"/* ; do
 | 
			
		||||
    if [[ $asset =~ .sha256$ ]] ; then
 | 
			
		||||
        continue
 | 
			
		||||
    fi
 | 
			
		||||
    gpg --armor --detach-sign --no-tty --pinentry-mode loopback $passphrase < "$asset" > "$asset".asc
 | 
			
		||||
    for asset in "$RELEASE_DIR"/*; do
 | 
			
		||||
        if [[ $asset =~ .sha256$ ]]; then
 | 
			
		||||
            continue
 | 
			
		||||
        fi
 | 
			
		||||
        gpg --armor --detach-sign --no-tty --pinentry-mode loopback $passphrase <"$asset" >"$asset".asc
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
maybe_sign_release() {
 | 
			
		||||
    if test -s "$GPG_PRIVATE_KEY"; then
 | 
			
		||||
    sign_release
 | 
			
		||||
        sign_release
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
maybe_override() {
 | 
			
		||||
    if test "$OVERRIDE" = "false"; then
 | 
			
		||||
    return
 | 
			
		||||
        return
 | 
			
		||||
    fi
 | 
			
		||||
    api DELETE repos/$REPO/releases/tags/"$TAG" >&/dev/null || true
 | 
			
		||||
    if get_tag && ! matched_tag; then
 | 
			
		||||
        api DELETE repos/$REPO/tags/"$TAG"
 | 
			
		||||
    fi
 | 
			
		||||
    api DELETE repos/$REPO/releases/tags/"$TAG" >& /dev/null || true
 | 
			
		||||
    api DELETE repos/$REPO/tags/"$TAG" >& /dev/null || true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
upload() {
 | 
			
		||||
| 
						 | 
				
			
			@ -126,9 +149,9 @@ upload() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
setup_api() {
 | 
			
		||||
    if ! which jq curl ; then
 | 
			
		||||
    apt-get -qq update
 | 
			
		||||
    apt-get install -y -qq jq curl
 | 
			
		||||
    if ! which jq curl; then
 | 
			
		||||
        apt-get -qq update
 | 
			
		||||
        apt-get install -y -qq jq curl
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -144,40 +167,40 @@ api() {
 | 
			
		|||
wait_release() {
 | 
			
		||||
    local ready=false
 | 
			
		||||
    for i in $(seq $RETRY); do
 | 
			
		||||
    if api GET repos/$REPO/releases/tags/"$TAG" | jq --raw-output .draft > "$TMP_DIR"/draft; then
 | 
			
		||||
        if test "$(cat "$TMP_DIR"/draft)" = "false"; then
 | 
			
		||||
        ready=true
 | 
			
		||||
        break
 | 
			
		||||
        if api GET repos/$REPO/releases/tags/"$TAG" | jq --raw-output .draft >"$TMP_DIR"/draft; then
 | 
			
		||||
            if test "$(cat "$TMP_DIR"/draft)" = "false"; then
 | 
			
		||||
                ready=true
 | 
			
		||||
                break
 | 
			
		||||
            fi
 | 
			
		||||
            echo "release $TAG is still a draft"
 | 
			
		||||
        else
 | 
			
		||||
            echo "release $TAG does not exist yet"
 | 
			
		||||
        fi
 | 
			
		||||
        echo "release $TAG is still a draft"
 | 
			
		||||
    else
 | 
			
		||||
        echo "release $TAG does not exist yet"
 | 
			
		||||
    fi
 | 
			
		||||
    echo "waiting $DELAY seconds"
 | 
			
		||||
    sleep $DELAY
 | 
			
		||||
        echo "waiting $DELAY seconds"
 | 
			
		||||
        sleep $DELAY
 | 
			
		||||
    done
 | 
			
		||||
    if ! $ready ; then
 | 
			
		||||
    echo "no release for $TAG"
 | 
			
		||||
    return 1
 | 
			
		||||
    if ! $ready; then
 | 
			
		||||
        echo "no release for $TAG"
 | 
			
		||||
        return 1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
download() {
 | 
			
		||||
    setup_api
 | 
			
		||||
    (
 | 
			
		||||
    mkdir -p $RELEASE_DIR
 | 
			
		||||
    cd $RELEASE_DIR
 | 
			
		||||
    if [[ ${DOWNLOAD_LATEST} == "true" ]] ; then
 | 
			
		||||
        echo "Downloading the latest release"
 | 
			
		||||
        api GET repos/$REPO/releases/latest > "$TMP_DIR"/assets.json
 | 
			
		||||
    elif [[ ${DOWNLOAD_LATEST} == "false" ]] ; then
 | 
			
		||||
        wait_release
 | 
			
		||||
        echo "Downloading tagged release ${TAG}"
 | 
			
		||||
        api GET repos/$REPO/releases/tags/"$TAG" > "$TMP_DIR"/assets.json
 | 
			
		||||
    fi
 | 
			
		||||
     jq --raw-output '.assets[] | "\(.browser_download_url) \(.name)"' < "$TMP_DIR"/assets.json | while read url name  ; do  # `name` may contain whitespace, therefore, it must be last
 | 
			
		||||
       curl --fail -H "Authorization: token $TOKEN" -o "$name" -L "$url"
 | 
			
		||||
     done
 | 
			
		||||
        mkdir -p $RELEASE_DIR
 | 
			
		||||
        cd $RELEASE_DIR
 | 
			
		||||
        if [[ ${DOWNLOAD_LATEST} == "true" ]]; then
 | 
			
		||||
            echo "Downloading the latest release"
 | 
			
		||||
            api GET repos/$REPO/releases/latest >"$TMP_DIR"/assets.json
 | 
			
		||||
        elif [[ ${DOWNLOAD_LATEST} == "false" ]]; then
 | 
			
		||||
            wait_release
 | 
			
		||||
            echo "Downloading tagged release ${TAG}"
 | 
			
		||||
            api GET repos/$REPO/releases/tags/"$TAG" >"$TMP_DIR"/assets.json
 | 
			
		||||
        fi
 | 
			
		||||
        jq --raw-output '.assets[] | "\(.browser_download_url) \(.name)"' <"$TMP_DIR"/assets.json | while read url name; do # `name` may contain whitespace, therefore, it must be last
 | 
			
		||||
            curl --fail -H "Authorization: token $TOKEN" -o "$name" -L "$url"
 | 
			
		||||
        done
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								testdata/forgejo-release-test.sh
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								testdata/forgejo-release-test.sh
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
# SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
PS4='${BASH_SOURCE[0]}:$LINENO: ${FUNCNAME[0]}:  '
 | 
			
		||||
 | 
			
		||||
test_teardown() {
 | 
			
		||||
    setup_api
 | 
			
		||||
| 
						 | 
				
			
			@ -44,16 +45,19 @@ test_ensure_tag() {
 | 
			
		|||
    # idempotent
 | 
			
		||||
    #
 | 
			
		||||
    ensure_tag
 | 
			
		||||
    api GET repos/$REPO/tags/$TAG > $TMP_DIR/tag1.json
 | 
			
		||||
    mv $TAG_FILE $TMP_DIR/tag1.json
 | 
			
		||||
 | 
			
		||||
    ensure_tag
 | 
			
		||||
    api GET repos/$REPO/tags/$TAG > $TMP_DIR/tag2.json
 | 
			
		||||
    mv $TAG_FILE $TMP_DIR/tag2.json
 | 
			
		||||
 | 
			
		||||
    diff -u $TMP_DIR/tag[12].json
 | 
			
		||||
    #
 | 
			
		||||
    # sanity check on the SHA of an existing tag
 | 
			
		||||
    #
 | 
			
		||||
    (
 | 
			
		||||
	SHA=12345
 | 
			
		||||
	! ensure_tag
 | 
			
		||||
        SHA=12345
 | 
			
		||||
        ! matched_tag
 | 
			
		||||
        ! ensure_tag
 | 
			
		||||
    )
 | 
			
		||||
    api DELETE repos/$REPO/tags/$TAG
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +98,8 @@ test_maybe_sign_release_skipped() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
test_maybe_sign_release_verify() {
 | 
			
		||||
    for file in  $RELEASE_DIR/file-one.txt  $RELEASE_DIR/file-two.txt; do
 | 
			
		||||
	gpg --verify $file.asc $file
 | 
			
		||||
    for file in $RELEASE_DIR/file-one.txt $RELEASE_DIR/file-two.txt; do
 | 
			
		||||
        gpg --verify $file.asc $file
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue