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
@@ -0,0 +1,278 @@
|
||||
# Сборка BiLauncher под Windows, Linux и macOS и публикация в Gitea Releases.
|
||||
#
|
||||
# push тега vX.Y.Z (или vX.Y.Z-rc1 → pre-release):
|
||||
# create-release создаёт черновик релиза → три сборки прикладывают к нему файлы →
|
||||
# publish добавляет SHA256SUMS.txt и снимает флаг черновика. Если какая-то сборка
|
||||
# упала, релиз остаётся черновиком и пользователям не виден.
|
||||
# Ручной запуск (workflow_dispatch): те же сборки, но результат — артефакты прогона,
|
||||
# релиз не создаётся.
|
||||
#
|
||||
# Пути к Qt на раннерах задаются в их config.yaml (runner.envs): QT_ROOT — kit Qt,
|
||||
# QT_TOOLS — папка Tools из Qt Online Installer (там CMake и Ninja).
|
||||
# Секрет RELEASE_TOKEN — PAT с правом repository: write.
|
||||
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: linux
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
tag: ${{ steps.meta.outputs.tag }}
|
||||
release_id: ${{ steps.release.outputs.id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- id: meta
|
||||
name: Версия из CMakeLists.txt и сверка с тегом
|
||||
run: |
|
||||
version=$(sed -nE 's/^project\(BiLauncher VERSION ([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CMakeLists.txt)
|
||||
[ -n "$version" ] || { echo "Не нашёл project(BiLauncher VERSION ...)"; exit 1; }
|
||||
tag=""
|
||||
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
base="${tag#v}"; base="${base%%-*}"
|
||||
if [ "$base" != "$version" ]; then
|
||||
echo "Тег $tag не совпадает с версией $version в CMakeLists.txt"; exit 1
|
||||
fi
|
||||
version="${tag#v}"
|
||||
fi
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
echo "Версия: $version, тег: ${tag:-нет}"
|
||||
|
||||
- id: release
|
||||
name: Черновик релиза
|
||||
if: steps.meta.outputs.tag != ''
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
TAG: ${{ steps.meta.outputs.tag }}
|
||||
run: |
|
||||
# Описание релиза — раздел CHANGELOG.md для этой версии
|
||||
base="${TAG#v}"; base="${base%%-*}"
|
||||
notes=$(awk -v v="$base" '
|
||||
/^## \[/ { if (on) exit; if (index($0, "[" v "]")) { on=1; next } }
|
||||
on' CHANGELOG.md)
|
||||
prerelease=false; case "$TAG" in *-*) prerelease=true;; esac
|
||||
body=$(python3 -c 'import json,sys; print(json.dumps({"tag_name":sys.argv[1],"name":"BiLauncher "+sys.argv[1],"body":sys.argv[2],"draft":True,"prerelease":sys.argv[3]=="true"}))' \
|
||||
"$TAG" "$notes" "$prerelease")
|
||||
id=$(curl -fsS -X POST "$API/releases" \
|
||||
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d "$body" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
|
||||
echo "id=$id" >> "$GITHUB_OUTPUT"
|
||||
echo "Создан черновик релиза $TAG (id $id)"
|
||||
|
||||
build-linux:
|
||||
needs: create-release
|
||||
runs-on: linux
|
||||
env:
|
||||
VERSION: ${{ needs.create-release.outputs.version }}
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||||
outputs:
|
||||
sums: ${{ steps.pack.outputs.sums }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Сборка
|
||||
run: |
|
||||
export PATH="$QT_TOOLS/CMake/bin:$QT_TOOLS/Ninja:$PATH"
|
||||
rm -rf build AppDir dist
|
||||
# LIBDIR=lib: zlibreference.cpp ищет libz рядом, в ../lib/BiLauncher,
|
||||
# а на Ubuntu по умолчанию был бы lib/x86_64-linux-gnu.
|
||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH="$QT_ROOT" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib
|
||||
# На ВМ 6 ГБ памяти: без ограничения 42 параллельных компилятора уходят в OOM.
|
||||
cmake --build build -j 8
|
||||
cmake --install build --prefix "$PWD/AppDir/usr"
|
||||
|
||||
- id: pack
|
||||
name: AppImage и tar.gz
|
||||
run: |
|
||||
mkdir -p dist
|
||||
cp AppDir/usr/share/applications/bilauncher.desktop AppDir/
|
||||
cp AppDir/usr/share/icons/hicolor/256x256/apps/bilauncher.png AppDir/
|
||||
ln -sf usr/bin/BiLauncher AppDir/AppRun
|
||||
ARCH=x86_64 appimagetool --no-appstream AppDir "dist/BiLauncher-$VERSION-x86_64.AppImage"
|
||||
cp -a AppDir/usr "BiLauncher-$VERSION"
|
||||
tar -czf "dist/BiLauncher-$VERSION-linux-x86_64.tar.gz" "BiLauncher-$VERSION"
|
||||
rm -rf "BiLauncher-$VERSION"
|
||||
ls -lh dist
|
||||
echo "sums=$(cd dist && sha256sum * | base64 -w0)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Загрузка в релиз
|
||||
if: env.RELEASE_ID != ''
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
for f in dist/*; do
|
||||
curl -fsS -X POST -H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@$f" "$API/releases/$RELEASE_ID/assets?name=$(basename "$f")" > /dev/null
|
||||
echo "Загружен $(basename "$f")"
|
||||
done
|
||||
|
||||
- name: Артефакты прогона
|
||||
if: env.RELEASE_ID == ''
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux
|
||||
path: dist/
|
||||
|
||||
build-windows:
|
||||
needs: create-release
|
||||
runs-on: windows
|
||||
env:
|
||||
VERSION: ${{ needs.create-release.outputs.version }}
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||||
outputs:
|
||||
sums: ${{ steps.build.outputs.sums }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- id: build
|
||||
name: Сборка, установщик и portable-архив
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
# Короткие пути: дерево WebEngine легко вылезает за MAX_PATH.
|
||||
$build = "C:\r\bl-build"; $stage = "C:\r\bl-stage"; $dist = "$PWD\dist"
|
||||
Remove-Item -Recurse -Force $build, $stage, $dist -ErrorAction SilentlyContinue
|
||||
|
||||
$vs = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * `
|
||||
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
|
||||
Import-Module "$vs\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"
|
||||
Enter-VsDevShell -VsInstallPath $vs -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64"
|
||||
$env:PATH = "$env:QT_TOOLS\CMake_64\bin;$env:QT_TOOLS\Ninja;$env:PATH"
|
||||
|
||||
cmake -S . -B $build -G Ninja -DCMAKE_BUILD_TYPE=Release "-DCMAKE_PREFIX_PATH=$env:QT_ROOT"
|
||||
if ($LASTEXITCODE) { throw "cmake configure" }
|
||||
cmake --build $build
|
||||
if ($LASTEXITCODE) { throw "cmake build" }
|
||||
cmake --install $build --prefix $stage
|
||||
if ($LASTEXITCODE) { throw "cmake install" }
|
||||
|
||||
New-Item -ItemType Directory -Force $dist | Out-Null
|
||||
& "$env:ISCC_DIR\ISCC.exe" /Q "/DAppVersion=$env:VERSION" "/DSourceDir=$stage" "/DOutputDir=$dist" packaging\windows\BiLauncher.iss
|
||||
if ($LASTEXITCODE) { throw "iscc" }
|
||||
|
||||
# Portable: то же дерево, что ставит установщик, без vc_redist
|
||||
# (в portable-варианте среда выполнения MSVC должна уже стоять в системе).
|
||||
Remove-Item "$stage\bin\vc_redist.x64.exe" -ErrorAction SilentlyContinue
|
||||
$portable = "C:\r\BiLauncher-$env:VERSION"
|
||||
Remove-Item -Recurse -Force $portable -ErrorAction SilentlyContinue
|
||||
Move-Item $stage $portable
|
||||
tar.exe -a -c -f "$dist\BiLauncher-$env:VERSION-win64-portable.zip" -C C:\r "BiLauncher-$env:VERSION"
|
||||
if ($LASTEXITCODE) { throw "zip" }
|
||||
Remove-Item -Recurse -Force $portable
|
||||
|
||||
Get-ChildItem $dist | Format-Table Name, Length
|
||||
$sums = Get-ChildItem $dist | ForEach-Object {
|
||||
"{0} {1}" -f (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower(), $_.Name }
|
||||
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(($sums -join "`n") + "`n"))
|
||||
# Не Out-File: PowerShell 5.1 пишет UTF-8 с BOM, и имя первой переменной ломается.
|
||||
[IO.File]::AppendAllText($env:GITHUB_OUTPUT, "sums=$b64`n")
|
||||
|
||||
- name: Загрузка в релиз
|
||||
if: env.RELEASE_ID != ''
|
||||
shell: powershell
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
foreach ($f in Get-ChildItem dist) {
|
||||
curl.exe -fsS -X POST -H "Authorization: token $env:TOKEN" `
|
||||
-F "attachment=@$($f.FullName)" "$env:API/releases/$env:RELEASE_ID/assets?name=$($f.Name)" | Out-Null
|
||||
if ($LASTEXITCODE) { throw "Не удалось загрузить $($f.Name)" }
|
||||
"Загружен $($f.Name)"
|
||||
}
|
||||
|
||||
- name: Артефакты прогона
|
||||
if: env.RELEASE_ID == ''
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows
|
||||
path: dist/
|
||||
|
||||
build-macos:
|
||||
needs: create-release
|
||||
runs-on: macos
|
||||
env:
|
||||
VERSION: ${{ needs.create-release.outputs.version }}
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||||
outputs:
|
||||
sums: ${{ steps.pack.outputs.sums }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Сборка (universal, arm64 + x86_64)
|
||||
run: |
|
||||
export PATH="$QT_TOOLS/CMake/CMake.app/Contents/bin:$QT_TOOLS/Ninja:$PATH"
|
||||
rm -rf build stage dist dmgroot
|
||||
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH="$QT_ROOT" \
|
||||
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
|
||||
cmake --build build
|
||||
cmake --install build --prefix "$PWD/stage"
|
||||
|
||||
- id: pack
|
||||
name: Ad-hoc подпись и DMG
|
||||
run: |
|
||||
# Без Developer ID: ad-hoc подпись нужна, чтобы приложение вообще
|
||||
# запускалось на Apple Silicon; Gatekeeper всё равно спросит подтверждение.
|
||||
codesign --force --deep --sign - stage/BiLauncher.app
|
||||
codesign --verify --deep --strict stage/BiLauncher.app
|
||||
mkdir -p dmgroot dist
|
||||
cp -R stage/BiLauncher.app dmgroot/
|
||||
ln -s /Applications dmgroot/Applications
|
||||
hdiutil create -volname "BiLauncher" -srcfolder dmgroot -ov -format UDZO \
|
||||
"dist/BiLauncher-$VERSION-macOS-universal.dmg"
|
||||
rm -rf dmgroot
|
||||
ls -lh dist
|
||||
echo "sums=$(cd dist && shasum -a 256 * | base64 | tr -d '\n')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Загрузка в релиз
|
||||
if: env.RELEASE_ID != ''
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
for f in dist/*; do
|
||||
curl -fsS -X POST -H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@$f" "$API/releases/$RELEASE_ID/assets?name=$(basename "$f")" > /dev/null
|
||||
echo "Загружен $(basename "$f")"
|
||||
done
|
||||
|
||||
- name: Артефакты прогона
|
||||
if: env.RELEASE_ID == ''
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: dist/
|
||||
|
||||
publish:
|
||||
needs: [create-release, build-linux, build-windows, build-macos]
|
||||
if: needs.create-release.outputs.release_id != ''
|
||||
runs-on: linux
|
||||
env:
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
steps:
|
||||
- name: SHA256SUMS.txt и публикация
|
||||
run: |
|
||||
{
|
||||
echo "${{ needs.build-windows.outputs.sums }}" | base64 -d
|
||||
echo "${{ needs.build-linux.outputs.sums }}" | base64 -d
|
||||
echo "${{ needs.build-macos.outputs.sums }}" | base64 -d
|
||||
} | tr -d '\r' | sed '/^$/d' > SHA256SUMS.txt
|
||||
cat SHA256SUMS.txt
|
||||
curl -fsS -X POST -H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@SHA256SUMS.txt" "$API/releases/$RELEASE_ID/assets?name=SHA256SUMS.txt" > /dev/null
|
||||
curl -fsS -X PATCH -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"draft": false}' "$API/releases/$RELEASE_ID" > /dev/null
|
||||
echo "Релиз опубликован"
|
||||
Reference in new issue
Block a user