137 lines
3.3 KiB
Bash
137 lines
3.3 KiB
Bash
#!/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 <tag> -a <asset-zip> [-n <name>] [-b <body-file>]" >&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
|
|
|
|
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'
|
|
import json, os
|
|
payload = {
|
|
"tag_name": os.environ["REL_TAG"],
|
|
"name": os.environ["REL_NAME"],
|
|
"body": os.environ["REL_BODY_TXT"],
|
|
"draft": False,
|
|
"prerelease": False
|
|
}
|
|
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)
|
|
|
|
# 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}")
|
|
rel_id=$(python3 - <<'PY'
|
|
import sys, json
|
|
obj=json.loads(sys.stdin.read())
|
|
print(obj.get('id',''))
|
|
PY
|
|
<<<"$get_resp")
|
|
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
|
|
|
|
# Delete existing asset with same name (if any)
|
|
assets_json=$(curl -sS -H "Authorization: token ${TOKEN}" "${API_URL}/repos/${OWNER}/${REPO}/releases/${rel_id}/assets")
|
|
asset_id=$(python3 - <<'PY'
|
|
import sys, json, os
|
|
name=os.environ['ASSET_NAME']
|
|
try:
|
|
arr=json.loads(sys.stdin.read())
|
|
for a in arr:
|
|
if a.get('name')==name:
|
|
print(a.get('id',''))
|
|
break
|
|
except Exception:
|
|
pass
|
|
PY
|
|
ASSET_NAME="$(basename "$ASSET_PATH")" <<<"$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")")
|
|
|
|
html_url=$(python3 - <<'PY'
|
|
import sys, json
|
|
try:
|
|
print(json.loads(sys.stdin.read()).get('browser_download_url',''))
|
|
except Exception:
|
|
print("")
|
|
PY
|
|
<<<"$upload_resp")
|
|
|
|
echo "Release ${TAG} created (id=${rel_id}). Asset uploaded: ${html_url}"
|
|
|