#!/usr/bin/env bash set -euo pipefail # Usage: scripts/release_gitea.sh [--draft] [--prerelease] # Env: liest automatisch $ROOT_DIR/.env (GITEA_TOKEN, GITEA_BASE, OWNER, REPO) # Falls nicht gesetzt, werden GITEA_BASE/OWNER/REPO aus der Git-Remote-URL abgeleitet. if [[ $# -lt 1 ]]; then echo "Usage: $0 [--draft] [--prerelease]" >&2 exit 1 fi VERSION="$1" shift || true DRAFT=false PRERELEASE=false for arg in "$@"; do case "$arg" in --draft) DRAFT=true ;; --prerelease) PRERELEASE=true ;; esac done ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)" # Load .env if present if [[ -f "$ROOT_DIR/.env" ]]; then set -a # shellcheck disable=SC1090 . "$ROOT_DIR/.env" set +a fi # Map alternative token variable name if [[ -z "${GITEA_TOKEN:-}" && -n "${GITEA_API_TOKEN:-}" ]]; then GITEA_TOKEN="$GITEA_API_TOKEN" fi # Map API URL to base if provided if [[ -z "${GITEA_BASE:-}" && -n "${GITEA_API_URL:-}" ]]; then # strip trailing /api/... from URL GITEA_BASE="${GITEA_API_URL%%/api/*}" fi # Map owner/repo alternative names if [[ -z "${OWNER:-}" && -n "${GITEA_OWNER:-}" ]]; then OWNER="$GITEA_OWNER" fi if [[ -z "${REPO:-}" && -n "${GITEA_REPO:-}" ]]; then REPO="$GITEA_REPO" fi # Derive defaults from git remote if not provided if [[ -z "${GITEA_BASE:-}" || -z "${OWNER:-}" || -z "${REPO:-}" ]]; then ORIGIN_URL=$(git -C "$ROOT_DIR" remote get-url origin 2>/dev/null || true) if [[ "$ORIGIN_URL" =~ ^https?://([^/]+)/([^/]+)/([^/]+?)(\.git)?$ ]]; then : "${GITEA_BASE:="https://${BASH_REMATCH[1]}"}" : "${OWNER:=${BASH_REMATCH[2]}}" : "${REPO:=${BASH_REMATCH[3]}}" fi fi : "${GITEA_TOKEN:?Set GITEA_TOKEN (in .env oder Umgebung)}" : "${GITEA_BASE:?Set GITEA_BASE (z. B. https://gitea.elpatron.me)}" : "${OWNER:?Set OWNER (z. B. elpatron)}" : "${REPO:?Set REPO (z. B. octo-funnel)}" DIST_DIR="$ROOT_DIR/octoprint_tailscale_funnel/dist" TAG="v${VERSION}" echo "Creating git tag ${TAG} and pushing..." git tag -f "${TAG}" git push -f origin "${TAG}" echo "Creating Gitea release ${TAG}..." BODY=$(cat <&2 exit 1 fi echo "Release created: ID=$ID" echo "Using: GITEA_BASE=$GITEA_BASE OWNER=$OWNER REPO=$REPO" function upload_asset() { local file="$1" local name name=$(basename "$file") echo "Uploading asset: $name" curl -sS -X POST "${GITEA_BASE}/api/v1/repos/${OWNER}/${REPO}/releases/${ID}/assets?name=${name}" \ -H "Authorization: token ${GITEA_TOKEN}" \ -H 'Content-Type: application/octet-stream' \ --data-binary @"$file" > /dev/null } upload_asset "$DIST_DIR/octoprint_tailscale_funnel-${VERSION}-py3-none-any.whl" upload_asset "$DIST_DIR/octoprint_tailscale_funnel-${VERSION}.tar.gz" upload_asset "$DIST_DIR/octoprint_tailscale_funnel-${VERSION}.zip" echo "Release ${TAG} created and assets uploaded." #!/usr/bin/env bash set -euo pipefail # Load .env if present if [ -f "$(dirname "$0")/../.env" ]; then set -a # shellcheck disable=SC1091 . "$(dirname "$0")/../.env" set +a 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="" NAME="" ASSET_PATH="" BODY_FILE="" usage() { echo "Usage: $0 -t -a [-n ] [-b ]" >&2 } while getopts ":t:a:n:b:" opt; do case $opt in t) TAG="$OPTARG" ;; a) ASSET_PATH="$OPTARG" ;; n) NAME="$OPTARG" ;; b) BODY_FILE="$OPTARG" ;; *) usage; exit 2 ;; esac done if [ -z "$TAG" ] || [ -z "$ASSET_PATH" ]; then usage; exit 2 fi if [ -z "$NAME" ]; then NAME="$TAG"; fi if [ ! -f "$ASSET_PATH" ]; then echo "Asset not found: $ASSET_PATH" >&2; exit 1 fi 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 # 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=$(echo "$get_resp" | jq -r '.id // empty') if [ -z "$rel_id" ]; then # Build minimal JSON payload (use existing tag) create_payload=$(jq -n --arg tag "$TAG" --arg name "$NAME" --arg body "$BODY" '{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:false}') 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 from create response rel_id=$(echo "$create_resp" | jq -r '.id // empty') 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=$(echo "$list_resp" | jq -r --arg tag "$TAG" '[.[] | select(.tag_name==$tag)][0].id // empty') fi if [ -z "$rel_id" ]; then echo "Failed to get create/fetch release id" >&2 echo "$create_resp" | head -c 400 >&2 exit 1 fi # Check if asset exists (skip upload if present) assets_json=$(curl -sS -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases/${rel_id}/assets") asset_exists=$(echo "$assets_json" | jq -r --arg name "$ASSET_NAME" 'any(.[]; .name==$name)') if [ "$asset_exists" = "true" ]; then echo "Asset already exists, skipping upload: ${ASSET_NAME}" else echo "Uploading asset: ${ASSET_NAME}" 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=$(echo "$upload_resp" | jq -r '.browser_download_url // empty') echo "Asset uploaded: ${html_url}" fi echo "Release ${TAG} ready (id=${rel_id})."