488 lines
22 KiB
YAML
488 lines
22 KiB
YAML
name: build-windows
|
|
|
|
on:
|
|
push:
|
|
branches: [pro-features]
|
|
workflow_dispatch:
|
|
inputs:
|
|
version_suffix:
|
|
description: "Version suffix (e.g. 'cst', 'beta1'). Empty = vanilla."
|
|
type: string
|
|
default: "cst"
|
|
|
|
env:
|
|
RUST_VERSION: "1.75"
|
|
LLVM_VERSION: "15.0.6"
|
|
# Where provision.ps1 installs LLVM. ffigen and flutter_rust_bridge_codegen need
|
|
# the install root (they append bin\libclang.dll themselves).
|
|
LLVM_HOME: 'C:\tools\llvm-15.0.6'
|
|
FLUTTER_VERSION: "3.24.5"
|
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
|
CARGO_EXPAND_VERSION: "1.0.95"
|
|
FLUTTER_RUST_BRIDGE_VERSION: "1.80.1"
|
|
# Numeric base, must match Cargo.toml's <major>.<minor>.<patch>.
|
|
# MSI ProductVersion is forced to this (Windows Installer rejects non-numeric).
|
|
VERSION_BASE: "1.4.6"
|
|
# Default suffix on push events. workflow_dispatch can override per-run.
|
|
VERSION_SUFFIX: ${{ inputs.version_suffix || 'cst' }}
|
|
|
|
jobs:
|
|
build-x64:
|
|
name: build-windows-x64
|
|
runs-on: [self-hosted, windows-10]
|
|
timeout-minutes: 240
|
|
env:
|
|
VCPKG_ROOT: C:\vcpkg
|
|
VCPKG_BINARY_SOURCES: "clear;files,C:\\vcpkg-cache,readwrite"
|
|
steps:
|
|
- name: Checkout source
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Verify host toolchain
|
|
shell: pwsh
|
|
run: |
|
|
$required = 'node','pwsh','git','bash','python','rustc','cargo','rustup','clang','flutter','nuget','cmake','ninja','dotnet'
|
|
$missing = @()
|
|
foreach ($tool in $required) {
|
|
$cmd = Get-Command $tool -ErrorAction SilentlyContinue
|
|
if (-not $cmd) { $missing += $tool; continue }
|
|
$ver = & $tool --version 2>&1 | Select-Object -First 1
|
|
Write-Host ("{0,-10} {1} ({2})" -f $tool, $cmd.Source, $ver)
|
|
}
|
|
if ($missing.Count -gt 0) {
|
|
Write-Error ("Missing tools on runner: {0}. Re-run provision.ps1 or install manually." -f ($missing -join ', '))
|
|
exit 1
|
|
}
|
|
if (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) {
|
|
Write-Error "VCPKG_ROOT not set or vcpkg.exe missing at $env:VCPKG_ROOT"
|
|
exit 1
|
|
}
|
|
Write-Host "VCPKG_ROOT $env:VCPKG_ROOT"
|
|
|
|
- name: Compute version strings
|
|
shell: pwsh
|
|
run: |
|
|
$base = "${env:VERSION_BASE}"
|
|
$suffix = "${env:VERSION_SUFFIX}"
|
|
if ($base -notmatch '^\d+\.\d+\.\d+$') {
|
|
Write-Error "VERSION_BASE '$base' must be major.minor.patch numeric"
|
|
exit 1
|
|
}
|
|
if ($suffix) { $display = "$base-$suffix" } else { $display = $base }
|
|
Write-Host ("Base : {0} (used for MSI ProductVersion)" -f $base)
|
|
Write-Host ("Suffix : {0}" -f $suffix)
|
|
Write-Host ("Display : {0} (used for exe filename + Cargo.toml)" -f $display)
|
|
"VERSION_DISPLAY=$display" | Out-File -FilePath $env:GITHUB_ENV -Append
|
|
|
|
- name: Patch Cargo.toml with display version
|
|
shell: bash
|
|
run: |
|
|
# Cargo accepts SemVer-style suffix with a hyphen (e.g. 1.4.6-cst).
|
|
sed -i -E "0,/^version[[:space:]]*=/{s/^version[[:space:]]*=[[:space:]]*\"${VERSION_BASE}\"/version = \"${VERSION_DISPLAY}\"/}" Cargo.toml
|
|
echo "--- Cargo.toml [package] ---"
|
|
awk '/^\[package\]/{f=1} f; /^\[/&&!/^\[package\]/{f=0}' Cargo.toml | head -10
|
|
|
|
- name: Ensure Rust toolchain configured for runner user
|
|
shell: pwsh
|
|
run: |
|
|
# provision.ps1 installs rust machine-wide (CARGO_HOME=C:\cargo,
|
|
# RUSTUP_HOME=C:\rustup) so this is normally a no-op verification.
|
|
# Kept as a guardrail in case the runner was provisioned with an
|
|
# older script or by hand.
|
|
rustup --version
|
|
rustup toolchain install $env:RUST_VERSION --profile minimal --component rustfmt
|
|
if ($LASTEXITCODE -ne 0) { throw "rustup toolchain install failed ($LASTEXITCODE)" }
|
|
rustup default $env:RUST_VERSION
|
|
if ($LASTEXITCODE -ne 0) { throw "rustup default failed ($LASTEXITCODE)" }
|
|
rustup target add x86_64-pc-windows-msvc
|
|
rustc --version
|
|
cargo --version
|
|
|
|
- name: Install flutter_rust_bridge codegen tools
|
|
shell: pwsh
|
|
run: |
|
|
# Pin the install destination with --root so the resulting binaries land
|
|
# in a deterministic, machine-wide path regardless of which user the
|
|
# runner service is configured to run as.
|
|
$tools = 'C:\cargo-tools'
|
|
New-Item -ItemType Directory -Force -Path "$tools\bin" | Out-Null
|
|
|
|
cargo install --root $tools cargo-expand --version "$env:CARGO_EXPAND_VERSION" --locked
|
|
if ($LASTEXITCODE -ne 0) { throw "cargo install cargo-expand failed ($LASTEXITCODE)" }
|
|
|
|
cargo install --root $tools flutter_rust_bridge_codegen --version "$env:FLUTTER_RUST_BRIDGE_VERSION" --features uuid --locked
|
|
if ($LASTEXITCODE -ne 0) { throw "cargo install flutter_rust_bridge_codegen failed ($LASTEXITCODE)" }
|
|
|
|
Write-Host "--- $tools\bin ---"
|
|
Get-ChildItem "$tools\bin" | Format-Table Name, Length, LastWriteTime
|
|
|
|
$expected = Join-Path $tools 'bin\flutter_rust_bridge_codegen.exe'
|
|
if (-not (Test-Path $expected)) { throw "missing: $expected" }
|
|
|
|
Add-Content -Path $env:GITHUB_PATH -Value "$tools\bin"
|
|
|
|
- name: Generate Rust <-> Dart bridge
|
|
shell: pwsh
|
|
env:
|
|
LIBCLANG_PATH: '${{ env.LLVM_HOME }}\bin'
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Force-prepend cargo-tools and Git so they win the lookup race even if
|
|
# something earlier in PATH owns the same name.
|
|
$env:PATH = "C:\cargo-tools\bin;C:\Program Files\Git\cmd;C:\Program Files\Git\bin;$env:PATH"
|
|
|
|
Write-Host "== Tool resolution =="
|
|
foreach ($t in 'git','flutter','flutter_rust_bridge_codegen','dart') {
|
|
$cmd = Get-Command $t -ErrorAction SilentlyContinue
|
|
if ($cmd) { Write-Host ("{0,-30} {1}" -f $t, $cmd.Source) }
|
|
else { Write-Host ("{0,-30} MISSING" -f $t) }
|
|
}
|
|
|
|
# `where git` shows ALL git.exe matches on PATH. If multiple, the first
|
|
# is what CreateProcess will pick -- and it might be a broken shim.
|
|
Write-Host "`n== where git =="
|
|
where.exe git 2>&1
|
|
|
|
Write-Host "`n== git --version =="
|
|
git --version
|
|
|
|
# Diagnose the real reason flutter pub get says "Unable to find git in
|
|
# your PATH". On a self-hosted runner where the Flutter SDK at
|
|
# C:\tools\flutter was provisioned by a different user, git refuses to
|
|
# touch it with "fatal: detected dubious ownership". Flutter's tool
|
|
# catches that ProcessException and (misleadingly) reports it as a
|
|
# missing-git-on-PATH error.
|
|
Write-Host "`n== git ops on flutter SDK (probe for dubious ownership) =="
|
|
git -C 'C:\tools\flutter' rev-parse HEAD 2>&1 | Out-Host
|
|
Write-Host "`n== Configuring safe.directory globally for runner user =="
|
|
git config --global --add safe.directory '*'
|
|
git config --global --get-all safe.directory
|
|
|
|
# Workaround: stage git.exe next to dart.exe. CreateProcessW searches
|
|
# the calling exe's directory before PATH -- so dropping git.exe here
|
|
# bypasses any PATH oddities the dart child may inherit from its
|
|
# parents (powershell -> cmd -> flutter.bat -> dart.exe).
|
|
$dartBin = 'C:\tools\flutter\bin\cache\dart-sdk\bin'
|
|
$stagedGit = Join-Path $dartBin 'git.exe'
|
|
$sourceGit = 'C:\Program Files\Git\cmd\git.exe'
|
|
if ((Test-Path $dartBin) -and -not (Test-Path $stagedGit)) {
|
|
Write-Host "`nStaging $sourceGit -> $stagedGit"
|
|
Copy-Item -Force $sourceGit $stagedGit
|
|
}
|
|
|
|
if (-not (Test-Path "$env:LIBCLANG_PATH\libclang.dll")) {
|
|
throw "libclang.dll not found at $env:LIBCLANG_PATH"
|
|
}
|
|
|
|
Write-Host "`n== flutter pub get =="
|
|
Push-Location flutter
|
|
flutter pub get
|
|
$rc = $LASTEXITCODE
|
|
Pop-Location
|
|
if ($rc -ne 0) { throw "flutter pub get failed ($rc)" }
|
|
|
|
Write-Host "`n== flutter_rust_bridge_codegen =="
|
|
flutter_rust_bridge_codegen `
|
|
--llvm-path "$env:LLVM_HOME" `
|
|
--rust-input ./src/flutter_ffi.rs `
|
|
--dart-output ./flutter/lib/generated_bridge.dart `
|
|
--c-output ./flutter/macos/Runner/bridge_generated.h
|
|
if ($LASTEXITCODE -ne 0) { throw "flutter_rust_bridge_codegen failed ($LASTEXITCODE)" }
|
|
|
|
Copy-Item -Force `
|
|
./flutter/macos/Runner/bridge_generated.h `
|
|
./flutter/ios/Runner/bridge_generated.h
|
|
|
|
- name: Replace Flutter engine with rustdesk custom engine
|
|
shell: pwsh
|
|
run: |
|
|
flutter precache --windows
|
|
Invoke-WebRequest -Uri https://github.com/rustdesk/engine/releases/download/main/windows-x64-release.zip -OutFile windows-x64-release.zip
|
|
Expand-Archive -Force -Path windows-x64-release.zip -DestinationPath windows-x64-release
|
|
$engineDir = "C:\tools\flutter\bin\cache\artifacts\engine\windows-x64-release"
|
|
New-Item -ItemType Directory -Force -Path $engineDir | Out-Null
|
|
Move-Item -Force windows-x64-release\* $engineDir\
|
|
|
|
- name: Patch Flutter (dropdown_menu enableFilter)
|
|
shell: bash
|
|
run: |
|
|
patch_file=".github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff"
|
|
if [ -f "$patch_file" ]; then
|
|
flutter_root="$(dirname "$(dirname "$(which flutter)")")"
|
|
cp "$patch_file" "$flutter_root/"
|
|
(cd "$flutter_root" && git apply "$(basename "$patch_file")" || true)
|
|
fi
|
|
|
|
- name: vcpkg install dependencies (x64-windows-static)
|
|
shell: bash
|
|
env:
|
|
VCPKG_DEFAULT_HOST_TRIPLET: x64-windows-static
|
|
run: |
|
|
mkdir -p /c/vcpkg-cache
|
|
if ! "$VCPKG_ROOT/vcpkg" install \
|
|
--triplet x64-windows-static \
|
|
--x-install-root="$VCPKG_ROOT/installed"; then
|
|
find "$VCPKG_ROOT/" -name "*.log" -exec sh -c 'echo "===== {} ====="; cat "{}"' \;
|
|
exit 1
|
|
fi
|
|
|
|
- name: Diagnose + restore flutter/windows if missing
|
|
shell: bash
|
|
run: |
|
|
echo "== pwd =="
|
|
pwd
|
|
echo
|
|
echo "== flutter/ (top level) =="
|
|
ls -la flutter/ 2>/dev/null || echo "flutter/ missing"
|
|
echo
|
|
if [ -d flutter/windows ]; then
|
|
echo "== flutter/windows/ exists, file count =="
|
|
find flutter/windows -type f | wc -l
|
|
ls -la flutter/windows/
|
|
else
|
|
echo "!! flutter/windows MISSING !!"
|
|
echo "git status (filtered to flutter/windows):"
|
|
git status --porcelain | grep -E "flutter/windows" | head -30 || echo "(no entries)"
|
|
echo
|
|
echo "Restoring flutter/windows from git index..."
|
|
git checkout HEAD -- flutter/windows
|
|
if [ -d flutter/windows ]; then
|
|
echo "Restored: $(find flutter/windows -type f | wc -l) files"
|
|
else
|
|
echo "RESTORE FAILED -- check git ls-files:"
|
|
git ls-files flutter/windows | head
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# The upstream GitHub workflow runs `python build.py` which chains cargo +
|
|
# `flutter build windows` in one step. We split that here so we can:
|
|
# - get a checkpoint between cargo and flutter (~14 min apart)
|
|
# - restore flutter/windows from git index if anything has clobbered it
|
|
# (early in our self-hosted bring-up, flutter/windows occasionally
|
|
# vanished during the cargo phase under LocalSystem; the restore is
|
|
# defensive and a no-op once the runner is on a normal user)
|
|
|
|
- name: Cargo build (virtual_display dylib + main lib)
|
|
shell: pwsh
|
|
run: |
|
|
$features = "hwcodec,vram,flutter"
|
|
|
|
Push-Location libs\virtual_display\dylib
|
|
cargo build --release
|
|
if ($LASTEXITCODE -ne 0) { throw "cargo build (virtual_display) failed" }
|
|
Pop-Location
|
|
|
|
cargo build --features $features --lib --release
|
|
if ($LASTEXITCODE -ne 0) { throw "cargo build (rustdesk lib) failed" }
|
|
if (-not (Test-Path target\release\librustdesk.dll)) {
|
|
throw "target\release\librustdesk.dll missing after cargo build"
|
|
}
|
|
|
|
# Restore + build are intentionally one step. Closes any potential window
|
|
# for flutter/windows to vanish between a separate restore step and the
|
|
# build, regardless of root cause.
|
|
- name: Flutter build windows (with last-second restore)
|
|
shell: pwsh
|
|
run: |
|
|
$cmake = '.\flutter\windows\CMakeLists.txt'
|
|
|
|
Write-Host "== Pre-flight check =="
|
|
Write-Host "pwd: $(Get-Location)"
|
|
if (Test-Path .\flutter\windows) {
|
|
Write-Host "flutter/windows present: $((Get-ChildItem -Recurse .\flutter\windows -File).Count) files"
|
|
} else {
|
|
Write-Host "flutter/windows MISSING"
|
|
}
|
|
|
|
if (-not (Test-Path $cmake)) {
|
|
Write-Host "`n== Restoring flutter/windows from git index =="
|
|
git status --porcelain | Where-Object { $_ -match 'flutter/windows' } | Select-Object -First 10
|
|
git checkout HEAD -- flutter/windows
|
|
if ($LASTEXITCODE -ne 0) { throw "git checkout HEAD -- flutter/windows failed" }
|
|
if (-not (Test-Path $cmake)) {
|
|
Write-Host "git ls-files flutter/windows:"
|
|
git ls-files flutter/windows | Select-Object -First 5
|
|
throw "Restore did not produce $cmake"
|
|
}
|
|
Write-Host "Restored: $((Get-ChildItem -Recurse .\flutter\windows -File).Count) files"
|
|
}
|
|
|
|
# Touch a marker so we can confirm later (in logs) that this guard ran.
|
|
$marker = ".\flutter\windows\.restored-at"
|
|
Set-Content -Path $marker -Value (Get-Date -Format o)
|
|
|
|
Write-Host "`n== Running flutter build windows --release =="
|
|
Push-Location flutter
|
|
flutter build windows --release
|
|
$rc = $LASTEXITCODE
|
|
Pop-Location
|
|
if ($rc -ne 0) {
|
|
Write-Host "`n!! flutter build failed -- post-mortem state of flutter/windows: !!"
|
|
if (Test-Path .\flutter\windows) { Get-ChildItem .\flutter\windows -Force }
|
|
else { Write-Host "(does not exist)" }
|
|
throw "flutter build windows failed ($rc)"
|
|
}
|
|
|
|
# Mirror what build.py's build_flutter_windows() does after flutter build.
|
|
Copy-Item -Force `
|
|
target\release\deps\dylib_virtual_display.dll `
|
|
flutter\build\windows\x64\runner\Release\
|
|
|
|
Move-Item -Force flutter\build\windows\x64\runner\Release rustdesk
|
|
|
|
- name: Bundle usbmmidd_v2 + printer driver
|
|
shell: pwsh
|
|
continue-on-error: true
|
|
run: |
|
|
Invoke-WebRequest -Uri https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip -OutFile usbmmidd_v2.zip
|
|
Expand-Archive -Force usbmmidd_v2.zip -DestinationPath .
|
|
Remove-Item -Recurse -Force usbmmidd_v2\Win32
|
|
Remove-Item -Force usbmmidd_v2\deviceinstaller64.exe, usbmmidd_v2\deviceinstaller.exe, usbmmidd_v2\usbmmidd.bat
|
|
Move-Item -Force .\usbmmidd_v2 .\rustdesk\
|
|
|
|
Invoke-WebRequest -Uri https://github.com/rustdesk/hbb_common/releases/download/driver/rustdesk_printer_driver_v4-1.4.zip -OutFile printer.zip
|
|
Invoke-WebRequest -Uri https://github.com/rustdesk/hbb_common/releases/download/driver/printer_driver_adapter.zip -OutFile printer_adapter.zip
|
|
Expand-Archive -Force printer.zip -DestinationPath .
|
|
Expand-Archive -Force printer_adapter.zip -DestinationPath .
|
|
New-Item -ItemType Directory -Force -Path .\rustdesk\drivers | Out-Null
|
|
Move-Item -Force .\rustdesk_printer_driver_v4-1.4 .\rustdesk\drivers\RustDeskPrinterDriver
|
|
Move-Item -Force .\printer_driver_adapter.dll .\rustdesk\
|
|
|
|
- name: Copy Runner.res for portable packer
|
|
shell: bash
|
|
continue-on-error: true
|
|
run: |
|
|
runner_res=$(find . -name Runner.res | head -1)
|
|
[ -n "$runner_res" ] && cp "$runner_res" ./libs/portable/Runner.res
|
|
|
|
- name: Build portable self-extracting exe
|
|
shell: bash
|
|
run: |
|
|
sed -i '/dpiAware/d' res/manifest.xml
|
|
pushd ./libs/portable
|
|
pip install -r requirements.txt
|
|
python ./generate.py -f ../../rustdesk/ -o . -e ../../rustdesk/rustdesk.exe
|
|
popd
|
|
mkdir -p ./SignOutput
|
|
mv ./target/release/rustdesk-portable-packer.exe "./SignOutput/rustdesk-${VERSION_DISPLAY}-x86_64.exe"
|
|
|
|
- name: Build MSI installer
|
|
shell: pwsh
|
|
run: |
|
|
Push-Location .\res\msi
|
|
# Pass numeric VERSION_BASE explicitly: MSI ProductVersion must be numeric,
|
|
# so we cannot let preprocess.py auto-detect from rustdesk.exe (which now
|
|
# carries the suffixed VERSION_DISPLAY).
|
|
python preprocess.py --arp -d ..\..\rustdesk -v "${env:VERSION_BASE}"
|
|
|
|
# Resolve MSBuild from the installed VS Build Tools.
|
|
# Resolve vswhere.exe explicitly. ${env:ProgramFiles(x86)} interpolation
|
|
# has parser-version quirks; use [Environment] to avoid them.
|
|
$pfx86 = [Environment]::GetEnvironmentVariable('ProgramFiles(x86)')
|
|
$vswhere = Join-Path $pfx86 'Microsoft Visual Studio\Installer\vswhere.exe'
|
|
if (-not (Test-Path $vswhere)) {
|
|
throw "vswhere.exe not found at $vswhere -- VS Installer missing?"
|
|
}
|
|
Write-Host "vswhere: $vswhere"
|
|
|
|
# Diagnostic: show what VS installs vswhere can see.
|
|
Write-Host "`n== vswhere installations =="
|
|
& $vswhere -all -prerelease -products '*' -property installationPath
|
|
Write-Host "==="
|
|
|
|
# Try the targeted -requires first; fall back to a broader search if the
|
|
# component name doesn't match (e.g. on Build Tools the component IDs differ).
|
|
$msbuild = & $vswhere -latest -products '*' `
|
|
-requires Microsoft.Component.MSBuild `
|
|
-find "MSBuild\**\Bin\MSBuild.exe" | Select-Object -First 1
|
|
if (-not $msbuild) {
|
|
Write-Host "Targeted lookup failed; trying broader search."
|
|
$msbuild = & $vswhere -latest -products '*' -prerelease `
|
|
-find "MSBuild\**\Bin\MSBuild.exe" | Select-Object -First 1
|
|
}
|
|
if (-not $msbuild) {
|
|
# Last resort: any MSBuild.exe under any VS install path.
|
|
$vsRoots = & $vswhere -all -prerelease -products '*' -property installationPath
|
|
foreach ($r in $vsRoots) {
|
|
$candidate = Get-ChildItem -Path $r -Recurse -Filter 'MSBuild.exe' -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.FullName -like '*\Bin\MSBuild.exe' -and $_.FullName -notlike '*\amd64\*' } |
|
|
Select-Object -First 1
|
|
if ($candidate) { $msbuild = $candidate.FullName; break }
|
|
}
|
|
}
|
|
if (-not $msbuild) { throw "MSBuild not found via vswhere or filesystem search" }
|
|
Write-Host "msbuild: $msbuild"
|
|
|
|
# Two-stage restore covers both project flavors in this solution:
|
|
# - CustomActions.vcxproj uses old-style packages.config -> nuget restore
|
|
# - Package.wixproj is SDK-style PackageReference -> msbuild -t:Restore
|
|
nuget restore msi.sln
|
|
& $msbuild msi.sln -t:Restore -p:Configuration=Release -p:Platform=x64
|
|
if ($LASTEXITCODE -ne 0) { throw "MSBuild restore failed ($LASTEXITCODE)" }
|
|
|
|
# WiX's WindowsInstallerValidation target invokes ICEs through the
|
|
# local Windows Installer service (msiserver). When the runner user
|
|
# lacks the COM/RPC rights to that service, every ICE check fails
|
|
# with WIX0217. Skip ICE validation -- it's a development-time lint,
|
|
# not a functional requirement, and the produced MSI is identical.
|
|
# Defensively also nudge the service in case some other validation
|
|
# path (e.g. signing tools) needs it.
|
|
try { Start-Service msiserver -ErrorAction SilentlyContinue } catch {}
|
|
|
|
& $msbuild msi.sln `
|
|
-p:Configuration=Release -p:Platform=x64 `
|
|
/p:TargetVersion=Windows10 `
|
|
/p:SuppressValidation=true
|
|
if ($LASTEXITCODE -ne 0) { throw "MSBuild build failed ($LASTEXITCODE)" }
|
|
|
|
Move-Item -Force .\Package\bin\x64\Release\en-us\Package.msi "..\..\SignOutput\rustdesk-${env:VERSION_DISPLAY}-x86_64.msi"
|
|
Pop-Location
|
|
|
|
- name: Report signing status of build artifacts
|
|
shell: pwsh
|
|
run: |
|
|
$artifacts = Get-ChildItem .\SignOutput -Include *.exe,*.msi -File
|
|
if (-not $artifacts) {
|
|
Write-Warning "No artifacts found in SignOutput\"
|
|
return
|
|
}
|
|
|
|
$unsigned = @()
|
|
foreach ($f in $artifacts) {
|
|
$sig = Get-AuthenticodeSignature -FilePath $f.FullName
|
|
$size = '{0,8:N0}' -f $f.Length
|
|
switch ($sig.Status) {
|
|
'Valid' {
|
|
Write-Host ("[ SIGNED ] {0} ({1} bytes) signed by: {2}" -f $f.Name, $size, $sig.SignerCertificate.Subject)
|
|
}
|
|
'NotSigned' {
|
|
Write-Host ("[UNSIGNED] {0} ({1} bytes)" -f $f.Name, $size)
|
|
$unsigned += $f.Name
|
|
}
|
|
default {
|
|
Write-Host ("[ {0,-7} ] {1} ({2} bytes) -- {3}" -f $sig.Status, $f.Name, $size, $sig.StatusMessage)
|
|
$unsigned += $f.Name
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($unsigned.Count -gt 0) {
|
|
# Render a Gitea/GHA-style annotation so it shows up prominently in the run summary.
|
|
$list = $unsigned -join ', '
|
|
Write-Host "::warning title=Unsigned artifacts::$list -- SmartScreen will warn end users. Wire up signing before distributing."
|
|
}
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: rustdesk-windows-x64-${{ github.sha }}
|
|
path: |
|
|
SignOutput/rustdesk-*.exe
|
|
SignOutput/rustdesk-*.msi
|
|
if-no-files-found: warn
|
|
retention-days: 14
|