Последняя активность 2 weeks ago

drholy ревизий этого фрагмента 2 weeks ago. К ревизии

1 file changed, 425 insertions

instruction.md(файл создан)

@@ -0,0 +1,425 @@
1 + # Установка зависимостей раннеров для сборки Aspia (macOS, Android) — команды
2 +
3 + Соответствует `.gitea/workflows/release.yml` на коммите `5565451d6` (ветка `domain-auth`, `Coder/aspia`
4 + на `https://git.byte-mate.ru`). Пояснения «зачем» — в `RUNNERS.md`, здесь только команды.
5 +
6 + Пометки: **[проверено]** — версия/ID/URL проверены 20.10.2026 по официальному источнику (ссылка рядом);
7 + **[не проверено]** — не удалось проверить, сверьте на месте.
8 +
9 + ---
10 +
11 + ## 0. Версия раннера
12 +
13 + Проект переименован: новые версии называются **gitea-runner 3.x–5.x** (последняя — 5.1.1 от
14 + 16.10.2026, https://gitea.com/gitea/act_runner/releases) [проверено]. У вас сейчас **act_runner
15 + v0.2.13**; его файлы по-прежнему доступны [проверено, HTTP 200]:
16 +
17 + - `https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-arm64`
18 + - `https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-windows-amd64.exe`
19 +
20 + Ниже используется **v0.2.13** — та же версия, что на работающих раннерах. Переход на 5.x —
21 + отдельная задача: в 5.0.0 есть несовместимые изменения (нужен Git ≥ 2.34.1 в PATH раннера,
22 + `${NAME}` в config.yaml раскрывается из окружения, job без `runs-on` падает); совместимость 5.x с
23 + Gitea 1.25.4 **[не проверено]**.
24 +
25 + **Важно — таймаут на стороне Gitea.** В примере config.yaml act_runner сказано: у Gitea свой
26 + таймаут задачи (**3 ч по умолчанию**) [проверено: комментарий в config.example.yaml v0.2.13].
27 + Первая сборка macOS universal без кэша может идти дольше. Если задача обрывается через 3 ч,
28 + увеличьте в `app.ini` Gitea секцию `[actions]` (параметр `ENDLESS_TASK_TIMEOUT`, имя
29 + **[не проверено]** для 1.25 — сверьте с https://docs.gitea.com/administration/config-cheat-sheet#actions-actions),
30 + либо задайте `vars.MACOS_UNIVERSAL=false` для первой сборки.
31 +
32 + ---
33 +
34 + ## 1. macOS (Apple Silicon), метка `macos-arm64:host`
35 +
36 + Все команды — в Terminal под пользователем раннера (`runner`, без прав администратора; для
37 + `sudo` нужен администратор — выполните эти строки от него).
38 +
39 + ### 1.1 Xcode и Rosetta
40 + Полный Xcode из App Store (Qt 6.10+ не собирается только с Command Line Tools — так в upstream
41 + workflow). Workflow задаёт `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer`, поэтому Xcode
42 + должен лежать именно там.
43 + ```bash
44 + # после установки Xcode из App Store:
45 + sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
46 + sudo xcodebuild -license accept
47 + sudo xcodebuild -runFirstLaunch
48 + xcode-select --install # Command Line Tools (если спросит)
49 +
50 + # Rosetta 2 — нужна для x86_64-половины universal-сборки (workflow запускает `arch -x86_64 cmake`)
51 + sudo softwareupdate --install-rosetta --agree-to-license
52 + ```
53 + Homebrew для x86_64 (`arch -x86_64 brew`, `/usr/local`) **не нужен**: компиляцию под x86_64 делает
54 + clang из Xcode (universal). Но workflow запускает **`arch -x86_64 cmake`**, а `arch` требует, чтобы в
55 + самом `cmake` была x86_64-часть. Бутылки Homebrew — только arm64, поэтому CMake ставится не из
56 + Homebrew, а официальный **universal** CMake.app (1.3a), как в upstream workflow
57 + (`/Applications/CMake.app/Contents/bin`). Остальные инструменты (ninja и т. д.) запускаются как
58 + дочерние процессы и работают нативно в arm64 **[не проверено]** на реальной сборке.
59 +
60 + ### 1.2 Homebrew
61 + Официальная команда установки (https://brew.sh) [проверено]:
62 + ```bash
63 + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
64 + echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
65 + eval "$(/opt/homebrew/bin/brew shellenv)"
66 + ```
67 +
68 + ### 1.3 Инструменты
69 + Шаг «Check the tools» в workflow проверяет: `cmake ninja pkg-config autoconf automake libtool nasm
70 + python3 gzip lipo` (+ `xcodebuild`, при universal — `arch -x86_64`). Формулы Homebrew
71 + [проверено: https://formulae.brew.sh/api/formula/<имя>.json → 200]:
72 + ```bash
73 + brew install ninja pkgconf autoconf autoconf-archive automake libtool nasm python@3.13 git gnu-tar xz node
74 + ```
75 +
76 + ### 1.3a CMake 4.4.4 universal (официальный)
77 + Та же версия, что закреплена для Linux-job (`cmake==4.4.4`); файл
78 + `cmake-4.4.4-macos-universal.dmg` [проверено: https://github.com/Kitware/CMake/releases/tag/v4.4.4].
79 + ```bash
80 + cd /tmp
81 + curl -fLO https://github.com/Kitware/CMake/releases/download/v4.4.4/cmake-4.4.4-macos-universal.dmg
82 + hdiutil attach cmake-4.4.4-macos-universal.dmg -mountpoint /Volumes/cmake-4.4.4 -nobrowse
83 + sudo ditto /Volumes/cmake-4.4.4/CMake.app /Applications/CMake.app
84 + hdiutil detach /Volumes/cmake-4.4.4
85 + lipo -archs /Applications/CMake.app/Contents/bin/cmake # ожидается: x86_64 arm64
86 + ```
87 + (Есть и cask `brew install --cask cmake-app` [проверено: formulae.brew.sh], но его версия не
88 + закреплена.) Если `cmake` ставили через brew — `brew uninstall cmake`, чтобы в PATH был только
89 + universal. `/Applications/CMake.app/Contents/bin` должен стоять в PATH **первым** (plist в 1.6).
90 + - `pkgconf` даёт команду `pkg-config` (формула `pkg-config` в Homebrew — псевдоним pkgconf).
91 + - `gzip`, `tar`, `lipo`, `openssl`, `security`, `ditto`, `PlistBuddy`, `productbuild` — системные / из Xcode.
92 + - `node` — для JavaScript-actions (checkout, cache, upload-artifact) в host-режиме.
93 + - `autoconf-archive`, `xz`, `gnu-tar`, `git` — не проверяются workflow, но нужны портам vcpkg / удобны;
94 + точный список, нужный портам vcpkg на macOS, **[не проверено]** — если порт попросит ещё что-то
95 + (например `bison`, `flex`, `gperf`, `meson`), доставьте через `brew install`.
96 +
97 + ### 1.4 act_runner v0.2.13 (darwin-arm64)
98 + ```bash
99 + mkdir -p ~/act_runner && cd ~/act_runner
100 + curl -fL -o act_runner https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-darwin-arm64
101 + chmod +x act_runner
102 + xattr -d com.apple.quarantine act_runner 2>/dev/null || true
103 + ./act_runner --version
104 + ./act_runner generate-config > config.yaml
105 + ```
106 + Правка `config.yaml` (ключи из config.example.yaml v0.2.13 [проверено]):
107 + ```bash
108 + # capacity: 1 (по умолчанию уже 1), timeout: 12h (workflow ставит timeout-minutes: 720), метка host
109 + sed -i '' 's/^ timeout: 3h/ timeout: 12h/' config.yaml
110 + python3 - <<'PY'
111 + import re
112 + p='config.yaml'; s=open(p).read()
113 + s=re.sub(r'(?ms)^ labels:\n( - .*\n)+', ' labels:\n - "macos-arm64:host"\n', s)
114 + open(p,'w').write(s)
115 + PY
116 + grep -nE '^ (capacity|timeout|labels)' -A1 config.yaml
117 + ```
118 +
119 + ### 1.5 Регистрация
120 + Токен: `Coder/aspia` → Settings → Actions → Runners → «Create new runner».
121 + ```bash
122 + cd ~/act_runner
123 + ./act_runner register --no-interactive \
124 + --instance https://git.byte-mate.ru \
125 + --token <RUNNER_REGISTRATION_TOKEN> \
126 + --name mac-arm64-01 \
127 + --labels macos-arm64:host \
128 + --config config.yaml
129 + ```
130 +
131 + ### 1.6 Сервис launchd (LaunchAgent пользователя runner)
132 + Включите автологин пользователя `runner` (System Settings → Users & Groups) — LaunchAgent и связки
133 + ключей работают в его сессии. Отключите сон: `sudo pmset -a sleep 0 disksleep 0`.
134 + ```bash
135 + mkdir -p ~/Library/LaunchAgents
136 + cat > ~/Library/LaunchAgents/ru.byte-mate.act_runner.plist <<PLIST
137 + <?xml version="1.0" encoding="UTF-8"?>
138 + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
139 + <plist version="1.0">
140 + <dict>
141 + <key>Label</key><string>ru.byte-mate.act_runner</string>
142 + <key>ProgramArguments</key>
143 + <array>
144 + <string>$HOME/act_runner/act_runner</string>
145 + <string>daemon</string>
146 + <string>--config</string>
147 + <string>$HOME/act_runner/config.yaml</string>
148 + </array>
149 + <key>WorkingDirectory</key><string>$HOME/act_runner</string>
150 + <key>EnvironmentVariables</key>
151 + <dict>
152 + <key>PATH</key><string>/Applications/CMake.app/Contents/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
153 + <key>LANG</key><string>en_US.UTF-8</string>
154 + <key>HOME</key><string>$HOME</string>
155 + </dict>
156 + <key>RunAtLoad</key><true/>
157 + <key>KeepAlive</key><true/>
158 + <key>StandardOutPath</key><string>$HOME/act_runner/runner.log</string>
159 + <key>StandardErrorPath</key><string>$HOME/act_runner/runner.log</string>
160 + </dict>
161 + </plist>
162 + PLIST
163 + plutil -lint ~/Library/LaunchAgents/ru.byte-mate.act_runner.plist
164 + launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ru.byte-mate.act_runner.plist
165 + launchctl kickstart -k gui/$(id -u)/ru.byte-mate.act_runner
166 + launchctl print gui/$(id -u)/ru.byte-mate.act_runner | grep -E 'state|pid'
167 + tail -f ~/act_runner/runner.log # Ctrl+C для выхода
168 + ```
169 + Перезапуск после правки config.yaml: `launchctl kickstart -k gui/$(id -u)/ru.byte-mate.act_runner`.
170 + Удаление: `launchctl bootout gui/$(id -u)/ru.byte-mate.act_runner`.
171 +
172 + ### 1.7 Проверка
173 + ```bash
174 + xcodebuild -version
175 + xcode-select -p # /Applications/Xcode.app/Contents/Developer
176 + arch -x86_64 /usr/bin/true && echo "rosetta ok"
177 + for t in cmake ninja pkg-config autoconf automake libtool nasm python3 gzip lipo git node; do
178 + printf '%-11s ' "$t"; command -v "$t" || echo "НЕТ"; done
179 + export PATH="/Applications/CMake.app/Contents/bin:$PATH" # как в plist
180 + command -v cmake # /Applications/CMake.app/Contents/bin/cmake
181 + cmake --version | head -1 # cmake version 4.4.4
182 + lipo -archs "$(command -v cmake)" # x86_64 arm64
183 + arch -x86_64 cmake --version | head -1 # должна запуститься под Rosetta
184 + df -h ~ # нужно ≥ 150 ГБ свободно
185 + ```
186 + В Gitea: Settings → Actions → Runners — `mac-arm64-01`, статус Idle, метка `macos-arm64`.
187 +
188 + ---
189 +
190 + ## 2. Android на существующем Windows-раннере, метка `windows-android`
191 +
192 + PowerShell **от администратора**. Пути — ровно те, что workflow ждёт по умолчанию (иначе задайте
193 + переменные, см. 2.6).
194 +
195 + | Что | Путь по умолчанию в workflow | Переменная |
196 + |---|---|---|
197 + | Qt for Android | `C:/Qt/6.11.1/android_arm64_v8a` | `ANDROID_QT_PATH` |
198 + | Host Qt | `C:/Qt/6.11.1/mingw_64` | `ANDROID_QT_HOST_PATH` |
199 + | Android SDK | `C:/Android/sdk` | `ANDROID_SDK_ROOT` |
200 + | NDK | `C:/Android/sdk/ndk/27.2.12479018` | `ANDROID_NDK_ROOT` |
201 + | JDK | `C:/Program Files/Eclipse Adoptium/jdk-21.0.11.10-hotspot` | `ANDROID_JAVA_HOME` |
202 +
203 + Требования Qt 6.11 для Android: **NDK r27c (27.2.12479018), JDK 21**
204 + [проверено: https://doc.qt.io/qt-6.11/android.html]. Gradle (9.3.1, AGP 9.0.0 по той же странице)
205 + скачивается сам через Gradle wrapper — нужен доступ в интернет (`services.gradle.org`,
206 + `dl.google.com`, `repo.maven.apache.org`).
207 +
208 + ### 2.1 JDK 21 (Eclipse Temurin)
209 + winget-ID `EclipseAdoptium.Temurin.21.JDK` [проверено: microsoft/winget-pkgs]. Альтернатива —
210 + `Microsoft.OpenJDK.21` [проверено], но тогда путь другой → задайте `ANDROID_JAVA_HOME`.
211 + ```powershell
212 + winget install --id EclipseAdoptium.Temurin.21.JDK -e --accept-package-agreements --accept-source-agreements
213 + Get-ChildItem 'C:\Program Files\Eclipse Adoptium' | Select-Object Name
214 + ```
215 + Точная папка зависит от версии, которую поставит winget (например `jdk-21.0.9.10-hotspot`); если
216 + она не `jdk-21.0.11.10-hotspot` — задайте переменную `ANDROID_JAVA_HOME` (2.6) на фактический путь
217 + (прямые слэши).
218 + ```powershell
219 + $jdk = (Get-ChildItem 'C:\Program Files\Eclipse Adoptium' -Directory | Where-Object Name -like 'jdk-21*' | Select-Object -First 1).FullName
220 + setx /M JAVA_HOME "$jdk"
221 + & "$jdk\bin\java.exe" -version
222 + ```
223 +
224 + ### 2.2 Android SDK command-line tools
225 + Файл `commandlinetools-win-15859902_latest.zip`, SHA-256
226 + `90ae805d20434428bffcb699c290860f19bb5f66a67e6b330067e3de801fb04a`
227 + [проверено: https://developer.android.com/studio#command-line-tools-only].
228 + ```powershell
229 + $sdk = 'C:\Android\sdk'
230 + New-Item -ItemType Directory -Force -Path "$sdk\cmdline-tools" | Out-Null
231 + $zip = "$env:TEMP\cmdline-tools.zip"
232 + Invoke-WebRequest -Uri 'https://dl.google.com/android/repository/commandlinetools-win-15859902_latest.zip' -OutFile $zip
233 + if ((Get-FileHash $zip -Algorithm SHA256).Hash -ne '90AE805D20434428BFFCB699C290860F19BB5F66A67E6B330067E3DE801FB04A') { throw 'SHA-256 mismatch' }
234 + Expand-Archive $zip -DestinationPath "$sdk\cmdline-tools" -Force
235 + Rename-Item "$sdk\cmdline-tools\cmdline-tools" 'latest' # структура, которую ждёт sdkmanager
236 + setx /M ANDROID_SDK_ROOT $sdk
237 + setx /M ANDROID_HOME $sdk
238 + ```
239 +
240 + ### 2.3 Пакеты SDK
241 + NDK `27.2.12479018` — как в workflow/upstream и в требованиях Qt 6.11 [проверено]. Уровень API и
242 + build-tools: Qt берёт самые новые установленные; `platforms;android-35` / `build-tools;35.0.0`
243 + взяты как разумный минимум **[не проверено]** для Qt 6.11 — если Gradle потребует другие, он
244 + назовёт их в логе, доставьте той же командой.
245 + ```powershell
246 + $env:JAVA_HOME = $jdk
247 + $sm = 'C:\Android\sdk\cmdline-tools\latest\bin\sdkmanager.bat'
248 + & $sm --sdk_root=C:\Android\sdk --list | Select-String -Pattern 'ndk;27|platforms;android-3[5-9]|build-tools;3[5-9]' | Select-Object -First 15
249 + 'y' * 20 | & $sm --sdk_root=C:\Android\sdk --licenses
250 + & $sm --sdk_root=C:\Android\sdk "platform-tools" "platforms;android-35" "build-tools;35.0.0" "ndk;27.2.12479018"
251 + Test-Path 'C:\Android\sdk\ndk\27.2.12479018\source.properties'
252 + ```
253 +
254 + ### 2.4 Qt 6.11.1 (Android arm64-v8a + host MinGW)
255 + Нужны два компонента [проверено по `Updates.xml` в https://download.qt.io/online/qtsdkrepository/]:
256 + - `qt.qt6.6111.android_arm64_v8a` (репозиторий `all_os/android/qt6_6111/qt6_6111_arm64_v8a`)
257 + - `qt.qt6.6111.win64_mingw` (репозиторий `windows_x86/desktop/qt6_6111/qt6_6111_mingw`)
258 +
259 + Модули проекта (Core, Gui, Network, Widgets, Xml, Svg, PrintSupport, Test, LinguistTools) входят в
260 + базовый пакет — в списке add-on'ов Android 6.11.1 их нет, add-on'ы не нужны [проверено].
261 +
262 + **Вариант А — официальный онлайн-установщик (нужна учётная запись Qt).**
263 + URL установщика [проверено, HTTP 200]:
264 + ```powershell
265 + Invoke-WebRequest -Uri 'https://download.qt.io/official_releases/online_installers/qt-online-installer-windows-x64-online.exe' -OutFile "$env:TEMP\qt-online-installer.exe"
266 + & "$env:TEMP\qt-online-installer.exe" --root C:\Qt --accept-licenses --accept-obligations `
267 + --default-answer --confirm-command --email <QT_ACCOUNT_EMAIL> --pw <QT_ACCOUNT_PASSWORD> `
268 + install qt.qt6.6111.android_arm64_v8a qt.qt6.6111.win64_mingw
269 + ```
270 + Ключи `--root --accept-licenses --accept-obligations --default-answer --confirm-command --email --pw
271 + install` — из документации Qt Installer Framework / Qt Online Installer CLI **[не проверено]** на этой
272 + версии установщика (`qt-online-installer.exe --help` покажет точный список). Вместо `--email/--pw`
273 + можно задать токен в переменной `QT_INSTALLER_JWT_TOKEN` **[не проверено]**. Пароль не оставляйте в
274 + истории PowerShell (`Clear-History`).
275 +
276 + **Вариант Б — aqtinstall (без учётной записи).** aqtinstall 3.3.0 — текущая версия на PyPI
277 + [проверено]; `aqt list-qt all_os android` показывает 6.11.1 и arch `android_arm64_v8a` [проверено];
278 + сама установка не запускалась **[не проверено]**.
279 + ```powershell
280 + py -m pip install --upgrade aqtinstall==3.3.0
281 + py -m aqt install-qt windows desktop 6.11.1 win64_mingw --outputdir C:\Qt
282 + py -m aqt install-qt all_os android 6.11.1 android_arm64_v8a --outputdir C:\Qt
283 + ```
284 + Проверка путей, которые ждёт workflow:
285 + ```powershell
286 + Test-Path 'C:\Qt\6.11.1\android_arm64_v8a\lib\cmake\Qt6\qt.toolchain.cmake'
287 + Test-Path 'C:\Qt\6.11.1\mingw_64\bin\qmake.exe'
288 + ```
289 + Сам компилятор MinGW (`qt.tools.win64_mingw1310`) для сборки **не нужен** — host-инструменты
290 + собираются MSVC (шаг `Set up MSVC`); нужен только host Qt `mingw_64` как `QT_HOST_PATH` (так в upstream).
291 +
292 + ### 2.5 Метка `windows-android` для существующего раннера
293 + В act_runner v0.2.13: если в `config.yaml` задан `runner.labels`, используется он; если пусто —
294 + метки из `.runner` [проверено: комментарий в config.example.yaml v0.2.13]. Перерегистрация не нужна.
295 + ```powershell
296 + cd <ПАПКА_РАННЕРА> # где лежат act_runner.exe, config.yaml и .runner
297 + Copy-Item config.yaml config.yaml.bak
298 + notepad config.yaml
299 + ```
300 + В `config.yaml`:
301 + ```yaml
302 + runner:
303 + labels:
304 + - "windows:host"
305 + - "windows-android:host"
306 + ```
307 + (Если раннер был зарегистрирован с другой основной меткой — сохраните её; посмотреть текущие:
308 + `Get-Content .runner`.) Перезапуск службы NSSM:
309 + ```powershell
310 + nssm status <ИМЯ_СЛУЖБЫ> # имя: Get-Service | ? Name -like '*runner*'
311 + nssm restart <ИМЯ_СЛУЖБЫ>
312 + ```
313 + В Gitea: Settings → Actions → Runners — у раннера метки `windows` и `windows-android`.
314 +
315 + ### 2.6 Переменные репозитория (если пути отличаются)
316 + `Coder/aspia` → Settings → Actions → Variables (прямые слэши):
317 + `ANDROID_QT_PATH`, `ANDROID_QT_HOST_PATH`, `ANDROID_SDK_ROOT`, `ANDROID_NDK_ROOT`, `ANDROID_JAVA_HOME`.
318 +
319 + ---
320 +
321 + ## 3. Windows: gzip для кэша vcpkg (сейчас «Save vcpkg cache» падает)
322 +
323 + Ошибка: `C:\Program Files\Git\usr\bin\tar.exe ... -z` → `/bin/sh: gzip: command not found`.
324 + tar из Git for Windows вызывает `gzip` через `sh`, а `sh` ищет его по PATH. Две причины: нет файла
325 + `gzip.exe` в `usr\bin` (MinGit / урезанная установка) или в PATH **службы** нет
326 + `C:\Program Files\Git\usr\bin`. Полный Git for Windows содержит `usr\bin\gzip.exe`
327 + **[не проверено]** для текущей 2.55.0 — проверьте командой ниже.
328 +
329 + ### 3.1 Диагностика
330 + ```powershell
331 + Test-Path 'C:\Program Files\Git\usr\bin\gzip.exe'
332 + & 'C:\Program Files\Git\usr\bin\sh.exe' -c 'command -v gzip; echo PATH=$PATH'
333 + nssm get <ИМЯ_СЛУЖБЫ> AppEnvironmentExtra
334 + ```
335 +
336 + ### 3.2 Если файла нет — поставить полный Git for Windows
337 + winget-ID `Git.Git` (последняя в каталоге — 2.55.0) [проверено: microsoft/winget-pkgs]:
338 + ```powershell
339 + winget install --id Git.Git -e --accept-package-agreements --accept-source-agreements
340 + Test-Path 'C:\Program Files\Git\usr\bin\gzip.exe'
341 + ```
342 +
343 + ### 3.3 Если файл есть, но служба его не видит — добавить usr\bin в PATH службы
344 + NSSM `AppEnvironmentExtra` дописывает переменные к окружению службы; `%PATH%` при этом
345 + **[не проверено]** раскрывается не во всех версиях NSSM — надёжнее записать PATH целиком:
346 + ```powershell
347 + $sysPath = [Environment]::GetEnvironmentVariable('Path','Machine')
348 + nssm set <ИМЯ_СЛУЖБЫ> AppEnvironmentExtra "PATH=C:\Program Files\Git\usr\bin;$sysPath"
349 + nssm get <ИМЯ_СЛУЖБЫ> AppEnvironmentExtra
350 + nssm restart <ИМЯ_СЛУЖБЫ>
351 + ```
352 + (Если в `AppEnvironmentExtra` уже есть другие переменные — передайте их тем же вызовом через
353 + пробел: `nssm set <ИМЯ> AppEnvironmentExtra "A=1" "PATH=..."`, иначе они перезапишутся.)
354 +
355 + ### 3.4 Проверка
356 + ```powershell
357 + & 'C:\Program Files\Git\usr\bin\sh.exe' -c 'command -v gzip && gzip --version | head -1'
358 + & 'C:\Program Files\Git\usr\bin\sh.exe' -c 'echo test | gzip -c | gzip -dc'
359 + ```
360 + Окончательная проверка — в логе следующего прогона шаг «Save vcpkg cache» должен закончиться
361 + `Cache saved successfully` (раньше — `gzip: command not found`).
362 +
363 + ---
364 +
365 + ## 4. Секреты и переменные Gitea (`Coder/aspia` → Settings → Actions)
366 +
367 + Все необязательные; без них — неподписанные `.pkg` и debug-APK.
368 +
369 + **macOS (подпись/нотаризация)** — секреты: `MACOS_CERT_P12_BASE64`, `MACOS_CERT_PASSWORD`,
370 + `MACOS_APP_SIGN_IDENTITY`, `MACOS_INSTALLER_SIGN_IDENTITY`, `MACOS_NOTARY_APPLE_ID`,
371 + `MACOS_NOTARY_TEAM_ID`, `MACOS_NOTARY_PASSWORD`. Переменная: `MACOS_UNIVERSAL` (`false` — только arm64).
372 + ```bash
373 + # Экспортируйте «Developer ID Application» и «Developer ID Installer» с ключами в один certs.p12
374 + # (Keychain Access → выделить оба → Export Items…), затем:
375 + base64 -i certs.p12 | pbcopy # вставить в MACOS_CERT_P12_BASE64
376 + security find-identity -v -p codesigning # точная строка для MACOS_APP_SIGN_IDENTITY
377 + security find-identity -v # строка "Developer ID Installer: ..." для MACOS_INSTALLER_SIGN_IDENTITY
378 + # MACOS_NOTARY_PASSWORD — app-specific password: https://account.apple.com → Sign-In and Security
379 + rm -P certs.p12 2>/dev/null || rm certs.p12
380 + ```
381 +
382 + **Android (release-подпись)** — секреты: `ANDROID_KEYSTORE_BASE64`, `ANDROID_KEYSTORE_PASSWORD`,
383 + `ANDROID_KEY_ALIAS`, `ANDROID_KEY_PASSWORD`. Переменные (если пути другие): см. 2.6.
384 + ```powershell
385 + & "$env:JAVA_HOME\bin\keytool.exe" -genkeypair -v -keystore aspia-release.keystore -alias aspia `
386 + -keyalg RSA -keysize 4096 -validity 10000 -storetype PKCS12
387 + [Convert]::ToBase64String([IO.File]::ReadAllBytes("$PWD\aspia-release.keystore")) | Set-Clipboard # → ANDROID_KEYSTORE_BASE64
388 + # альтернатива: certutil -encode aspia-release.keystore ks.b64 (затем удалить строки BEGIN/END и переносы)
389 + ```
390 + Для PKCS12 пароль ключа равен паролю хранилища — задайте одно значение в `ANDROID_KEYSTORE_PASSWORD`
391 + и `ANDROID_KEY_PASSWORD`. Keystore и пароли сохраните в надёжном месте: без них обновлять
392 + приложение у пользователей нельзя.
393 +
394 + **Уже есть:** `VCPKG4ASPIA_TOKEN` (секрет), при желании `RELEASE_TOKEN`, `RELEASE_API_URL`, `VCPKG4ASPIA_URL`.
395 +
396 + ---
397 +
398 + ## 5. Итоговый чек-лист и тестовый запуск
399 +
400 + macOS:
401 + - [ ] Xcode в `/Applications/Xcode.app`, лицензия принята, `xcode-select -p` указывает на него
402 + - [ ] Rosetta 2 (`arch -x86_64 /usr/bin/true`)
403 + - [ ] brew-инструменты (1.3), universal CMake 4.4.4 первым в PATH (1.3a)
404 + - [ ] act_runner v0.2.13, `config.yaml`: `timeout: 12h`, `labels: macos-arm64:host`
405 + - [ ] зарегистрирован, LaunchAgent запущен, в Gitea статус Idle
406 + - [ ] ≥ 150 ГБ свободно, сон отключён, автологин
407 +
408 + Windows / Android:
409 + - [ ] JDK 21, `ANDROID_JAVA_HOME` задан, если путь не `jdk-21.0.11.10-hotspot`
410 + - [ ] `C:\Android\sdk` с `cmdline-tools\latest`, platform-tools, platforms/build-tools, `ndk\27.2.12479018`, лицензии приняты
411 + - [ ] `C:\Qt\6.11.1\android_arm64_v8a` и `C:\Qt\6.11.1\mingw_64`
412 + - [ ] метки `windows:host` + `windows-android:host`, служба перезапущена
413 + - [ ] `sh.exe -c 'command -v gzip'` находит gzip
414 +
415 + Тестовый запуск — по одной платформе, чтобы не ждать остальные (новый тег, например
416 + `v3.1.3-lota.4`; `release_type=draft`, чтобы не публиковать):
417 + ```bash
418 + curl -H "Authorization: token <TOKEN>" -H "Content-Type: application/json" -X POST \
419 + https://git.byte-mate.ru/api/v1/repos/Coder/aspia/actions/workflows/release.yml/dispatches \
420 + -d '{"ref":"domain-auth","inputs":{"tag":"v3.1.3-lota.4","release_type":"draft","replace":"false","build_linux":"false","build_windows":"false","build_macos":"true","build_android":"false","run_tests":"true","use_cache":"true"}}'
421 + ```
422 + Затем то же с `"build_android":"true"` (и `"build_macos":"false"`), и отдельно с
423 + `"build_windows":"true"` — проверить, что «Save vcpkg cache» на Windows теперь проходит. Через форму:
424 + Actions → release → Run workflow, те же параметры. Черновики-релизы после проверки удалите
425 + (Releases → Edit → Delete) или запускайте с `replace=true` на тот же тег.
Новее Позже