Files

339 lines
12 KiB
YAML

name: Build Windows 7 package
description: Build the Windows 7 x64 offline NSIS package.
inputs:
app-name:
description: Release asset app name prefix.
required: false
default: NyaTerm
artifact-version:
description: Version string to use in the output installer filename. Use package-json to read package.json.
required: false
default: package-json
artifact-dir:
description: Directory where output artifacts are copied.
required: false
default: win7-artifacts
include-diagnostics:
description: Copy PE import reports and build metadata into the artifact directory.
required: false
default: "false"
outputs:
installer-path:
description: Path to the Windows 7 installer artifact.
value: ${{ steps.installer.outputs.path }}
artifact-dir:
description: Directory containing the Windows 7 output artifacts.
value: ${{ inputs.artifact-dir }}
runs:
using: composite
steps:
- name: Configure Win7 build environment
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
@(
"CARGO_INCREMENTAL=0",
"RUSTFLAGS=-C target-feature=+crt-static",
"WIN7_TARGET=x86_64-win7-windows-msvc",
"WIN7_RUST_TOOLCHAIN=nightly-2026-07-22",
"WIN7_TAURI_CONFIG=src-tauri/tauri.win7.conf.json"
) | Add-Content -LiteralPath $env:GITHUB_ENV -Encoding UTF8
- name: Install pnpm
uses: pnpm/action-setup@v5
with:
version: 9
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install frontend dependencies
shell: pwsh
run: pnpm install --frozen-lockfile
- name: Prepare ConPTY runtime
shell: pwsh
run: pnpm prepare:conpty
- name: Install Win7 Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2026-07-22
components: rust-src
- name: Build frontend and Win7 MCP sidecar
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$env:NYATERM_MCP_TARGET = $env:WIN7_TARGET
$env:NYATERM_MCP_BUILD_STD = "std,panic_abort"
pnpm build
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: |
./src-tauri -> target
key: windows-2022-x86_64-win7-windows-msvc
cache-on-failure: true
env:
RUST_CACHE_COMPRESS: true
- name: Enable Win7-only Cargo patches
shell: pwsh
run: ./.github/scripts/enable-win7-cargo-patches.ps1
- name: Print build metadata
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
rustc -Vv
cargo -V
node --version
pnpm --version
Write-Host "Target: $env:WIN7_TARGET"
Write-Host "RUSTFLAGS: $env:RUSTFLAGS"
cargo metadata --manifest-path src-tauri/Cargo.toml --locked --format-version 1 | Out-File -FilePath win7-cargo-metadata.json -Encoding utf8
function PackageVersion($Name) {
$metadata = Get-Content win7-cargo-metadata.json -Raw | ConvertFrom-Json
$packages = @($metadata.packages | Where-Object { $_.name -eq $Name } | Select-Object -ExpandProperty version -Unique)
if ($packages.Count -eq 0) {
return "<not found>"
}
return ($packages -join ", ")
}
Write-Host "wry: $(PackageVersion "wry")"
Write-Host "webview2-com: $(PackageVersion "webview2-com")"
Write-Host "webview2-com-sys: $(PackageVersion "webview2-com-sys")"
Write-Host "ctor: $(PackageVersion "ctor")"
Write-Host "dirs-sys: $(PackageVersion "dirs-sys")"
Write-Host "pageant: $(PackageVersion "pageant")"
- name: Raw Win7 cargo probe
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
cargo build `
--manifest-path src-tauri/Cargo.toml `
--locked `
--release `
--target $env:WIN7_TARGET `
--features tauri/custom-protocol `
-Z build-std=std,panic_abort
if ($LASTEXITCODE -ne 0) {
throw "Raw Windows 7 cargo probe failed. Patch the first reported dependency blocker before enabling later stages."
}
- name: Locate raw Win7 executable
id: raw_exe
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$releaseDir = Join-Path "src-tauri/target" "$env:WIN7_TARGET/release"
$expected = Join-Path $releaseDir "nyaterm.exe"
if (Test-Path -LiteralPath $expected -PathType Leaf) {
$exe = (Resolve-Path -LiteralPath $expected).Path
} else {
$exe = Get-ChildItem -LiteralPath $releaseDir -Filter "*.exe" |
Where-Object { $_.Name -notmatch 'build[-_]script' } |
Select-Object -First 1 -ExpandProperty FullName
}
if ([string]::IsNullOrWhiteSpace($exe) -or !(Test-Path -LiteralPath $exe -PathType Leaf)) {
Write-Host "Expected release directory: $releaseDir"
Get-ChildItem -LiteralPath $releaseDir -Force -ErrorAction SilentlyContinue
throw "Could not locate the raw Windows 7 executable."
}
"path=$exe" >> $env:GITHUB_OUTPUT
Write-Host "Raw executable: $exe"
- name: Capture raw PE imports
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
./.github/scripts/assert-win7-pe-compat.ps1 `
-BinaryPath "${{ steps.raw_exe.outputs.path }}" `
-ReportPath "win7-pe-imports-raw.txt"
continue-on-error: true
- name: Prepare WebView2 109 fixed runtime
shell: pwsh
run: ./.github/scripts/prepare-webview2-win7-runtime.ps1
- name: Verify WebView2 109 fixed runtime
shell: pwsh
run: ./.github/scripts/assert-webview2-win7-runtime.ps1
- name: Prepare Win7-compatible WebView2 loader
shell: pwsh
run: ./.github/scripts/prepare-webview2-win7-loader.ps1
- name: Rebuild with Win7 WebView2 bundle config
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$env:TAURI_CONFIG = Get-Content $env:WIN7_TAURI_CONFIG -Raw
cargo clean --manifest-path src-tauri/Cargo.toml --target $env:WIN7_TARGET -p webview2-com-sys
if ($LASTEXITCODE -ne 0) {
throw "cargo clean failed for webview2-com-sys."
}
cargo clean --manifest-path src-tauri/Cargo.toml --target $env:WIN7_TARGET -p nyaterm
if ($LASTEXITCODE -ne 0) {
throw "cargo clean failed for nyaterm."
}
cargo build `
--manifest-path src-tauri/Cargo.toml `
--locked `
--release `
--target $env:WIN7_TARGET `
--features tauri/custom-protocol `
-Z build-std=std,panic_abort
if ($LASTEXITCODE -ne 0) {
throw "Windows 7 cargo build failed after WebView2 preparation."
}
- name: Locate final Win7 executable
id: final_exe
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$releaseDir = Join-Path "src-tauri/target" "$env:WIN7_TARGET/release"
$expected = Join-Path $releaseDir "nyaterm.exe"
if (Test-Path -LiteralPath $expected -PathType Leaf) {
$exe = (Resolve-Path -LiteralPath $expected).Path
} else {
$exe = Get-ChildItem -LiteralPath $releaseDir -Filter "*.exe" |
Where-Object { $_.Name -notmatch 'build[-_]script' } |
Select-Object -First 1 -ExpandProperty FullName
}
if ([string]::IsNullOrWhiteSpace($exe) -or !(Test-Path -LiteralPath $exe -PathType Leaf)) {
Write-Host "Expected release directory: $releaseDir"
Get-ChildItem -LiteralPath $releaseDir -Force -ErrorAction SilentlyContinue
throw "Could not locate the final Windows 7 executable."
}
"path=$exe" >> $env:GITHUB_OUTPUT
Write-Host "Final executable: $exe"
- name: Audit final PE imports
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
./.github/scripts/assert-win7-pe-compat.ps1 `
-BinaryPath "${{ steps.final_exe.outputs.path }}" `
-ReportPath "win7-pe-imports.txt"
- name: Bundle Win7 NSIS installer
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$env:TAURI_CONFIG = Get-Content $env:WIN7_TAURI_CONFIG -Raw
pnpm tauri bundle --bundles nsis --target $env:WIN7_TARGET --config $env:WIN7_TAURI_CONFIG
if ($LASTEXITCODE -ne 0) {
throw "Tauri NSIS bundle failed for the Windows 7 target."
}
- name: Locate and rename Win7 installer
id: installer
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$packageVersion = (Get-Content package.json -Raw | ConvertFrom-Json).version
$artifactVersion = "${{ inputs.artifact-version }}"
if ([string]::IsNullOrWhiteSpace($artifactVersion) -or $artifactVersion -eq "package-json") {
$artifactVersion = $packageVersion
}
$bundleDir = Join-Path "src-tauri/target" "$env:WIN7_TARGET/release/bundle/nsis"
$installer = Get-ChildItem -LiteralPath $bundleDir -Filter "*.exe" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($null -eq $installer) {
Write-Host "Expected NSIS bundle directory: $bundleDir"
Get-ChildItem -LiteralPath $bundleDir -Force -ErrorAction SilentlyContinue
throw "Could not locate the Windows 7 NSIS installer."
}
$artifactDir = "${{ inputs.artifact-dir }}"
Remove-Item -LiteralPath $artifactDir -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $artifactDir | Out-Null
$installerName = "${{ inputs.app-name }}_${artifactVersion}_windows_x64-win7-webview2-109-offline-setup.exe"
$installerPath = Join-Path $artifactDir $installerName
Copy-Item -LiteralPath $installer.FullName -Destination $installerPath -Force
if ("${{ inputs.include-diagnostics }}" -eq "true") {
Copy-Item -LiteralPath "win7-pe-imports.txt" -Destination (Join-Path $artifactDir "win7-pe-imports.txt") -Force
if (Test-Path -LiteralPath "win7-pe-imports-raw.txt") {
Copy-Item -LiteralPath "win7-pe-imports-raw.txt" -Destination (Join-Path $artifactDir "win7-pe-imports-raw.txt") -Force
}
Copy-Item -LiteralPath "win7-cargo-metadata.json" -Destination (Join-Path $artifactDir "win7-cargo-metadata.json") -Force
$metadata = [ordered]@{
app = "${{ inputs.app-name }}"
artifactVersion = $artifactVersion
packageVersion = $packageVersion
target = $env:WIN7_TARGET
rustToolchain = $env:WIN7_RUST_TOOLCHAIN
rustflags = $env:RUSTFLAGS
webview2Runtime = "109.0.1518.78"
webview2LoaderSdk = "Microsoft.Web.WebView2 1.0.1020.30"
updaterArtifacts = $false
win7RuntimeLaunch = "NOT VERIFIED"
}
$metadata | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $artifactDir "win7-build-metadata.json") -Encoding UTF8
}
"path=$installerPath" >> $env:GITHUB_OUTPUT
Write-Host "Win7 installer artifact: $installerPath"
- name: Ensure 7-Zip is available
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$knownPaths = @(
(Join-Path $env:ProgramFiles "7-Zip\7z.exe"),
(Join-Path ${env:ProgramFiles(x86)} "7-Zip\7z.exe"),
"C:\ProgramData\chocolatey\bin\7z.exe"
)
if ((Get-Command 7z.exe -ErrorAction SilentlyContinue) -or ($knownPaths | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1)) {
Write-Host "7-Zip is available."
return
}
choco install 7zip -y --no-progress
- name: Verify Win7 installer content
shell: pwsh
run: ./.github/scripts/assert-win7-installer-content.ps1 -InstallerPath "${{ steps.installer.outputs.path }}"