Files
tactileipc3d/.gitea/workflows/windows-release.yml
2026-02-05 02:23:45 +08:00

299 lines
11 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: windows-release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Override app version (e.g. 0.5.0). Defaults to tag name without leading v."
required: false
type: string
jobs:
build_windows:
runs-on: windows-host
defaults:
run:
shell: cmd
env:
QT_ROOT: C:\Qt\6.8.3\mingw_64
BUILD_DIR: build-ci
DIST_DIR: dist
BUILD_TYPE: Release
APP_EXE_NAME: TactileIpc3D.exe
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: recursive
- name: Init submodules
run: |
git submodule sync --recursive
git submodule update --init --recursive
- name: Resolve version
run: |
set "APP_VERSION=${{ inputs.version }}"
if "%APP_VERSION%"=="" (
if "%GITHUB_REF:~0,10%"=="refs/tags/" (
set "APP_VERSION=%GITHUB_REF_NAME%"
) else (
if exist "VERSION.txt" (
for /f "usebackq delims=" %%v in ("VERSION.txt") do set "APP_VERSION=%%v"
) else (
set "APP_VERSION=%GITHUB_REF_NAME%"
)
)
)
if "%APP_VERSION:~0,1%"=="v" set "APP_VERSION=%APP_VERSION:~1%"
echo APP_VERSION=%APP_VERSION%>> "%GITHUB_ENV%"
echo Using APP_VERSION=%APP_VERSION%
- name: Setup Qt env & sanity check
run: |
call "%QT_ROOT%\bin\qtenv2.bat"
echo ==== qmake / windeployqt ====
where qmake
qmake -v
where windeployqt
where g++
g++ --version
# ========= 这里二选一CMake 或 qmake =========
# A) CMake 框架(推荐)
- name: Configure (CMake)
run: |
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "BUILD_DIR_ABS=%REPO_ROOT%\%BUILD_DIR%"
call "%QT_ROOT%\bin\qtenv2.bat"
if exist "%BUILD_DIR_ABS%" rmdir /s /q "%BUILD_DIR_ABS%"
mkdir "%BUILD_DIR_ABS%"
cmake -S "%REPO_ROOT%" -B "%BUILD_DIR_ABS%" -G "MinGW Makefiles" ^
-DCMAKE_BUILD_TYPE=%BUILD_TYPE%
- name: Build (CMake)
run: |
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "BUILD_DIR_ABS=%REPO_ROOT%\%BUILD_DIR%"
call "%QT_ROOT%\bin\qtenv2.bat"
cmake --build "%BUILD_DIR_ABS%" --config %BUILD_TYPE% -j 8
# # B) qmake 框架(如果你用 qmake把上面 CMake 三步注释掉,启用下面)
# - name: Build (qmake)
# run: |
# call "%QT_ROOT%\bin\qtenv2.bat"
# if exist "%BUILD_DIR%" rmdir /s /q "%BUILD_DIR%"
# mkdir "%BUILD_DIR%"
# cd "%BUILD_DIR%"
# qmake ..
# mingw32-make -j 8
# ========= 找到 exe & 产物目录 =========
- name: Collect exe
run: |
call "%QT_ROOT%\bin\qtenv2.bat"
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "DIST_ABS=%REPO_ROOT%\%DIST_DIR%"
if exist "%DIST_ABS%" rmdir /s /q "%DIST_ABS%"
mkdir "%DIST_ABS%"
set "BUILD_DIR_ABS=%REPO_ROOT%\%BUILD_DIR%"
set "RUNTIME_OUT_DIR=%BUILD_DIR_ABS%\out"
set "RUNTIME_OUT_DIR_CFG=%RUNTIME_OUT_DIR%\%BUILD_TYPE%"
if exist "%RUNTIME_OUT_DIR_CFG%\%APP_EXE_NAME%" (
set "RUNTIME_BASE=%RUNTIME_OUT_DIR_CFG%"
) else (
set "RUNTIME_BASE=%RUNTIME_OUT_DIR%"
)
if not exist "%RUNTIME_BASE%\%APP_EXE_NAME%" (
echo EXE not found: "%RUNTIME_BASE%\%APP_EXE_NAME%"
exit /b 1
)
echo ==== copy app exe ====
copy /y "%RUNTIME_BASE%\%APP_EXE_NAME%" "%DIST_ABS%\%APP_EXE_NAME%"
echo ==== copy plugin dlls ====
if not exist "%DIST_ABS%\plugins\decoders" mkdir "%DIST_ABS%\plugins\decoders"
if not exist "%RUNTIME_BASE%\plugins\decoders\*.dll" (
echo Plugin DLLs not found: "%RUNTIME_BASE%\plugins\decoders\*.dll"
exit /b 1
)
copy /y "%RUNTIME_BASE%\plugins\decoders\*.dll" "%DIST_ABS%\plugins\decoders\"
echo ==== copy OpenCV runtime dlls ====
set "OPENCV_LIB_DIR=%REPO_ROOT%\3rdpart\OpenCV\lib"
if not exist "%OPENCV_LIB_DIR%\libopencv_core4100.dll" (
echo OpenCV DLL not found: "%OPENCV_LIB_DIR%\libopencv_core4100.dll"
exit /b 1
)
if not exist "%OPENCV_LIB_DIR%\libopencv_imgproc4100.dll" (
echo OpenCV DLL not found: "%OPENCV_LIB_DIR%\libopencv_imgproc4100.dll"
exit /b 1
)
copy /y "%OPENCV_LIB_DIR%\libopencv_core4100.dll" "%DIST_ABS%\"
copy /y "%OPENCV_LIB_DIR%\libopencv_imgproc4100.dll" "%DIST_ABS%\"
echo Copied to %DIST_DIR%
dir "%DIST_ABS%"
- name: Deploy Qt runtime (windeployqt)
run: |
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "DIST_ABS=%REPO_ROOT%\%DIST_DIR%"
call "%QT_ROOT%\bin\qtenv2.bat"
"%QT_ROOT%\bin\windeployqt.exe" "%DIST_ABS%\%APP_EXE_NAME%" ^
--release --compiler-runtime --no-translations
- name: Build installer (Inno Setup)
run: |
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "DIST_ABS=%REPO_ROOT%\%DIST_DIR%"
set "ISS_FILE=%REPO_ROOT%\installer\TactileIpc3D.iss"
if not exist "%ISS_FILE%" (
echo Inno Setup script not found: "%ISS_FILE%"
exit /b 1
)
if not exist "%DIST_ABS%" (
echo Dist dir not found: "%DIST_ABS%"
exit /b 1
)
where iscc || (echo ISCC not found & exit /b 1)
iscc /DMyAppVersion=%APP_VERSION% /DSourceDir="%DIST_ABS%" /DOutputDir="%DIST_ABS%" "%ISS_FILE%"
# (可选)打包 zip
- name: Zip package
run: |
if defined GITHUB_WORKSPACE (
set "REPO_ROOT=%GITHUB_WORKSPACE%"
) else (
set "REPO_ROOT=%CD%"
)
set "DIST_ABS=%REPO_ROOT%\%DIST_DIR%"
powershell -NoProfile -Command ^
"if (Test-Path '%DIST_ABS%.zip') { Remove-Item -Force '%DIST_ABS%.zip' }; " ^
"Compress-Archive -Path '%DIST_ABS%\*' -DestinationPath '%DIST_ABS%.zip'"
- name: Publish Gitea Release
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
shell: powershell
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
$ErrorActionPreference = "Stop"
$token = $env:GITEA_TOKEN
if (-not $token) { throw "GITEA_TOKEN is not set. Please add it in repo secrets." }
$api = $env:GITEA_API_URL
if (-not $api) { $api = $env:GITHUB_API_URL }
if (-not $api) {
if ($env:GITEA_SERVER_URL) { $api = "$($env:GITEA_SERVER_URL)/api/v1" }
elseif ($env:GITHUB_SERVER_URL) { $api = "$($env:GITHUB_SERVER_URL)/api/v1" }
}
if (-not $api) { throw "API URL not found. Set GITEA_API_URL or GITEA_SERVER_URL." }
$repo = $env:GITHUB_REPOSITORY
if (-not $repo) { $repo = $env:GITEA_REPOSITORY }
if (-not $repo) { throw "Repository not found in env." }
$ref = $env:GITHUB_REF
$isTag = $false
if ($ref) { $isTag = $ref.StartsWith("refs/tags/") }
if ($isTag) {
$tag = $env:GITHUB_REF_NAME
} else {
$tag = "v$($env:APP_VERSION)"
}
if (-not $tag) { throw "Release tag not found." }
$owner, $repoName = $repo.Split("/")
if (-not $owner -or -not $repoName) { throw "Invalid repo format: $repo" }
$headers = @{ Authorization = "token $token" }
# Get or create release
$release = $null
try {
$release = Invoke-RestMethod -Method Get -Headers $headers -Uri "$api/repos/$owner/$repoName/releases/tags/$tag"
} catch {
$release = $null
}
if (-not $release) {
$body = @{
tag_name = $tag
name = $tag
draft = $false
prerelease = $false
}
if (-not $isTag) {
$body.target_commitish = $env:GITHUB_SHA
}
$body = $body | ConvertTo-Json
$release = Invoke-RestMethod -Method Post -Headers $headers -ContentType "application/json" -Body $body -Uri "$api/repos/$owner/$repoName/releases"
}
$releaseId = $release.id
if (-not $releaseId) { throw "Release ID not found." }
# Resolve dist dir
$repoRoot = $env:GITHUB_WORKSPACE
if (-not $repoRoot) { $repoRoot = (Get-Location).Path }
$distDir = Join-Path $repoRoot $env:DIST_DIR
if (-not (Test-Path $distDir)) { throw "Dist dir not found: $distDir" }
$installer = Get-ChildItem -Path $distDir -Filter "TactileIpc3D-Setup-*.exe" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $installer) { throw "Installer not found in $distDir" }
$zipPath = Join-Path $repoRoot "$($env:DIST_DIR).zip"
$assets = @($installer.FullName)
if (Test-Path $zipPath) { $assets += $zipPath }
# Delete existing assets with same name
$existing = Invoke-RestMethod -Method Get -Headers $headers -Uri "$api/repos/$owner/$repoName/releases/$releaseId/assets"
$existingMap = @{}
foreach ($a in $existing) { $existingMap[$a.name] = $a.id }
foreach ($asset in $assets) {
$name = [System.IO.Path]::GetFileName($asset)
if ($existingMap.ContainsKey($name)) {
$assetId = $existingMap[$name]
Invoke-RestMethod -Method Delete -Headers $headers -Uri "$api/repos/$owner/$repoName/releases/assets/$assetId"
}
$uploadUrl = "$api/repos/$owner/$repoName/releases/$releaseId/assets?name=$name"
& curl.exe -sS -X POST -H "Authorization: token $token" -F "attachment=@$asset" $uploadUrl
if ($LASTEXITCODE -ne 0) { throw "Upload failed for $name" }
}