mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-03 12:18:48 +08:00
✨ feat(release): 发布 Windows Portable 与 MSI 双产物
- Windows AMD64 与 ARM64 同时生成 Portable EXE 和 MSI 安装包 - 统一 stable 与 dev 的 MSI 产品身份并支持通道切换升级 - 发布清单同时包含两类资产及对应 SHA256 校验信息 - 在 Windows workflow 中执行双模式更新与 WiX 契约测试
This commit is contained in:
83
.github/workflows/dev-build.yml
vendored
83
.github/workflows/dev-build.yml
vendored
@@ -25,6 +25,11 @@ jobs:
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: Test release asset contracts
|
||||
run: |
|
||||
python3 tools/generate-update-latest-manifest.test.py
|
||||
python3 tools/windows-release-artifacts.test.py
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
@@ -391,6 +396,24 @@ jobs:
|
||||
}
|
||||
& $upxCmd --version
|
||||
|
||||
- name: Install WiX Toolset (Windows)
|
||||
if: contains(matrix.platform, 'windows')
|
||||
shell: pwsh
|
||||
run: |
|
||||
$wixVersion = "6.0.2"
|
||||
$wixTools = Join-Path $env:RUNNER_TEMP "wix-tools"
|
||||
dotnet tool install wix --tool-path $wixTools --version $wixVersion
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX Toolset 安装失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
$wixTools | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
|
||||
$env:PATH = "$wixTools;$env:PATH"
|
||||
wix extension add --global "WixToolset.UI.wixext/$wixVersion"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX UI 扩展安装失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
wix --version
|
||||
|
||||
- name: Install Linux Dependencies
|
||||
if: contains(matrix.platform, 'linux')
|
||||
run: |
|
||||
@@ -519,7 +542,7 @@ jobs:
|
||||
- name: Test Windows Online Updater (Windows AMD64)
|
||||
if: ${{ matrix.platform == 'windows/amd64' }}
|
||||
shell: pwsh
|
||||
run: go test ./internal/app -run '^TestWindowsPowerShellUpdater' -count=1 -timeout=3m
|
||||
run: go test ./internal/app -run '^(TestWindowsPowerShellUpdater|TestExpectedAssetNameForExecutableUsesWindowsPortableSuffix|TestShouldWindowsUpdateLaunchDownloadedAssetDirectly|TestResolveUpdateInstallMode|TestExpectedAssetNameForWindowsInstallMode|TestResolveUpdateWorkspaceDirForPlatformSeparatesMSIFromInstallDirectory|TestValidateUpdatePackageForCurrentInstallMode|TestInstallUpdateAndRestartMSI|TestBuildWindowsMSIUpdatePowerShellScript|TestBuildWindowsMSILaunchCommand|TestResolveWindowsMSIExecPath)' -count=1 -timeout=3m
|
||||
|
||||
# ---- 生成 dev 版本号 ----
|
||||
- name: Generate Dev Version
|
||||
@@ -861,14 +884,16 @@ jobs:
|
||||
mv "$DMG_NAME" "../../$FINAL_NAME"
|
||||
|
||||
# Windows Packaging
|
||||
- name: Package Windows EXE
|
||||
- name: Package Windows Portable EXE and MSI
|
||||
if: contains(matrix.platform, 'windows')
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-Location build/bin
|
||||
$version = "${{ steps.version.outputs.version }}"
|
||||
$target = "${{ matrix.build_name }}"
|
||||
$finalExeName = "GoNavi-$version-${{ matrix.os_name }}-${{ matrix.arch_name }}${{ matrix.artifact_suffix }}.exe"
|
||||
$archName = "${{ matrix.arch_name }}"
|
||||
$portableExeName = "GoNavi-$version-${{ matrix.os_name }}-$archName${{ matrix.artifact_suffix }}-Portable.exe"
|
||||
$msiName = "GoNavi-$version-${{ matrix.os_name }}-$archName${{ matrix.artifact_suffix }}-Installer.msi"
|
||||
|
||||
if (Test-Path "$target.exe") {
|
||||
$finalExe = "$target.exe"
|
||||
@@ -911,8 +936,55 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "📦 输出 Windows 可执行文件 $finalExeName..."
|
||||
Copy-Item -LiteralPath $finalExe -Destination "..\\..\\$finalExeName" -Force
|
||||
Write-Host "📦 输出 Windows Portable 可执行文件 $portableExeName..."
|
||||
Copy-Item -LiteralPath $finalExe -Destination "..\\..\\$portableExeName" -Force
|
||||
|
||||
$runNumber = [int64]$env:GITHUB_RUN_NUMBER
|
||||
if ($runNumber -le 0 -or $runNumber -gt 65535) {
|
||||
throw "GitHub run number 无法映射为 MSI 版本号: $runNumber"
|
||||
}
|
||||
$productVersion = "255.0.$runNumber"
|
||||
$wixArch = if ($archName -eq "Arm64") { "arm64" } else { "x64" }
|
||||
$componentGuid = if ($archName -eq "Arm64") {
|
||||
"7F4C7757-329F-42B0-B312-D4B8AD50415E"
|
||||
} else {
|
||||
"0BCEE70B-9CF2-449C-9ADE-190188493234"
|
||||
}
|
||||
|
||||
$licenseText = Get-Content -LiteralPath "..\\..\\LICENSE" -Raw
|
||||
$escapedLicense = $licenseText.Replace('\', '\\').Replace('{', '\{').Replace('}', '\}')
|
||||
$escapedLicense = $escapedLicense -replace "`r?`n", "\par`r`n"
|
||||
$licenseRtf = Join-Path $env:RUNNER_TEMP "GoNavi-License.rtf"
|
||||
$rtfContent = "{\rtf1\ansi\deff0{\fonttbl{\f0 Segoe UI;}}\f0\fs18 $escapedLicense}"
|
||||
Set-Content -LiteralPath $licenseRtf -Value $rtfContent -Encoding ascii
|
||||
|
||||
$sourceExe = (Resolve-Path -LiteralPath $finalExe).Path
|
||||
$wxsPath = (Resolve-Path -LiteralPath "..\\windows\\installer.wxs").Path
|
||||
$iconPath = (Resolve-Path -LiteralPath "..\\windows\\icon.ico").Path
|
||||
$installMarkerPath = Join-Path $env:RUNNER_TEMP ".gonavi-msi-install"
|
||||
Set-Content -LiteralPath $installMarkerPath -Value "MSI" -Encoding ascii -NoNewline
|
||||
$installMarkerPath = (Resolve-Path -LiteralPath $installMarkerPath).Path
|
||||
$wixIntermediateDir = Join-Path $env:RUNNER_TEMP "wixobj-$archName"
|
||||
Write-Host "📦 生成 Windows MSI 安装程序 $msiName (version=$productVersion arch=$wixArch)..."
|
||||
wix build $wxsPath `
|
||||
-arch $wixArch `
|
||||
-ext "WixToolset.UI.wixext/6.0.2" `
|
||||
-d "ProductName=GoNavi" `
|
||||
-d "ProductVersion=$productVersion" `
|
||||
-d "UpgradeCode=CDD6BF2F-ED1E-4345-A0AB-DCDB7E15FB23" `
|
||||
-d "ComponentGuid=$componentGuid" `
|
||||
-d "InstallFolderName=GoNavi" `
|
||||
-d "RegistryKeyName=GoNavi" `
|
||||
-d "SourceExe=$sourceExe" `
|
||||
-d "InstallMarker=$installMarkerPath" `
|
||||
-d "IconPath=$iconPath" `
|
||||
-d "LicenseRtf=$licenseRtf" `
|
||||
-pdbtype none `
|
||||
-intermediatefolder $wixIntermediateDir `
|
||||
-out "..\\..\\$msiName"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX MSI 构建失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
# Linux Packaging
|
||||
- name: Package Linux
|
||||
@@ -1003,6 +1075,7 @@ jobs:
|
||||
path: |
|
||||
GoNavi-*.dmg
|
||||
GoNavi-*.exe
|
||||
GoNavi-*.msi
|
||||
GoNavi-*.tar.gz
|
||||
GoNavi-*.AppImage
|
||||
drivers/**
|
||||
|
||||
89
.github/workflows/release.yml
vendored
89
.github/workflows/release.yml
vendored
@@ -21,6 +21,11 @@ jobs:
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
- name: Test release asset contracts
|
||||
run: |
|
||||
python3 tools/generate-update-latest-manifest.test.py
|
||||
python3 tools/windows-release-artifacts.test.py
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
@@ -343,6 +348,24 @@ jobs:
|
||||
}
|
||||
& $upxCmd --version
|
||||
|
||||
- name: Install WiX Toolset (Windows)
|
||||
if: contains(matrix.platform, 'windows')
|
||||
shell: pwsh
|
||||
run: |
|
||||
$wixVersion = "6.0.2"
|
||||
$wixTools = Join-Path $env:RUNNER_TEMP "wix-tools"
|
||||
dotnet tool install wix --tool-path $wixTools --version $wixVersion
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX Toolset 安装失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
$wixTools | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8
|
||||
$env:PATH = "$wixTools;$env:PATH"
|
||||
wix extension add --global "WixToolset.UI.wixext/$wixVersion"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX UI 扩展安装失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
wix --version
|
||||
|
||||
# Linux Dependencies (GTK3, WebKit2GTK required by Wails)
|
||||
- name: Install Linux Dependencies
|
||||
if: contains(matrix.platform, 'linux')
|
||||
@@ -475,7 +498,7 @@ jobs:
|
||||
- name: Test Windows Online Updater (Windows AMD64)
|
||||
if: ${{ matrix.platform == 'windows/amd64' }}
|
||||
shell: pwsh
|
||||
run: go test ./internal/app -run '^TestWindowsPowerShellUpdater' -count=1 -timeout=3m
|
||||
run: go test ./internal/app -run '^(TestWindowsPowerShellUpdater|TestExpectedAssetNameForExecutableUsesWindowsPortableSuffix|TestShouldWindowsUpdateLaunchDownloadedAssetDirectly|TestResolveUpdateInstallMode|TestExpectedAssetNameForWindowsInstallMode|TestResolveUpdateWorkspaceDirForPlatformSeparatesMSIFromInstallDirectory|TestValidateUpdatePackageForCurrentInstallMode|TestInstallUpdateAndRestartMSI|TestBuildWindowsMSIUpdatePowerShellScript|TestBuildWindowsMSILaunchCommand|TestResolveWindowsMSIExecPath)' -count=1 -timeout=3m
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -806,7 +829,7 @@ jobs:
|
||||
mv "$DMG_NAME" "../../$FINAL_NAME"
|
||||
|
||||
# Windows Packaging
|
||||
- name: Package Windows EXE
|
||||
- name: Package Windows Portable EXE and MSI
|
||||
if: contains(matrix.platform, 'windows')
|
||||
shell: pwsh
|
||||
run: |
|
||||
@@ -816,7 +839,9 @@ jobs:
|
||||
$version = $version.Substring(1)
|
||||
}
|
||||
$target = "${{ matrix.build_name }}"
|
||||
$finalExeName = "GoNavi-$version-${{ matrix.os_name }}-${{ matrix.arch_name }}${{ matrix.artifact_suffix }}.exe"
|
||||
$archName = "${{ matrix.arch_name }}"
|
||||
$portableExeName = "GoNavi-$version-${{ matrix.os_name }}-$archName${{ matrix.artifact_suffix }}-Portable.exe"
|
||||
$msiName = "GoNavi-$version-${{ matrix.os_name }}-$archName${{ matrix.artifact_suffix }}-Installer.msi"
|
||||
|
||||
if (Test-Path "$target.exe") {
|
||||
$finalExe = "$target.exe"
|
||||
@@ -859,8 +884,61 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "📦 输出 Windows 可执行文件 $finalExeName..."
|
||||
Copy-Item -LiteralPath $finalExe -Destination "..\\..\\$finalExeName" -Force
|
||||
Write-Host "📦 输出 Windows Portable 可执行文件 $portableExeName..."
|
||||
Copy-Item -LiteralPath $finalExe -Destination "..\\..\\$portableExeName" -Force
|
||||
|
||||
if ($version -match '^(?<major>\d+)\.(?<minor>\d+)\.(?<build>\d+)(?:[-+].*)?$') {
|
||||
$major = [int]$Matches.major
|
||||
$minor = [int]$Matches.minor
|
||||
$build = [int]$Matches.build
|
||||
} else {
|
||||
throw "Windows MSI 版本必须是 major.minor.patch 格式,当前为: $version"
|
||||
}
|
||||
if ($major -gt 255 -or $minor -gt 255 -or $build -gt 65535) {
|
||||
throw "Windows MSI 版本超出范围 (major/minor <= 255, patch <= 65535): $version"
|
||||
}
|
||||
$productVersion = "$major.$minor.$build"
|
||||
$wixArch = if ($archName -eq "Arm64") { "arm64" } else { "x64" }
|
||||
$componentGuid = if ($archName -eq "Arm64") {
|
||||
"7F4C7757-329F-42B0-B312-D4B8AD50415E"
|
||||
} else {
|
||||
"0BCEE70B-9CF2-449C-9ADE-190188493234"
|
||||
}
|
||||
|
||||
$licenseText = Get-Content -LiteralPath "..\\..\\LICENSE" -Raw
|
||||
$escapedLicense = $licenseText.Replace('\', '\\').Replace('{', '\{').Replace('}', '\}')
|
||||
$escapedLicense = $escapedLicense -replace "`r?`n", "\par`r`n"
|
||||
$licenseRtf = Join-Path $env:RUNNER_TEMP "GoNavi-License.rtf"
|
||||
$rtfContent = "{\rtf1\ansi\deff0{\fonttbl{\f0 Segoe UI;}}\f0\fs18 $escapedLicense}"
|
||||
Set-Content -LiteralPath $licenseRtf -Value $rtfContent -Encoding ascii
|
||||
|
||||
$sourceExe = (Resolve-Path -LiteralPath $finalExe).Path
|
||||
$wxsPath = (Resolve-Path -LiteralPath "..\\windows\\installer.wxs").Path
|
||||
$iconPath = (Resolve-Path -LiteralPath "..\\windows\\icon.ico").Path
|
||||
$installMarkerPath = Join-Path $env:RUNNER_TEMP ".gonavi-msi-install"
|
||||
Set-Content -LiteralPath $installMarkerPath -Value "MSI" -Encoding ascii -NoNewline
|
||||
$installMarkerPath = (Resolve-Path -LiteralPath $installMarkerPath).Path
|
||||
$wixIntermediateDir = Join-Path $env:RUNNER_TEMP "wixobj-$archName"
|
||||
Write-Host "📦 生成 Windows MSI 安装程序 $msiName (version=$productVersion arch=$wixArch)..."
|
||||
wix build $wxsPath `
|
||||
-arch $wixArch `
|
||||
-ext "WixToolset.UI.wixext/6.0.2" `
|
||||
-d "ProductName=GoNavi" `
|
||||
-d "ProductVersion=$productVersion" `
|
||||
-d "UpgradeCode=CDD6BF2F-ED1E-4345-A0AB-DCDB7E15FB23" `
|
||||
-d "ComponentGuid=$componentGuid" `
|
||||
-d "InstallFolderName=GoNavi" `
|
||||
-d "RegistryKeyName=GoNavi" `
|
||||
-d "SourceExe=$sourceExe" `
|
||||
-d "InstallMarker=$installMarkerPath" `
|
||||
-d "IconPath=$iconPath" `
|
||||
-d "LicenseRtf=$licenseRtf" `
|
||||
-pdbtype none `
|
||||
-intermediatefolder $wixIntermediateDir `
|
||||
-out "..\\..\\$msiName"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "WiX MSI 构建失败,退出码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
# Linux Packaging (tar.gz and AppImage)
|
||||
- name: Package Linux
|
||||
@@ -962,6 +1040,7 @@ jobs:
|
||||
path: |
|
||||
GoNavi-*.dmg
|
||||
GoNavi-*.exe
|
||||
GoNavi-*.msi
|
||||
GoNavi-*.tar.gz
|
||||
GoNavi-*.AppImage
|
||||
drivers/**
|
||||
|
||||
Reference in New Issue
Block a user