Przeglądaj źródła

Drone: Upload AppImage to GitHub using nextcloud-desktop-bot

Uploading AppImage's to transfer.sh often fail and cause the CI to wait for
the 15 minutes timeout.

This new approach uses a bot user to create releases in a dedicated ci-builds
repository. Each PR (or master) will get a dedicated release with the AppImage
supplied as a release asset. Older assets will be deleted prior uploading the
recent build.

The bot will then (in case of a PR) create a comment in the PR, containing the
download link.

Home of the CI releases: https://github.com/nextcloud-desktop-bot/ci-builds/releases

Inspired by: https://github.com/nextcloud/android/blob/master/scripts/uploadArtifact.sh

Signed-off-by: Michael Schuster <michael@schuster.ms>
Michael Schuster 5 lat temu
rodzic
commit
c3f5a9b9cc
2 zmienionych plików z 136 dodań i 15 usunięć
  1. 6 1
      .drone.yml
  2. 130 14
      admin/linux/upload-appimage.sh

+ 6 - 1
.drone.yml

@@ -104,9 +104,14 @@ name: AppImage
 steps:
 - name: build
   image: nextcloudci/client-5.12:client-5.12-7
+  environment:
+    CI_UPLOAD_GIT_TOKEN:
+      from_secret: CI_UPLOAD_GIT_TOKEN
+    CI_UPLOAD_GIT_USERNAME:
+      from_secret: CI_UPLOAD_GIT_USERNAME
   commands:
     - /bin/bash -c "./admin/linux/build-appimage.sh"
-    - /bin/bash -c "./admin/linux/upload-appimage.sh"
+    - /bin/bash -c "./admin/linux/upload-appimage.sh" || echo "Upload failed, however this is an optional step."
 trigger:
   branch:
     - master

+ 130 - 14
admin/linux/upload-appimage.sh

@@ -1,21 +1,137 @@
 #! /bin/bash
 
-set -xe
+# Env
+export BUILD=${DRONE_BUILD_NUMBER}
+export PR=${DRONE_PULL_REQUEST}
+export GIT_USERNAME=${CI_UPLOAD_GIT_USERNAME}
+export GIT_TOKEN=${CI_UPLOAD_GIT_TOKEN}
+
+# Defaults
+export GIT_REPO=ci-builds
+export API_BASE_URL=https://api.github.com/repos/$GIT_USERNAME/$GIT_REPO
+export DESKTOP_API_BASE_URL=https://api.github.com/repos/nextcloud/desktop
+
+# PR / master
+export TAG_NAME=${PR:=master}
+export RELEASE_BODY=https://github.com/nextcloud/desktop
+
+if [ $TAG_NAME != "master" ]; then
+    TAG_NAME="PR-$TAG_NAME"
+    RELEASE_BODY="nextcloud/desktop#$PR"
+fi
 
 cd /build
 
-# Upload AppImage
-APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
-BASENAME=$(basename ${APPIMAGE})
-
-if curl --max-time 900 --upload-file ${APPIMAGE} https://transfer.sh/${BASENAME}
-then
-    echo
-    echo "Get the AppImage at the link above!"
-else
-    echo
-    echo "Upload failed, however this is an optional step."
+# AppImage
+export APPIMAGE=$(readlink -f ./Nextcloud*.AppImage)
+export BASENAME=$(basename ${APPIMAGE})
+
+if ! test -e $APPIMAGE ; then
+    exit 1
+fi
+
+echo "Found AppImage: $BASENAME"
+
+apt-get -y install jq
+
+if [[ "$TAG_NAME" != *.master ]]; then
+    # Delete all old comments in desktop PR, starting with "AppImage file:"
+    oldComments=$(curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X GET $DESKTOP_API_BASE_URL/issues/$PR/comments | jq '.[] | (.id |tostring) + "|" + (.user.login | test("'${GIT_USERNAME}'") | tostring) + "|" + (.body | test("AppImage file:.*") | tostring)'  | grep "true|true" | tr -d "\"" | cut -f1 -d"|")
+
+    if [[ "$oldComments" != "" ]]; then
+        echo $oldComments | while read comment ; do
+            curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X DELETE $DESKTOP_API_BASE_URL/issues/comments/$comment
+        done
+    fi
+fi
+
+# Helper functions
+urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
+
+create_release()
+{
+    name=$TAG_NAME
+    body=$RELEASE_BODY
+    tagName=$TAG_NAME
+    echo $(curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X POST $API_BASE_URL/releases -d "{ \"tag_name\": \"$tagName\", \"target_commitish\": \"master\", \"name\": \"$name\", \"body\": \"$body\", \"draft\": false, \"prerelease\": true }")
+}
+
+get_release()
+{
+    tagName=$TAG_NAME
+    echo $(curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X GET $API_BASE_URL/releases/tags/$tagName)
+}
+
+get_release_assets()
+{
+    releaseId=$1
+    echo $(curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X GET $API_BASE_URL/releases/$releaseId/assets)
+}
+
+upload_release_asset()
+{
+    uploadUrl=$1
+    echo $(curl --max-time 900 -u $GIT_USERNAME:$GIT_TOKEN -X POST $uploadUrl --header "Content-Type: application/octet-stream" --upload-file $APPIMAGE)
+}
+
+delete_release_asset()
+{
+    assetId=$1
+    curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X DELETE $API_BASE_URL/releases/assets/$assetId
+}
+
+# Try to get an already existing release
+json=$(get_release)
+
+releaseId=$(echo $json | jq -r '.id')
+uploadUrl=$(echo $json | jq -r '.upload_url')
+
+if [[ "$uploadUrl" == "null" ]]; then
+    # Try to create a release
+    json=$(create_release)
+
+    releaseId=$(echo $json | jq -r '.id')
+    uploadUrl=$(echo $json | jq -r '.upload_url')
+
+    if [[ "$uploadUrl" == "null" ]]; then
+        echo "create_release failed: $json"
+        exit 2
+    fi
+fi
+
+# Prepare upload url
+uploadUrl=$(echo "${uploadUrl/'{?name,label}'/?name=$BASENAME}")
+
+# Try to delete existing AppImage assets for this PR
+assets=$(get_release_assets $releaseId)
+
+for data in $(echo $assets | jq -r '.[] | @uri'); do
+    json=$(urldecode "$data")
+
+    assetId=$(echo $json | jq -r '.id')
+    name=$(echo $json | jq -r '.name')
+
+    if [[ "$name" == *.AppImage ]]; then
+        echo "Deleting old asset: $name"
+        $(delete_release_asset $assetId)
+    fi
+done
+
+# Upload release asset
+echo "Uploading new asset: $BASENAME"
+
+json=$(upload_release_asset "$uploadUrl")
+browserDownloadUrl=$(echo $json | jq -r '.browser_download_url')
+
+if [[ "$browserDownloadUrl" == "null" ]]; then
+    echo "upload_release_asset failed: $json"
+    exit 3
+fi
+
+if [[ "$TAG_NAME" != *.master ]]; then
+    # Create comment in desktop PR
+    curl 2>/dev/null -u $GIT_USERNAME:$GIT_TOKEN -X POST $DESKTOP_API_BASE_URL/issues/$PR/comments -d "{ \"body\" : \"AppImage file: [$BASENAME]($browserDownloadUrl) <br/><br/>To test this change/fix you can simply download above AppImage file and test it. <br/><br/>Please make sure to quit your existing Nextcloud app and backup your data. \" }"
 fi
 
-# Don't let the Drone build fail
-exit 0
+echo
+echo "AppImage link: $browserDownloadUrl"