#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ADDON_XML="${ROOT_DIR}/addon/addon.xml" DEFAULT_NOTES="Automatischer Release-Upload aus ViewIT Build." TAG="" ASSET_PATH="" TITLE="" NOTES="${DEFAULT_NOTES}" DRY_RUN="0" while [[ $# -gt 0 ]]; do case "$1" in --tag) TAG="${2:-}" shift 2 ;; --asset) ASSET_PATH="${2:-}" shift 2 ;; --title) TITLE="${2:-}" shift 2 ;; --notes) NOTES="${2:-}" shift 2 ;; --dry-run) DRY_RUN="1" shift ;; *) echo "Unbekanntes Argument: $1" >&2 exit 1 ;; esac done if [[ ! -f "${ADDON_XML}" ]]; then echo "Missing: ${ADDON_XML}" >&2 exit 1 fi read -r ADDON_ID ADDON_VERSION < <(python3 - "${ADDON_XML}" <<'PY' import sys import xml.etree.ElementTree as ET root = ET.parse(sys.argv[1]).getroot() print(root.attrib.get("id", "plugin.video.viewit"), root.attrib.get("version", "0.0.0")) PY ) if [[ -z "${TAG}" ]]; then TAG="v${ADDON_VERSION}" fi if [[ -z "${ASSET_PATH}" ]]; then ASSET_PATH="${ROOT_DIR}/dist/${ADDON_ID}-${ADDON_VERSION}.zip" fi if [[ ! -f "${ASSET_PATH}" ]]; then echo "Asset nicht gefunden, baue ZIP: ${ASSET_PATH}" "${ROOT_DIR}/scripts/build_kodi_zip.sh" >/dev/null fi if [[ ! -f "${ASSET_PATH}" ]]; then echo "Asset fehlt nach Build: ${ASSET_PATH}" >&2 exit 1 fi if [[ -z "${TITLE}" ]]; then TITLE="ViewIT ${TAG}" fi REMOTE_URL="$(git -C "${ROOT_DIR}" remote get-url origin)" read -r BASE_URL OWNER REPO < <(python3 - "${REMOTE_URL}" <<'PY' import re import sys u = sys.argv[1].strip() m = re.match(r"^https?://([^/]+)/([^/]+)/([^/.]+)(?:\.git)?/?$", u) if not m: raise SystemExit("Origin-URL muss https://host/owner/repo(.git) sein.") host, owner, repo = m.group(1), m.group(2), m.group(3) print(f"https://{host}", owner, repo) PY ) API_BASE="${BASE_URL}/api/v1/repos/${OWNER}/${REPO}" ASSET_NAME="$(basename "${ASSET_PATH}")" if [[ "${DRY_RUN}" == "1" ]]; then echo "[DRY-RUN] API: ${API_BASE}" echo "[DRY-RUN] Tag: ${TAG}" echo "[DRY-RUN] Asset: ${ASSET_PATH}" exit 0 fi if [[ -z "${GITEA_TOKEN:-}" ]]; then echo "Bitte GITEA_TOKEN setzen." >&2 exit 1 fi tmp_json="$(mktemp)" tmp_http="$(mktemp)" trap 'rm -f "${tmp_json}" "${tmp_http}"' EXIT urlenc() { python3 - "$1" <<'PY' import sys from urllib.parse import quote print(quote(sys.argv[1], safe="")) PY } tag_enc="$(urlenc "${TAG}")" auth_header="Authorization: token ${GITEA_TOKEN}" http_code="$(curl -sS -H "${auth_header}" -o "${tmp_json}" -w "%{http_code}" "${API_BASE}/releases/tags/${tag_enc}")" if [[ "${http_code}" == "200" ]]; then RELEASE_ID="$(python3 - "${tmp_json}" <<'PY' import json,sys print(json.load(open(sys.argv[1], encoding="utf-8"))["id"]) PY )" elif [[ "${http_code}" == "404" ]]; then # Branch und prerelease aus Version ableiten read -r TARGET_BRANCH IS_PRERELEASE < <(python3 - "${ADDON_VERSION}" <<'PY' import sys v = sys.argv[1] if "-dev" in v: print("dev", "true") elif "-nightly" in v: print("nightly", "true") else: print("main", "false") PY ) payload="$(python3 - "${TAG}" "${TITLE}" "${NOTES}" "${TARGET_BRANCH}" "${IS_PRERELEASE}" <<'PY' import json,sys print(json.dumps({ "tag_name": sys.argv[1], "name": sys.argv[2], "body": sys.argv[3], "target_commitish": sys.argv[4], "draft": False, "prerelease": sys.argv[5] == "true" })) PY )" http_code_create="$(curl -sS -X POST -H "${auth_header}" -H "Content-Type: application/json" -d "${payload}" -o "${tmp_json}" -w "%{http_code}" "${API_BASE}/releases")" if [[ "${http_code_create}" != "201" ]]; then echo "Release konnte nicht erstellt werden (HTTP ${http_code_create})." >&2 cat "${tmp_json}" >&2 exit 1 fi RELEASE_ID="$(python3 - "${tmp_json}" <<'PY' import json,sys print(json.load(open(sys.argv[1], encoding="utf-8"))["id"]) PY )" else echo "Release-Abfrage fehlgeschlagen (HTTP ${http_code})." >&2 cat "${tmp_json}" >&2 exit 1 fi assets_code="$(curl -sS -H "${auth_header}" -o "${tmp_json}" -w "%{http_code}" "${API_BASE}/releases/${RELEASE_ID}/assets")" if [[ "${assets_code}" == "200" ]]; then EXISTING_ASSET_ID="$(python3 - "${tmp_json}" "${ASSET_NAME}" <<'PY' import json,sys assets=json.load(open(sys.argv[1], encoding="utf-8")) name=sys.argv[2] for a in assets: if a.get("name")==name: print(a.get("id")) break PY )" if [[ -n "${EXISTING_ASSET_ID}" ]]; then del_code="$(curl -sS -X DELETE -H "${auth_header}" -o "${tmp_http}" -w "%{http_code}" "${API_BASE}/releases/${RELEASE_ID}/assets/${EXISTING_ASSET_ID}")" if [[ "${del_code}" != "204" ]]; then echo "Altes Asset konnte nicht geloescht werden (HTTP ${del_code})." >&2 cat "${tmp_http}" >&2 exit 1 fi fi fi asset_name_enc="$(urlenc "${ASSET_NAME}")" upload_code="$(curl -sS -X POST -H "${auth_header}" -F "attachment=@${ASSET_PATH}" -o "${tmp_json}" -w "%{http_code}" "${API_BASE}/releases/${RELEASE_ID}/assets?name=${asset_name_enc}")" if [[ "${upload_code}" != "201" ]]; then echo "Asset-Upload fehlgeschlagen (HTTP ${upload_code})." >&2 cat "${tmp_json}" >&2 exit 1 fi echo "Release-Asset hochgeladen:" echo " Repo: ${OWNER}/${REPO}" echo " Tag: ${TAG}" echo " Asset: ${ASSET_NAME}" echo " URL: ${BASE_URL}/${OWNER}/${REPO}/releases/tag/${TAG}"