From 66f5749fc17862ab7d555b33efb52bf2c9feb6a9 Mon Sep 17 00:00:00 2001 From: mrleo1nid <43583385+mrleo1nid@users.noreply.github.com> Date: Wed, 21 Oct 2026 00:23:28 +0300 Subject: [PATCH] fix(deploy): take the Gitea address for Android updates from git remote The server kept the git.example.lan placeholder from .env.example, so the /android page and in-app updates had no release. install.sh and update.sh now fill GITEA_URL and GITEA_REPO from the clone's origin (https, ssh and scp forms, credentials stripped) when they are empty or still the placeholder, and the API treats the placeholder as not configured. Co-Authored-By: Claude Opus 5.5 --- deploy/.env.example | 6 ++-- deploy/install.sh | 33 ++++++++++++++++++++ deploy/update.sh | 33 ++++++++++++++++++++ docs/deployment.md | 2 +- docs/install-guide.md | 6 ++-- services/api/internal/appupdate/appupdate.go | 4 ++- 6 files changed, 78 insertions(+), 6 deletions(-) diff --git a/deploy/.env.example b/deploy/.env.example index 263fdba..989ad14 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -45,6 +45,8 @@ SUPPORTED_LOCALES=ru,en MIN_ANDROID_VERSION_CODE=0 # --- Самообновление Android (M5) --- -GITEA_URL=https://git.example.lan -GITEA_REPO=owner/pipu-music +# Пусто — install.sh и update.sh возьмут из origin клона (например, https://gitea.example.com и owner/pipu-music). +# Если сервер не видит Gitea по внешнему адресу, укажите внутренний: GITEA_URL=http://10.0.0.5:3000 +GITEA_URL= +GITEA_REPO= GITEA_TOKEN= diff --git a/deploy/install.sh b/deploy/install.sh index 4aa9f4f..8a7f4de 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -76,6 +76,39 @@ for key in JWT_PRIVATE_KEY STREAM_SIGNING_KEY; do fi done +# Самообновление Android: адрес Gitea и репозиторий — из origin этого клона, если в .env пусто +# или осталась заглушка из .env.example (https://host/owner/repo, git@host:owner/repo, ssh://git@host:port/owner/repo). +fill_gitea() { + local url repo origin host path + url="$(sed -n 's/^GITEA_URL=//p' .env)" + repo="$(sed -n 's/^GITEA_REPO=//p' .env)" + case "$url" in "" | *example.*) url="" ;; esac + case "$repo" in "" | owner/*) repo="" ;; esac + [ -n "$url" ] && [ -n "$repo" ] && return 0 + origin="$(git -c safe.directory='*' remote get-url origin 2>/dev/null || true)" + [ -n "$origin" ] || return 0 + case "$origin" in + http://* | https://*) + host="$(printf '%s' "$origin" | sed -E 's#^(https?://)([^@/]*@)?([^/]+)/.*#\1\3#')" + path="$(printf '%s' "$origin" | sed -E 's#^https?://[^/]+/##')" ;; + ssh://*) + host="https://$(printf '%s' "$origin" | sed -E 's#^ssh://([^@/]*@)?([^:/]+).*#\2#')" + path="$(printf '%s' "$origin" | sed -E 's#^ssh://[^/]+/##')" ;; + *:*) + host="https://$(printf '%s' "$origin" | sed -E 's#^([^@]*@)?([^:]+):.*#\2#')" + path="${origin#*:}" ;; + *) return 0 ;; + esac + path="${path%.git}" + [ -n "$url" ] || url="$host" + [ -n "$repo" ] || repo="$path" + for kv in "GITEA_URL=$url" "GITEA_REPO=$repo"; do + if grep -q "^${kv%%=*}=" .env; then sed -i "s|^${kv%%=*}=.*|$kv|" .env; else echo "$kv" >> .env; fi + done + echo "→ самообновление Android: $url, $repo (из git remote; поменять — в .env)" +} +fill_gitea + # LIBRARY_HOST, переданный при повторном запуске, попадает и в уже существующий .env if [ -n "$LIBRARY_HOST" ]; then if grep -q '^LIBRARY_HOST=' .env; then diff --git a/deploy/update.sh b/deploy/update.sh index d6e9ac2..b6319d2 100755 --- a/deploy/update.sh +++ b/deploy/update.sh @@ -26,6 +26,39 @@ for key in JWT_PRIVATE_KEY STREAM_SIGNING_KEY; do fi done +# Самообновление Android: адрес Gitea и репозиторий — из origin этого клона, если в .env пусто +# или осталась заглушка из .env.example (https://host/owner/repo, git@host:owner/repo, ssh://git@host:port/owner/repo). +fill_gitea() { + local url repo origin host path + url="$(sed -n 's/^GITEA_URL=//p' .env)" + repo="$(sed -n 's/^GITEA_REPO=//p' .env)" + case "$url" in "" | *example.*) url="" ;; esac + case "$repo" in "" | owner/*) repo="" ;; esac + [ -n "$url" ] && [ -n "$repo" ] && return 0 + origin="$(git -c safe.directory='*' remote get-url origin 2>/dev/null || true)" + [ -n "$origin" ] || return 0 + case "$origin" in + http://* | https://*) + host="$(printf '%s' "$origin" | sed -E 's#^(https?://)([^@/]*@)?([^/]+)/.*#\1\3#')" + path="$(printf '%s' "$origin" | sed -E 's#^https?://[^/]+/##')" ;; + ssh://*) + host="https://$(printf '%s' "$origin" | sed -E 's#^ssh://([^@/]*@)?([^:/]+).*#\2#')" + path="$(printf '%s' "$origin" | sed -E 's#^ssh://[^/]+/##')" ;; + *:*) + host="https://$(printf '%s' "$origin" | sed -E 's#^([^@]*@)?([^:]+):.*#\2#')" + path="${origin#*:}" ;; + *) return 0 ;; + esac + path="${path%.git}" + [ -n "$url" ] || url="$host" + [ -n "$repo" ] || repo="$path" + for kv in "GITEA_URL=$url" "GITEA_REPO=$repo"; do + if grep -q "^${kv%%=*}=" .env; then sed -i "s|^${kv%%=*}=.*|$kv|" .env; else echo "$kv" >> .env; fi + done + echo "→ самообновление Android: $url, $repo (из git remote; поменять — в .env)" +} +fill_gitea + # Папка с музыкой пуста — почти всегда это несмонтированный диск: api отдавал бы ошибки воспроизведения. LIBRARY_HOST="$(sed -n 's/^LIBRARY_HOST=//p' .env)" if [ -n "$LIBRARY_HOST" ] && [ -z "$(ls -A "$LIBRARY_HOST" 2>/dev/null)" ] && [ "${PIPU_ALLOW_EMPTY_LIBRARY:-}" != 1 ]; then diff --git a/docs/deployment.md b/docs/deployment.md index df8dd09..fcad397 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -77,7 +77,7 @@ | `BOOTSTRAP_ADMIN_PASSWORD` | пусто → сгенерировать и вывести в лог | | | `TRANSCODE_CACHE_LIMIT_GB` | `50` | | | `TRANSCODE_CONCURRENCY` | `2` | | -| `GITEA_URL`, `GITEA_REPO`, `GITEA_TOKEN` | `https://git.home.lan`, `owner/pipu-music`, read-only токен | Для самообновления Android | +| `GITEA_URL`, `GITEA_REPO`, `GITEA_TOKEN` | пусто — из `git remote` (`install.sh`, `update.sh`); токен — для закрытого репозитория | Самообновление Android и страница `/android` | | `PIPU_FILE_UID`, `PIPU_FILE_GID` | `1000` | Владелец файлов, которые агент записывает в принимающие хранилища | | `UPLOADS_DIR` | `/uploads` | Staging очереди на добавление (лимит очереди задаётся в админке) | | `LOG_LEVEL` | `info` | | diff --git a/docs/install-guide.md b/docs/install-guide.md index 2ba1e53..5e39e2c 100644 --- a/docs/install-guide.md +++ b/docs/install-guide.md @@ -250,8 +250,10 @@ curl -s https://music.example.com/readyz приложение попросит обновиться. Дальше приложение обновляется само: с версии M5 оно проверяет новые релизы через ваш сервер -и предлагает обновиться ([mobile.md](mobile.md#самообновление)). Для этого в `.env` сервера нужно заполнить -`GITEA_URL`, `GITEA_REPO` и `GITEA_TOKEN` (токен только на чтение). +и предлагает обновиться ([mobile.md](mobile.md#самообновление)). Адрес Gitea и репозиторий (`GITEA_URL`, `GITEA_REPO`) +`install.sh` и `update.sh` берут из `git remote` клона; `GITEA_TOKEN` (только на чтение) нужен, если репозиторий +закрытый. Если сервер не видит Gitea по внешнему адресу — впишите внутренний в `GITEA_URL`. Раздать приложение — +ссылка `https://<ваш-домен>/android`. > Приложению нужен настоящий сертификат. С самоподписанным сертификатом и голым IP-адресом подключиться не получится. > Поэтому нужен домен с Let's Encrypt, как в этой инструкции. diff --git a/services/api/internal/appupdate/appupdate.go b/services/api/internal/appupdate/appupdate.go index d2faf8e..7266ebc 100644 --- a/services/api/internal/appupdate/appupdate.go +++ b/services/api/internal/appupdate/appupdate.go @@ -100,8 +100,10 @@ func NewHandler(cfg Config, log *slog.Logger) *Handler { return &Handler{cfg: cfg, client: &http.Client{Timeout: 10 * time.Minute}, log: log} } +// configured — адрес и репозиторий заданы, и это не заглушка из .env.example. func (h *Handler) configured() bool { - return h.cfg.GiteaURL != "" && h.cfg.Repo != "" + return h.cfg.GiteaURL != "" && h.cfg.Repo != "" && + !strings.Contains(h.cfg.GiteaURL, "example.") && !strings.HasPrefix(h.cfg.Repo, "owner/") } func (h *Handler) get(ctx context.Context, url string) (*http.Response, error) {