From ca1c8e8c686bac77c9b3be60747d41429ad9d53e Mon Sep 17 00:00:00 2001 From: Ivan Vasilev Date: Sat, 29 Aug 2026 02:45:14 +0300 Subject: [PATCH] Add a Gitea release workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Releases only existed on GitHub, while install.sh now defaults to pulling the archive from the Gitea mirror. This builds the same archive on a v* tag and publishes it through the Gitea API, since the runner has no gh CLI: create the release, fall back to looking it up by tag when it already exists, then upload the tarball as an asset. Two details are easy to get wrong and are commented in place. The release id is the first "id" in Gitea's JSON, so the match must be non-greedy — a greedy one picks up the author or asset id instead. And the id helper needs `|| true`, because an empty grep under pipefail would abort the step on the path where the release already exists. The workflow cannot run yet: the Gitea repo is a pull mirror, which neither runs Actions nor accepts release creation. It starts working once the repo is un-mirrored, Actions are enabled and a runner with the ubuntu-latest label is registered; the header of the file lists those prerequisites. --- .gitea/workflows/release.yml | 89 ++++++++++++++++++++++++++++++++++++ README.md | 5 ++ 2 files changed, 94 insertions(+) create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..e5d5f40 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,89 @@ +# Публикация релиза в Gitea. Зеркало .github/workflows/release.yml: собирает тот +# же архив, но заливает его через API Gitea — gh CLI в раннере нет. +# +# Gitea читает workflow из .gitea/workflows; когда этот каталог есть, файлы из +# .github/workflows она не запускает, так что GitHub-версия остаётся только для +# GitHub. +# +# Что нужно на стороне сервера, иначе workflow просто не запустится: +# 1. Репозиторий НЕ должен быть pull-зеркалом — в зеркале Actions не +# запускаются, а релизы через API не создаются (сейчас +# maeneko/forgetting — зеркало GitHub, has_actions: false). +# 2. В настройках репозитория включены Actions. +# 3. Зарегистрирован act_runner с меткой ubuntu-latest (иначе поправь runs-on +# под свою метку — Gitea принимает только `runs-on: метка`). +# 4. Токен: по умолчанию берётся встроенный secrets.GITEA_TOKEN. Если ему не +# хватает прав, заведи секрет RELEASE_TOKEN с PAT (имя не может начинаться +# с GITEA_/GITHUB_ — эти префиксы зарезервированы). + +name: release + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Build frontend + working-directory: awg-ui + run: | + npm install + npm run build + + - name: Package archive + run: | + VERSION="${GITHUB_REF_NAME#v}" + mkdir "awgcontrol-${VERSION}" + cp -r awg-ctrl awg-ui cli .env "awgcontrol-${VERSION}/" + tar --exclude='node_modules' -czf "awgcontrol-${VERSION}.tar.gz" "awgcontrol-${VERSION}/" + + # Токен выбираем в bash, а не выражением ${{ a || b }}: так поведение не + # зависит от версии движка выражений в Gitea. + - name: Publish release + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} + run: | + set -euo pipefail + TOKEN="${RELEASE_TOKEN:-$GITEA_TOKEN}" + [ -n "$TOKEN" ] || { echo "нет токена: ни RELEASE_TOKEN, ни GITEA_TOKEN"; exit 1; } + + VERSION="${GITHUB_REF_NAME#v}" + ARCHIVE="awgcontrol-${VERSION}.tar.gz" + API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" + + # id релиза — первое поле в JSON Gitea, поэтому берём ПЕРВОЕ вхождение + # "id" (дальше идут id автора и ассетов; жадный sed схватил бы их). + # jq в раннере может не быть, поэтому grep. Если релиз на этот тег уже + # есть (повторный запуск), создание вернёт ошибку — берём его по тегу. + # `|| true` обязателен: без совпадения grep вернёт 1, а с pipefail + # это уронило бы шаг там, где пустой ответ — штатная ветка. + release_id() { grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -n1 | grep -oE '[0-9]+$' || true; } + + id=$(curl -sS -X POST "$API/releases" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"${GITHUB_REF_NAME}\",\"name\":\"${GITHUB_REF_NAME}\",\"prerelease\":true}" \ + | release_id) + + if [ -z "$id" ]; then + echo "релиз ${GITHUB_REF_NAME} уже существует — дополняем его" + id=$(curl -sS -H "Authorization: token $TOKEN" \ + "$API/releases/tags/${GITHUB_REF_NAME}" | release_id) + fi + [ -n "$id" ] || { echo "не удалось получить id релиза"; exit 1; } + + curl -sS --fail -X POST "$API/releases/${id}/assets?name=${ARCHIVE}" \ + -H "Authorization: token $TOKEN" \ + -F "attachment=@${ARCHIVE};type=application/gzip" > /dev/null + + echo "опубликовано: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${GITHUB_REF_NAME}" diff --git a/README.md b/README.md index 575c962..97f77f5 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,11 @@ AWG_GEN=auto bash <(curl -Ls https://git.ma7neko.ru/maeneko/forgetting/raw/branc так что подходит любой из них. Если архив не найден в основном источнике, установщик предупреждает и берёт его из запасного. +Архив собирается по тегу `v*`: на GitHub — `.github/workflows/release.yml`, в +Gitea — `.gitea/workflows/release.yml` (сборка та же, публикация через API +Gitea). Для запуска в Gitea репозиторий не должен быть pull-зеркалом, Actions +включены, а runner зарегистрирован с меткой `ubuntu-latest`. + ```bash REPO_BASE=https://git.example.org/me/vpn BRAND="My VPN" \ bash <(curl -Ls https://git.example.org/me/vpn/raw/branch/main/install.sh)