From 4f8e65b76b082616c86cfa9da71740c54eea3fff Mon Sep 17 00:00:00 2001 From: duffyduck Date: Thu, 24 Sep 2026 20:32:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(host-agent):=20release=5Fagent.sh=20?= =?UTF-8?q?=E2=80=94=20Binaries=20als=20Gitea-Assets,=20nicht=20im=20Tree?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release_agent.sh (wie die App-release.sh): setzt Version (host_agent.py AGENT_VERSION + Android versionName/Code), baut Linux-Binary + Android-APK per Docker, taggt agent-v (eigener Namespace, keine Kollision mit App-Tags v), legt Gitea-Release an und laedt Assets hoch. mac/win optional falls in dist/ vorgebaut. Agent meldet AGENT_VERSION jetzt in host_hello + info. README-Release-Sektion aktualisiert. Co-Authored-By: Claude Opus 4.8 --- host-agent/android/README.md | 32 +++++++-- host-agent/host_agent.py | 6 +- host-agent/release_agent.sh | 134 +++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 7 deletions(-) create mode 100755 host-agent/release_agent.sh diff --git a/host-agent/android/README.md b/host-agent/android/README.md index 5d8cd58..988ba41 100644 --- a/host-agent/android/README.md +++ b/host-agent/android/README.md @@ -164,11 +164,31 @@ Gradle-Cache im Image). Häufige Stolperer: Bis es `release.sh` gibt, wird die Version in `app/build.gradle` gepflegt (`versionCode` / `versionName`). Aktuell `1` / `0.2.0` (M1+M2). -## Release (geplant — Meilenstein 4) +## Release -`release.sh ` — wie die `release.sh` der Haupt-App: nimmt die -Versionsnummer als Parameter, baut das APK, taggt und lädt es als -**Gitea-Release-Asset** hoch, damit der Download einfach ist. Noch nicht gebaut. +Das APK ist **kein** Teil des Git-Trees (blaeht sonst die History dauerhaft auf) — +es wird als **Release-Asset** an einen Tag gehaengt. Das macht `release_agent.sh` +(liegt eine Ebene hoeher, in `host-agent/`): -> Status: **M1 + M2 fertig** (verbinden, `info`, `screenshot`, `ui_dump`). -> Als Nächstes Meilenstein 3 (Steuern), Release-Skript in M4. +```bash +cd host-agent +./release_agent.sh 0.2.0 +``` + +Das Skript (wie die `release.sh` der Haupt-App, Version als Parameter): + +- setzt die Version (`host_agent.py` → `AGENT_VERSION`, `app/build.gradle` → + `versionName`/`versionCode`), +- baut **Linux-Binary + Android-APK** per Docker, +- committet den Version-Bump, taggt **`agent-v`** (eigener Namespace, + kollidiert nicht mit den App-Tags `v`) und pusht, +- legt ein Gitea-Release an und laedt die Assets hoch: + `aria-host-agent-linux-x64`, `aria-host-agent-android-agent-v.apk`, + optional `-macos` / `-windows.exe` (falls in `host-agent/dist/` vorgebaut). + +Gitea-Zugang (`GITEA_URL`, `GITEA_REPO`, `GITEA_USER`) kommt aus der Umgebung oder +einer `.env`; das Kennwort wird interaktiv abgefragt. **Binaries landen unter +„Releases", nie im Tree.** + +> Status: **M1 + M2 fertig** (verbinden, `info`, `screenshot`, `ui_dump`), +> `release_agent.sh` vorhanden. Als Nächstes Meilenstein 3 (Steuern). diff --git a/host-agent/host_agent.py b/host-agent/host_agent.py index b2c0cd9..1b72fca 100644 --- a/host-agent/host_agent.py +++ b/host-agent/host_agent.py @@ -155,6 +155,9 @@ OUT_MAX_CHARS_HARD = int(os.environ.get("OUT_MAX_CHARS_HARD", "200000") or "2000 # Datei-Transfer-Limit (Base64 durchs RVS). FILE_MAX_BYTES = int(os.environ.get("FILE_MAX_BYTES", str(10 * 1024 * 1024)) or str(10 * 1024 * 1024)) +# Version (wird von release_agent.sh beim Release gesetzt). +AGENT_VERSION = "0.2.0" + HEARTBEAT_SEC = 25 CAPS = ["exec", "read", "write", "info", "screenshot"] @@ -291,6 +294,7 @@ def _do_write(params: dict) -> dict: def _do_info(params: dict) -> dict: info = { "host": HOST_NAME, "hostname": socket.gethostname(), + "agent_version": AGENT_VERSION, "os": platform.platform(), "kernel": platform.release(), "arch": platform.machine(), "python": platform.python_version(), "user": os.environ.get("USER") or os.environ.get("USERNAME") or "", @@ -414,7 +418,7 @@ class HostAgent: HOST_ID, HOST_NAME, ",".join(CAPS), CONTROL_ENABLED) await self._send({"type": "host_hello", "payload": { "hostId": HOST_ID, "name": HOST_NAME, "os": platform.platform(), - "caps": CAPS, "control": CONTROL_ENABLED, + "version": AGENT_VERSION, "caps": CAPS, "control": CONTROL_ENABLED, }, "timestamp": int(time.time() * 1000)}) async def _heartbeat(self) -> None: diff --git a/host-agent/release_agent.sh b/host-agent/release_agent.sh new file mode 100755 index 0000000..6a4d71d --- /dev/null +++ b/host-agent/release_agent.sh @@ -0,0 +1,134 @@ +#!/bin/bash +# ════════════════════════════════════════════════════════════════════ +# ARIA Host-Agent — Release Script +# Baut die auf Linux+Docker moeglichen Artefakte und haengt sie als +# Gitea-Release-Assets an einen Tag. NICHTS wandert in den Git-Tree — +# Binaries leben nur unter "Releases" (blaeht clone/History nicht auf). +# +# Verwendung: ./release_agent.sh (z.B. ./release_agent.sh 0.2.0) +# +# Artefakte: +# - Linux-x64-Binary (Docker, PyInstaller) -> immer +# - Android-APK (Docker, Gradle) -> immer +# - macOS / Windows (falls in dist/ vorgebaut) -> optional +# (mac/win koennen auf Linux nicht cross-gebaut werden -> build-native.* +# auf dem jeweiligen OS laufen lassen, Ergebnis nach host-agent/dist/ legen) +# +# Eigener Tag-Namespace agent-v (kollidiert NICHT mit den +# App-Tags v). +# +# Gitea-Zugang (GITEA_URL, GITEA_REPO, GITEA_USER) wird aus der Umgebung +# oder aus host-agent/.env bzw. der Repo-Wurzel-.env gelesen; das Kennwort +# wird interaktiv abgefragt. +# ════════════════════════════════════════════════════════════════════ + +set -e +cd "$(dirname "$0")" # host-agent/ +SCRIPT_DIR="$(pwd)" +ROOT_DIR="$(cd .. && pwd)" + +# ── Farben ─────────────────────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' + +# ── Parameter ──────────────────────────────────────────────────────── +VERSION=${1:?"Usage: ./release_agent.sh (z.B. 0.2.0)"} +TAG="agent-v$VERSION" + +# ── Gitea-Konfiguration (env > host-agent/.env > Repo-Wurzel-.env) ──── +[ -f "$SCRIPT_DIR/.env" ] && source "$SCRIPT_DIR/.env" +[ -f "$ROOT_DIR/.env" ] && source "$ROOT_DIR/.env" + +GITEA_URL="${GITEA_URL:?"GITEA_URL nicht gesetzt (in .env oder als Umgebungsvariable)"}" +GITEA_REPO="${GITEA_REPO:?"GITEA_REPO nicht gesetzt (z.B. stefan/aria-agent)"}" +GITEA_USER="${GITEA_USER:-$(echo "$GITEA_REPO" | cut -d'/' -f1)}" + +echo -e "${CYAN}╔═══════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║ ARIA Host-Agent Release — ${TAG}$(printf '%*s' $((14 - ${#TAG})) '')║${NC}" +echo -e "${CYAN}╚═══════════════════════════════════════════╝${NC}\n" + +# ── Kennwort ───────────────────────────────────────────────────────── +echo -e "${YELLOW}Gitea-Login: ${GITEA_USER}${NC}" +read -s -p "Gitea-Kennwort: " GITEA_PASS; echo "" +HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "${GITEA_USER}:${GITEA_PASS}" "$GITEA_URL/api/v1/user") +if [ "$HTTP_CODE" != "200" ]; then + echo -e "${RED}Login fehlgeschlagen (HTTP $HTTP_CODE). Kennwort korrekt?${NC}"; exit 1 +fi +echo -e " ${GREEN}✓${NC} Login erfolgreich\n" + +# ── Versionsnummern setzen ─────────────────────────────────────────── +echo -e "${GREEN}[1/5] Version auf $VERSION setzen...${NC}" +# Desktop-Agent +sed -i "s/^AGENT_VERSION = \"[^\"]*\"/AGENT_VERSION = \"$VERSION\"/" host_agent.py +echo -e " ${GREEN}✓${NC} host_agent.py → AGENT_VERSION $VERSION" +# Android: versionName + versionCode (aus Version berechnen; 3- oder 4-stellig) +IFS='.' read -ra VP <<< "$VERSION" +V1=${VP[0]:-0}; V2=${VP[1]:-0}; V3=${VP[2]:-0}; V4=${VP[3]:-0} +VERSION_CODE=$((V1 * 1000000 + V2 * 10000 + V3 * 100 + V4)); [ "$VERSION_CODE" -lt 1 ] && VERSION_CODE=1 +sed -i "s/versionName '[^']*'/versionName '$VERSION'/" android/app/build.gradle +sed -i "s/versionCode [0-9]*/versionCode $VERSION_CODE/" android/app/build.gradle +echo -e " ${GREEN}✓${NC} android/app/build.gradle → versionName $VERSION, versionCode $VERSION_CODE\n" + +# ── Bauen (Docker) ─────────────────────────────────────────────────── +echo -e "${GREEN}[2/5] Linux-Binary + Android-APK bauen (Docker)...${NC}" +./build.sh >/dev/null +LINUX_BIN="$SCRIPT_DIR/dist/aria-host-agent" +[ -f "$LINUX_BIN" ] || { echo -e "${RED}Linux-Binary fehlt: $LINUX_BIN${NC}"; exit 1; } +echo -e " ${GREEN}✓${NC} Linux-Binary ($(du -h "$LINUX_BIN" | cut -f1))" + +( cd android && ./build.sh >/dev/null ) +APK="$SCRIPT_DIR/android/dist/aria-android-agent.apk" +[ -f "$APK" ] || { echo -e "${RED}APK fehlt: $APK${NC}"; exit 1; } +echo -e " ${GREEN}✓${NC} Android-APK ($(du -h "$APK" | cut -f1))\n" + +# Asset-Liste aufbauen: "lokaler_pfad::asset-name" +ASSETS=( + "$LINUX_BIN::aria-host-agent-linux-x64" + "$APK::aria-host-agent-android-$TAG.apk" +) +# Optionale, vorgebaute native Artefakte (nur wenn vorhanden): +[ -f "$SCRIPT_DIR/dist/aria-host-agent-macos" ] && ASSETS+=("$SCRIPT_DIR/dist/aria-host-agent-macos::aria-host-agent-macos") +[ -f "$SCRIPT_DIR/dist/aria-host-agent.exe" ] && ASSETS+=("$SCRIPT_DIR/dist/aria-host-agent.exe::aria-host-agent-windows.exe") +[ -f "$SCRIPT_DIR/dist/aria-host-agent-setup.exe" ] && ASSETS+=("$SCRIPT_DIR/dist/aria-host-agent-setup.exe::aria-host-agent-setup.exe") + +# ── Git-Tag ────────────────────────────────────────────────────────── +echo -e "${GREEN}[3/5] Git-Tag $TAG...${NC}" +git add host_agent.py android/app/build.gradle +git commit -m "release(agent): bump to $VERSION" 2>/dev/null || echo -e " ${YELLOW}Keine Aenderungen zum Committen${NC}" +if git rev-parse "$TAG" &>/dev/null; then + echo -e " ${YELLOW}Tag $TAG existiert bereits — überspringe${NC}" +else + git tag "$TAG"; echo -e " ${GREEN}✓${NC} Tag $TAG erstellt" +fi +git push origin main "$TAG" +echo -e " ${GREEN}✓${NC} Tag gepusht\n" + +# ── Gitea-Release ──────────────────────────────────────────────────── +echo -e "${GREEN}[4/5] Gitea-Release anlegen...${NC}" +BODY="ARIA Host-Agent $TAG\n\nDesktop (Linux) + Android-APK. Auf das Zielgeraet kopieren, siehe README." +BODY_JSON=$(printf '%s' "$BODY" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null || printf '"%s"' "$BODY") +RESP=$(curl -s -X POST "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases" \ + -u "${GITEA_USER}:${GITEA_PASS}" -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"$TAG\",\"name\":\"Host-Agent $TAG\",\"body\":$BODY_JSON,\"draft\":false,\"prerelease\":false}") +RELEASE_ID=$(echo "$RESP" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2) +if [ -z "$RELEASE_ID" ]; then echo -e "${RED}Release fehlgeschlagen:${NC}\n$RESP"; exit 1; fi +echo -e " ${GREEN}✓${NC} Release #$RELEASE_ID erstellt\n" + +# ── Assets hochladen ───────────────────────────────────────────────── +echo -e "${GREEN}[5/5] Assets hochladen (${#ASSETS[@]})...${NC}" +for entry in "${ASSETS[@]}"; do + path="${entry%%::*}"; name="${entry##*::}" + UP=$(curl -s -X POST \ + "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases/$RELEASE_ID/assets?name=$name" \ + -u "${GITEA_USER}:${GITEA_PASS}" -F "attachment=@${path}") + if echo "$UP" | grep -q '"name"'; then + echo -e " ${GREEN}✓${NC} $name" + else + echo -e " ${RED}✗ $name fehlgeschlagen:${NC} $UP" + fi +done + +echo "" +echo -e "${GREEN}╔═══════════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ Host-Agent $TAG ist live!${NC}" +echo -e "${GREEN}║${NC} $GITEA_URL/$GITEA_REPO/releases/tag/$TAG" +echo -e "${GREEN}╚═══════════════════════════════════════════════════╝${NC}"