From 4d484c502355cba4dba973330876b91a6dc15773 Mon Sep 17 00:00:00 2001 From: "Markus F.J. Busche" Date: Sat, 20 Sep 2025 18:07:27 +0200 Subject: [PATCH] Bump to v0.1.6.2 --- octoprint_tailscale_funnel/setup.py | 2 +- octoprint_tailscale_funnel/update.json | 2 +- scripts/release_gitea.sh | 84 +++++++++++------- scripts/upload_asset_direct.sh | 117 +++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 32 deletions(-) create mode 100755 scripts/upload_asset_direct.sh diff --git a/octoprint_tailscale_funnel/setup.py b/octoprint_tailscale_funnel/setup.py index 85e5bb9..20f7801 100644 --- a/octoprint_tailscale_funnel/setup.py +++ b/octoprint_tailscale_funnel/setup.py @@ -14,7 +14,7 @@ plugin_package = "octoprint_tailscale_funnel" plugin_name = "OctoPrint-Tailscale-Funnel" # The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module -plugin_version = "0.1.6.1" +plugin_version = "0.1.6.2" # The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin # module diff --git a/octoprint_tailscale_funnel/update.json b/octoprint_tailscale_funnel/update.json index c1d6bee..64643f2 100644 --- a/octoprint_tailscale_funnel/update.json +++ b/octoprint_tailscale_funnel/update.json @@ -1,4 +1,4 @@ { - "version": "0.1.6.1" + "version": "0.1.6.2" } diff --git a/scripts/release_gitea.sh b/scripts/release_gitea.sh index 21c781e..fed2ce8 100644 --- a/scripts/release_gitea.sh +++ b/scripts/release_gitea.sh @@ -44,13 +44,30 @@ if [ -z "$TOKEN" ]; then echo "GITEA_API_TOKEN not set (in .env)." >&2; exit 1 fi +# Derive asset name early for later use +ASSET_NAME="$(basename "$ASSET_PATH")" + BODY="Tailscale Funnel Plugin ${TAG}\n\nAutomated release." if [ -n "$BODY_FILE" ] && [ -f "$BODY_FILE" ]; then BODY=$(cat "$BODY_FILE") fi -# Build JSON payload via python (robust quoting) -create_payload=$(REL_TAG="$TAG" REL_NAME="$NAME" REL_BODY_TXT="$BODY" python3 - <<'PY' +# Try to fetch existing release by tag first +get_resp=$(curl -sS -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases/tags/${TAG}" || true) +rel_id=$(python3 - <<'PY' +import sys, json +data=sys.stdin.read().strip() +try: + obj=json.loads(data) if data else {} + print(obj.get('id','')) +except Exception: + print('') +PY +<<<"$get_resp") + +if [ -z "$rel_id" ]; then + # Build minimal JSON payload (use existing tag) + create_payload=$(REL_TAG="$TAG" REL_NAME="$NAME" REL_BODY_TXT="$BODY" python3 - <<'PY' import json, os payload = { "tag_name": os.environ["REL_TAG"], @@ -61,37 +78,44 @@ payload = { } print(json.dumps(payload)) PY -) + ) -create_resp=$(curl -sS -X POST \ - -H 'Content-Type: application/json' \ - -H "Authorization: token ${TOKEN}" \ - -d "$create_payload" \ - "${API_URL}/repos/${OWNER}/${REPO}/releases" || true) + create_resp=$(curl -sS -X POST \ + -H 'Content-Type: application/json' \ + -H "Authorization: token ${TOKEN}" \ + -d "$create_payload" \ + "${API_URL}/repos/${OWNER}/${REPO}/releases" || true) -# Extract id; if missing, fetch by tag -rel_id=$(python3 - <<'PY' -import sys, json -data=sys.stdin.read().strip() -if not data: - print("") -else: - try: - obj=json.loads(data) - print(obj.get('id','')) - except Exception: - print("") -PY -<<<"$create_resp") - -if [ -z "$rel_id" ]; then - get_resp=$(curl -sS -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases/tags/${TAG}") + # Extract id from create response rel_id=$(python3 - <<'PY' import sys, json -obj=json.loads(sys.stdin.read()) -print(obj.get('id','')) +data=sys.stdin.read().strip() +try: + obj=json.loads(data) if data else {} + print(obj.get('id','')) +except Exception: + print('') PY -<<<"$get_resp") + <<<"$create_resp") +fi + +# Fallback: search releases list for matching tag if still empty +if [ -z "$rel_id" ]; then + list_resp=$(curl -sS -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases?limit=100") + rel_id=$(python3 - <<'PY' +import sys, json, os +data=sys.stdin.read().strip() +try: + arr=json.loads(data) if data else [] + tag=os.environ.get('TAG') + for rel in arr: + if rel.get('tag_name')==tag: + print(rel.get('id','')) + break +except Exception: + pass +PY + <<<"$list_resp") fi if [ -z "$rel_id" ]; then @@ -114,14 +138,14 @@ try: except Exception: pass PY -ASSET_NAME="$(basename "$ASSET_PATH")" <<<"$assets_json") +<<<"$assets_json") if [ -n "$asset_id" ]; then curl -sS -X DELETE -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases/${rel_id}/assets/${asset_id}" >/dev/null || true fi # Upload asset -upload_resp=$(curl -sS -H "Authorization: token ${TOKEN}" -F attachment=@"${ASSET_PATH}" "${API_URL}/repos/${OWNER}/${REPO}/releases/${rel_id}/assets?name=$(basename "$ASSET_PATH")") +upload_resp=$(curl -sS -H "Authorization: token ${TOKEN}" -F attachment=@"${ASSET_PATH}" "${API_URL}/repos/${OWNER}/${REPO}/releases/${rel_id}/assets?name=${ASSET_NAME}") html_url=$(python3 - <<'PY' import sys, json diff --git a/scripts/upload_asset_direct.sh b/scripts/upload_asset_direct.sh new file mode 100755 index 0000000..cace60f --- /dev/null +++ b/scripts/upload_asset_direct.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +set -e +set +u + +# Load .env +if [ -f "$(dirname "$0")/../.env" ]; then + # shellcheck disable=SC1091 + . "$(dirname "$0")/../.env" +fi + +API_URL=${GITEA_API_URL:-"https://gitea.elpatron.me/api/v1"} +OWNER=${GITEA_OWNER:-"elpatron"} +REPO=${GITEA_REPO:-"octo-funnel"} +TOKEN=${GITEA_API_TOKEN:-""} + +TAG=${1:-v0.1.6.1} +ASSET_PATH=${2:-"$(pwd)/octoprint_tailscale_funnel/dist/OctoPrint-Tailscale-Funnel-0.1.6.1.zip"} + +if [ -z "$TOKEN" ]; then + echo "GITEA_API_TOKEN not set" >&2 + exit 1 +fi +if [ ! -f "$ASSET_PATH" ]; then + echo "Asset not found: $ASSET_PATH" >&2 + exit 1 +fi + +ASSET_NAME=$(basename "$ASSET_PATH") + +# Get release by tag +REL_JSON=$(curl -sS -H "Authorization: token $TOKEN" "$API_URL/repos/$OWNER/$REPO/releases/tags/$TAG" || true) +REL_ID=$(python3 - <<'PY' +import sys, json +s=sys.stdin.read().strip() +try: + d=json.loads(s) if s else {} + print(d.get('id','')) +except Exception: + print('') +PY +<<<"$REL_JSON") + +# Fallback list search +if [ -z "$REL_ID" ]; then + LIST=$(curl -sS -H "Authorization: token $TOKEN" "$API_URL/repos/$OWNER/$REPO/releases?limit=100") + REL_ID=$(TAG="$TAG" python3 - <<'PY' +import os, sys, json +tag=os.environ['TAG'] +try: + arr=json.loads(sys.stdin.read()) + for r in arr: + if r.get('tag_name')==tag: + print(r.get('id','')) + break +except Exception: + print('') +PY +<<<"$LIST") +fi + +# Create release if still missing +if [ -z "$REL_ID" ]; then + PAYLOAD=$(TAG="$TAG" python3 - <<'PY' +import json, os +print(json.dumps({ + 'tag_name': os.environ['TAG'], + 'name': os.environ['TAG'], + 'body': 'Automated release' +})) +PY +) + CREATE=$(curl -sS -X POST -H 'Content-Type: application/json' -H "Authorization: token $TOKEN" -d "$PAYLOAD" "$API_URL/repos/$OWNER/$REPO/releases") + REL_ID=$(python3 - <<'PY' +import sys, json +try: + d=json.loads(sys.stdin.read()) + print(d.get('id','')) +except Exception: + print('') +PY +<<<"$CREATE") +fi + +if [ -z "$REL_ID" ]; then + echo "Failed to resolve release id for tag $TAG" >&2 + exit 1 +fi + +# Check existing assets +ASSETS=$(curl -sS -H "Authorization: token $TOKEN" "$API_URL/repos/$OWNER/$REPO/releases/$REL_ID/assets") +HAS=$(NAME="$ASSET_NAME" python3 - <<'PY' +import os, sys, json +name=os.environ['NAME'] +try: + arr=json.loads(sys.stdin.read()) + print(any(a.get('name')==name for a in arr)) +except Exception: + print(False) +PY +<<<"$ASSETS") + +if [ "$HAS" = "True" ]; then + echo "Asset already exists: $ASSET_NAME" +else + echo "Uploading asset: $ASSET_NAME" + curl -sS -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/octet-stream" \ + --data-binary @"$ASSET_PATH" \ + "$API_URL/repos/$OWNER/$REPO/releases/$REL_ID/assets?name=$ASSET_NAME" >/dev/null + echo "Upload done." +fi + +DL_URL="https://gitea.elpatron.me/$OWNER/$REPO/releases/download/$TAG/$ASSET_NAME" +CODE=$(curl -s -o /dev/null -w '%{http_code}' "$DL_URL") +echo "DOWNLOAD_URL=$DL_URL" +echo "HTTP_STATUS=$CODE" + +