CI: сборка релизов под Windows, Linux и macOS через Gitea Actions
- .gitea/workflows/release.yml: по тегу vX.Y.Z черновик релиза, три сборки
(Inno Setup + portable zip, AppImage + tar.gz, universal DMG), SHA256SUMS
и публикация; workflow_dispatch собирает артефакты без релиза.
- ci/setup-runner-{linux.sh,windows.ps1}: подготовка раннеров поверх уже
установленного Qt (компилятор, git, node, appimagetool/Inno, gitea-runner).
- packaging/: THIRD_PARTY_LICENSES.txt (без него падал cmake --install на
Windows/Linux) и скрипт установщика Inno Setup.
- Linux: недостающий #include <QCoreApplication> в zlibreference.cpp и
OUTPUT_DIRECTORY QML-модуля — каталог BiLauncher в build-dir совпадал с
именем исполняемого файла, и линковка падала.
- Из ресурсов убраны неиспользуемые mp4 и дубли icon.rc; из git — icon.rc
(генерируется из icon.rc.in) и doc/.DS_Store.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
29b53ce75a
commit
586201ac4e
9 files changed
+658
-5
No files matched your search
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
# Подготовка Linux-раннера Gitea Actions для сборки BiLauncher (Ubuntu 22.04).
|
||||
#
|
||||
# Qt (~/Qt/6.11.1/gcc_64 с WebEngine), CMake и Ninja (~/Qt/Tools) ставятся заранее
|
||||
# через Qt Online Installer — скрипт их не трогает, а докачивает только то, чего Qt
|
||||
# не даёт: компилятор, системные библиотеки для сборки и деплоя, Node.js (для
|
||||
# actions/checkout), appimagetool и сам gitea-runner. Повторный запуск безопасен.
|
||||
#
|
||||
# Запуск от пользователя, которому принадлежит Qt (нужен sudo без пароля):
|
||||
# ./setup-runner-linux.sh [токен регистрации]
|
||||
set -euo pipefail
|
||||
|
||||
TOKEN="${1:-}"
|
||||
INSTANCE="${INSTANCE:-https://projects-live.galeonworx.com}"
|
||||
RUNNER_NAME="${RUNNER_NAME:-linux-vm}"
|
||||
RUNNER_VERSION="${RUNNER_VERSION:-4.1.0}"
|
||||
QT_ROOT="${QT_ROOT:-$HOME/Qt/6.11.1/gcc_64}"
|
||||
QT_TOOLS="${QT_TOOLS:-$HOME/Qt/Tools}"
|
||||
RDIR="$HOME/act_runner"
|
||||
|
||||
[ -d "$QT_ROOT/lib/cmake/Qt6WebEngineQuick" ] || { echo "Нет Qt с WebEngine в $QT_ROOT" >&2; exit 1; }
|
||||
|
||||
# --- Компилятор и библиотеки ---------------------------------------------------
|
||||
# libgl1-mesa-dev — заголовки OpenGL для Qt6::Gui; xcb-* и прочие — то, что
|
||||
# Linux-деплой Qt и плагин xcb ищут при упаковке и запуске; libfuse2 — для
|
||||
# запуска самого appimagetool (он тоже AppImage).
|
||||
sudo apt-get update -q
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||
build-essential patchelf file curl git xz-utils \
|
||||
libgl1-mesa-dev libfuse2 libfontconfig1 libdbus-1-3 \
|
||||
libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
|
||||
libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 libxcb-xkb1 \
|
||||
libnss3 libxcomposite1 libxdamage1 libxrandr2 libxtst6 libxkbfile1 libxshmfence1 libasound2
|
||||
|
||||
# --- Node.js LTS ---------------------------------------------------------------
|
||||
if ! command -v node >/dev/null; then
|
||||
NODE_VER=$(curl -fsSL https://nodejs.org/dist/index.json \
|
||||
| python3 -c 'import json,sys; print(next(r["version"] for r in json.load(sys.stdin) if r["lts"]))')
|
||||
curl -fsSL "https://nodejs.org/dist/$NODE_VER/node-$NODE_VER-linux-x64.tar.xz" -o /tmp/node.tar.xz
|
||||
sudo rm -rf /opt/node && sudo mkdir -p /opt/node
|
||||
sudo tar -xJf /tmp/node.tar.xz -C /opt/node --strip-components=1
|
||||
sudo ln -sf /opt/node/bin/node /opt/node/bin/npm /opt/node/bin/npx /usr/local/bin/
|
||||
fi
|
||||
|
||||
# --- appimagetool ----------------------------------------------------------------
|
||||
if ! command -v appimagetool >/dev/null; then
|
||||
sudo curl -fsSL -o /usr/local/bin/appimagetool \
|
||||
https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
sudo chmod +x /usr/local/bin/appimagetool
|
||||
fi
|
||||
|
||||
# --- gitea-runner ------------------------------------------------------------------
|
||||
mkdir -p "$RDIR/work"
|
||||
if [ ! -x "$RDIR/gitea-runner" ]; then
|
||||
curl -fsSL -o "$RDIR/gitea-runner" \
|
||||
"https://gitea.com/gitea/runner/releases/download/v$RUNNER_VERSION/gitea-runner-$RUNNER_VERSION-linux-amd64"
|
||||
chmod +x "$RDIR/gitea-runner"
|
||||
fi
|
||||
|
||||
cat > "$RDIR/config.yaml" <<EOF
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: $RDIR/.runner
|
||||
capacity: 1
|
||||
timeout: 3h
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
envs:
|
||||
QT_ROOT: $QT_ROOT
|
||||
QT_TOOLS: $QT_TOOLS
|
||||
labels:
|
||||
- "linux:host"
|
||||
cache:
|
||||
enabled: false
|
||||
host:
|
||||
workdir_parent: $RDIR/work
|
||||
EOF
|
||||
|
||||
if [ -n "$TOKEN" ] && [ ! -f "$RDIR/.runner" ]; then
|
||||
(cd "$RDIR" && ./gitea-runner register --no-interactive --instance "$INSTANCE" \
|
||||
--token "$TOKEN" --name "$RUNNER_NAME" --labels "linux:host" --config config.yaml)
|
||||
fi
|
||||
|
||||
# --- systemd: раннер работает от владельца Qt, а не от root ------------------------
|
||||
sudo tee /etc/systemd/system/gitea-runner.service >/dev/null <<EOF
|
||||
[Unit]
|
||||
Description=Gitea Actions runner (BiLauncher)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
User=$USER
|
||||
WorkingDirectory=$RDIR
|
||||
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
||||
ExecStart=$RDIR/gitea-runner daemon --config $RDIR/config.yaml
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now gitea-runner
|
||||
echo "Готово: $(systemctl is-active gitea-runner)"
|
||||
@@ -0,0 +1,143 @@
|
||||
# Подготовка Windows-раннера Gitea Actions для сборки BiLauncher.
|
||||
#
|
||||
# Qt (C:\Qt\6.11.1\msvc2022_64 с WebEngine), CMake и Ninja (C:\Qt\Tools) ставятся
|
||||
# заранее через Qt Online Installer — скрипт их не трогает, а докачивает только то,
|
||||
# чего Qt не даёт: компилятор MSVC, git, Node.js (для actions/checkout), Inno Setup
|
||||
# и сам gitea-runner. Повторный запуск безопасен: уже установленное пропускается.
|
||||
#
|
||||
# Запуск (PowerShell от администратора):
|
||||
# powershell -ExecutionPolicy Bypass -File setup-runner-windows.ps1 [-Token <токен регистрации>]
|
||||
|
||||
param(
|
||||
[string]$Token = "",
|
||||
[string]$Instance = "https://projects-live.galeonworx.com",
|
||||
[string]$RunnerName = "win-vm",
|
||||
[string]$RunnerVersion = "4.1.0",
|
||||
[string]$QtRoot = "C:\Qt\6.11.1\msvc2022_64",
|
||||
[string]$QtTools = "C:\Qt\Tools"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue" # иначе Invoke-WebRequest падает без консоли (по SSH)
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
$dl = "C:\ci-downloads"
|
||||
New-Item -ItemType Directory -Force -Path $dl | Out-Null
|
||||
|
||||
function Fetch($url, $name) {
|
||||
$out = Join-Path $dl $name
|
||||
if (-not (Test-Path $out)) {
|
||||
Write-Host "Скачиваю $url"
|
||||
Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $out
|
||||
}
|
||||
return $out
|
||||
}
|
||||
|
||||
function Run($exe, $argList) {
|
||||
$p = Start-Process -FilePath $exe -ArgumentList $argList -Wait -PassThru -NoNewWindow
|
||||
# 3010 — «успешно, нужна перезагрузка» у установщиков MSI и VS
|
||||
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { throw "$exe завершился с кодом $($p.ExitCode)" }
|
||||
}
|
||||
|
||||
# --- Visual Studio 2022 Build Tools (MSVC x64 + Windows SDK) -----------------
|
||||
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
$haveMsvc = (Test-Path $vswhere) -and
|
||||
(& $vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath)
|
||||
if (-not $haveMsvc) {
|
||||
$vs = Fetch "https://aka.ms/vs/17/release/vs_BuildTools.exe" "vs_BuildTools.exe"
|
||||
Write-Host "Ставлю VS 2022 Build Tools (20–40 минут)…"
|
||||
Run $vs @("--quiet", "--wait", "--norestart", "--nocache",
|
||||
"--add", "Microsoft.VisualStudio.Workload.VCTools", "--includeRecommended")
|
||||
} else { Write-Host "MSVC уже установлен" }
|
||||
|
||||
# --- Git for Windows -----------------------------------------------------------
|
||||
if (-not (Test-Path "C:\Program Files\Git\cmd\git.exe")) {
|
||||
$rel = Invoke-RestMethod "https://api.github.com/repos/git-for-windows/git/releases/latest"
|
||||
$asset = $rel.assets | Where-Object { $_.name -match '^Git-.*-64-bit\.exe$' } | Select-Object -First 1
|
||||
$git = Fetch $asset.browser_download_url $asset.name
|
||||
Run $git @("/VERYSILENT", "/NORESTART", "/NOCANCEL", "/SP-", "/COMPONENTS=gitlfs")
|
||||
} else { Write-Host "Git уже установлен" }
|
||||
|
||||
# --- Node.js LTS (нужен JS-экшенам вроде actions/checkout) ---------------------
|
||||
if (-not (Test-Path "C:\Program Files\nodejs\node.exe")) {
|
||||
# Скобки вокруг Invoke-RestMethod обязательны: PowerShell 5.1 иначе отдаёт
|
||||
# JSON-массив в конвейер одним объектом, и фильтр видит все версии сразу.
|
||||
$lts = ((Invoke-RestMethod "https://nodejs.org/dist/index.json") | Where-Object { $_.lts } | Select-Object -First 1).version
|
||||
$msi = Fetch "https://nodejs.org/dist/$lts/node-$lts-x64.msi" "node-$lts-x64.msi"
|
||||
Run "msiexec.exe" @("/i", "`"$msi`"", "/qn", "/norestart")
|
||||
} else { Write-Host "Node.js уже установлен" }
|
||||
|
||||
# --- Inno Setup ----------------------------------------------------------------
|
||||
$iscc = Get-ChildItem "C:\Program Files*\Inno Setup*\ISCC.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if (-not $iscc) {
|
||||
# jrsoftware.org/download.php без браузера отдаёт HTML — берём файл из релизов на GitHub
|
||||
$rel = Invoke-RestMethod "https://api.github.com/repos/jrsoftware/issrc/releases/latest"
|
||||
$asset = $rel.assets | Where-Object { $_.name -match '^innosetup-[\d.]+(-x64)?\.exe$' } |
|
||||
Sort-Object { $_.name -notmatch '-x64' } | Select-Object -First 1
|
||||
$is = Fetch $asset.browser_download_url $asset.name
|
||||
Run $is @("/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART", "/ALLUSERS")
|
||||
$iscc = Get-ChildItem "C:\Program Files*\Inno Setup*\ISCC.exe" | Select-Object -First 1
|
||||
} else { Write-Host "Inno Setup уже установлен" }
|
||||
|
||||
# --- Длинные пути: дерево WebEngine легко вылезает за 260 символов --------------
|
||||
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem -Name LongPathsEnabled -Value 1
|
||||
& "C:\Program Files\Git\cmd\git.exe" config --system core.longpaths true
|
||||
|
||||
# --- gitea-runner ----------------------------------------------------------------
|
||||
$rdir = "C:\act_runner"
|
||||
New-Item -ItemType Directory -Force -Path $rdir, "C:\r" | Out-Null
|
||||
$exe = Join-Path $rdir "gitea-runner.exe"
|
||||
if (-not (Test-Path $exe)) {
|
||||
$src = Fetch "https://gitea.com/gitea/runner/releases/download/v$RunnerVersion/gitea-runner-$RunnerVersion-windows-amd64.exe" "gitea-runner-$RunnerVersion.exe"
|
||||
Copy-Item $src $exe
|
||||
}
|
||||
|
||||
# Конфиг: host-режим, рабочая папка с коротким путём, пути к Qt через env.
|
||||
$isccDir = Split-Path $iscc.FullName
|
||||
$cfg = @"
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: $($rdir -replace '\\','/')/.runner
|
||||
capacity: 1
|
||||
timeout: 3h
|
||||
fetch_timeout: 5s
|
||||
fetch_interval: 2s
|
||||
envs:
|
||||
QT_ROOT: '$QtRoot'
|
||||
QT_TOOLS: '$QtTools'
|
||||
ISCC_DIR: '$isccDir'
|
||||
labels:
|
||||
- "windows:host"
|
||||
cache:
|
||||
enabled: false
|
||||
host:
|
||||
workdir_parent: C:/r
|
||||
"@
|
||||
Set-Content -Path (Join-Path $rdir "config.yaml") -Value $cfg -Encoding UTF8
|
||||
|
||||
if ($Token -and -not (Test-Path (Join-Path $rdir ".runner"))) {
|
||||
Push-Location $rdir
|
||||
& $exe register --no-interactive --instance $Instance --token $Token `
|
||||
--name $RunnerName --labels "windows:host" --config config.yaml
|
||||
if ($LASTEXITCODE -ne 0) { throw "Регистрация раннера не удалась" }
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# Обёртка запуска: PATH дополняется git и node — задача планировщика может
|
||||
# стартовать раньше, чем сессия получит обновлённый системный PATH.
|
||||
$cmd = @"
|
||||
@echo off
|
||||
set PATH=C:\Program Files\Git\cmd;C:\Program Files\Git\usr\bin;C:\Program Files\nodejs;%PATH%
|
||||
cd /d $rdir
|
||||
gitea-runner.exe daemon --config config.yaml >> runner.log 2>&1
|
||||
"@
|
||||
Set-Content -Path (Join-Path $rdir "run-runner.cmd") -Value $cmd -Encoding ASCII
|
||||
|
||||
# Автозапуск при входе galeon: так задаче не нужен пароль учётной записи.
|
||||
# Чтобы раннер поднимался и без входа, пересоздайте задачу с /sc onstart /rp *.
|
||||
schtasks /create /f /tn "Gitea Runner" /sc onlogon /ru $env:USERNAME /it /rl highest `
|
||||
/tr "powershell.exe -WindowStyle Hidden -NoProfile -Command $rdir\run-runner.cmd" | Out-Null
|
||||
if (-not (Get-Process gitea-runner -ErrorAction SilentlyContinue)) { schtasks /run /tn "Gitea Runner" | Out-Null }
|
||||
|
||||
Write-Host "Готово. MSVC, git, node, Inno Setup и gitea-runner на месте."
|
||||
Reference in new issue
Block a user