Skip to content

Align the script with new way of Tools retreival#8

Merged
fs1n merged 20 commits into
mainfrom
refactor/new-update-script
Jun 5, 2026
Merged

Align the script with new way of Tools retreival#8
fs1n merged 20 commits into
mainfrom
refactor/new-update-script

Conversation

@fs1n
Copy link
Copy Markdown
Owner

@fs1n fs1n commented May 1, 2026

What

This PR refactors the update flow to stop “scraping for latest” at runtime and instead consume a repo-hosted manifest.json that enumerates available VirtIO and QEMU Guest Agent MSI download URLs (directly from Fedora’s archive). The PowerShell script now supports pinning specific versions (or using latest) and can prompt interactively to pick a version when not running with -Force.

Why

  • Fedora People archive browsing is Anubis-protected and unreliable/slow to query from PowerShell at runtime.
  • A generated manifest makes version selection deterministic and enables “pin a known version” behavior.
  • Docs/PR description alignment: While earlier wording referenced GitHub Releases for version discovery, the current implementation intentionally sources the manifest from the repository’s main branch (raw URL) and the workflow commits updates to main. This is simpler for consumers and avoids coupling to release assets/tags.

Changes

PowerShell (Update-VirtIO-QemuGA.ps1)

  • Bumps script version to 2.0.0.
  • Adds parameters:
    • -VirtIOVersion (default: latest)
    • -QemuGAVersion (default: latest)
  • Fetches available versions from:
    • https://raw.githubusercontent.com/fs1n/Update-VirtIO-QemuGA/refs/heads/main/manifest.json
  • Allows interactive selection when not using -Force.
  • Keeps existing safety checks (Windows/admin/x64), logging, install flow, cleanup, and reboot handling.

Manifest generation (GitHub Actions + Node)

  • Updates .github/scripts/mirror-scrape.js to generate only manifest.json (no MSI downloads).
    • Improves robustness against Anubis cold starts (retry + basic content validation).
    • Uses a persistent Playwright profile (cached) to reuse solved cookies on warm runs.
    • Collects all available versions (no KEEP_VERSIONS cap).
  • Updates .github/workflows/mirror-virtio.yml to:
    • restore the cached browser profile
    • generate manifest.json
    • commit/push manifest.json to main

Docs

  • Updates README.md to reflect the new version-pinning parameters and more general requirements (no longer requiring a direct connection to fedorapeople.org for version resolution).

…for VirtIO and QEMU Guest Agent

- Added parameters for specifying VirtIO and QEMU Guest Agent versions, defaulting to "latest".
- Implemented a manifest-based approach for fetching available versions from GitHub releases.
- Introduced user prompts for selecting versions when not using the latest.
- Removed dependency on Fedora People Archive for version resolution.
- Improved logging and error handling throughout the script.
@fs1n fs1n self-assigned this May 1, 2026
@fs1n fs1n requested a review from Copilot May 1, 2026 20:10
@fs1n fs1n added the enhancement New feature or request label May 1, 2026

This comment was marked as outdated.

fs1n and others added 13 commits May 2, 2026 10:12
…d direct from Fedora

Remove MSI downloading, renaming, and GitHub release hosting from the mirror
workflow. The scraper now only builds manifest.json with direct Fedora URLs and
commits it to main. The PS1 script fetches the manifest from raw.githubusercontent.com
and downloads directly from Fedora, eliminating the release middleman entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ions

- Add retry logic (3 attempts) + content validation in fetchWithBrowser:
  wait for Anubis to clear, pause 1.5s for post-challenge redirect,
  re-wait for networkidle, then reject if fewer than 3 links found
- VirtIO: skip per-directory fetches entirely — filename is stable
  (virtio-win-gt-x64.msi), so we only hit the archive index once
- Remove KEEP_VERSIONS cap — manifest now includes all available versions
- Relax VirtIO folder regex anchor (remove $) to tolerate any suffix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use launchPersistentContext pointed at a cached profile directory so
Anubis PoW cookies survive between daily workflow runs — warm runs
skip the challenge entirely. Also suppress the webdriver fingerprint
via --disable-blink-features=AutomationControlled and an initScript
that hides navigator.webdriver.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…env vars

GitHub Actions does not shell-expand ~ in env: values, so BROWSER_PROFILE_DIR
was being passed literally to Node.js, creating the profile in the wrong place
and causing actions/cache to find nothing to save. Use /home/runner explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 11 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment on lines +70 to +71
| `-VirtIOVersion` | Pin one of 3 available VirtIO versions to install |
| `-QemuGAVersion` | Pin one of 3 available Qemu GA versions to install |
Comment thread README.md
- Some Windows OS (Tested on Windows 11, Server 22 and Server 25)
- **Administrator privileges**
- Internet access and connection to `fedorapeople.org` & **THE** GitHub Domains
- Internet access
Comment thread .github/workflows/mirror-virtio.yml
Comment thread .github/scripts/mirror-scrape.js
Comment thread Update-VirtIO-QemuGA.ps1 Outdated
Comment on lines +29 to +32
Specify a particular VirtIO version to install (e.g. "0.1.285"). Default is "latest" which selects the newest available version from the manifest.

.PARAMETER QemuGAVersion
Specify a particular QEMU Guest Agent version to install (e.g. "0.1.285"). Default is "latest" which selects the newest available version from the manifest.
Comment thread Update-VirtIO-QemuGA.ps1 Outdated
Comment on lines +425 to +459
# --- Fetch release manifest ---
Write-Log -Message "Fetching release manifest from: $ManifestURL" -Level "Info"
try {
$FPAVirtIORootSite = Invoke-WebRequest -Uri $ArchiveVirtIOURL -UseBasicParsing -ErrorAction Stop
$manifestJson = Invoke-WebRequest -Uri $ManifestURL -UseBasicParsing -ErrorAction Stop
$manifest = $manifestJson.Content | ConvertFrom-Json
}
catch {
Write-Log -Message "Failed to access Fedora People Archive at $ArchiveVirtIOURL. Error: $_" -Level "Error"
exit 1
}

if ($FPAVirtIORootSite.StatusCode -ne 200) {
Write-Log -Message "Failed to access Fedora People Archive at $ArchiveVirtIOURL. Status Code: $($FPAVirtIORootSite.StatusCode)" -Level "Error"
exit 1
}

Write-Log -Message "Successfully accessed Fedora People Archive at $ArchiveVirtIOURL" -Level "Info"

$FPAVirtIODirectoryLinks = $FPAVirtIORootSite.Links |
Where-Object { $_.href -match 'virtio-win-[\d\.]+-\d+/?$' } |
ForEach-Object {
$ver = [regex]::Match($_.href, 'virtio-win-([\d\.]+-\d+)').Groups[1].Value
[PSCustomObject]@{ Href = $_.href; Version = $ver }
}

$VirtIOLatest = $FPAVirtIODirectoryLinks |
Sort-Object { [version]($_.Version -replace '-', '.') } -Descending |
Select-Object -First 1

if ($null -eq $VirtIOLatest) {
Write-Log -Message "No matching virtio-win version folders found in $ArchiveVirtIOURL" -Level "Error"
Write-Log -Message "Failed to fetch release manifest. Error: $_" -Level "Error"
exit 1
}

if (-not [string]::IsNullOrWhiteSpace($VirtIOCurrentVersion)) {
$VirtIOLocalComparableVersion = Get-VirtIOComparableVersion -VersionString $VirtIOCurrentVersion
$VirtIORemoteComparableVersion = Get-VirtIOComparableVersion -VersionString $VirtIOLatest.Version

if ($null -eq $VirtIOLocalComparableVersion -or $null -eq $VirtIORemoteComparableVersion) {
Write-Log -Message "VirtIO version format is incompatible for comparison (local='$VirtIOCurrentVersion', remote='$($VirtIOLatest.Version)'). VirtIO update will be skipped." -Level "Error"
$SkipVirtIO = $true
}
elseif ($VirtIOLocalComparableVersion -ge $VirtIORemoteComparableVersion) {
Write-Log -Message "VirtIO is already up to date or newer (local='$VirtIOCurrentVersion', remote='$($VirtIOLatest.Version)'). Skipping VirtIO installation." -Level "Info"
$SkipVirtIO = $true
}
else {
Write-Log -Message "VirtIO update required (local='$VirtIOCurrentVersion', remote='$($VirtIOLatest.Version)')." -Level "Info"
# --- Resolve VirtIO version ---
if ($VirtIOVersion -eq "latest") {
$selectedVirtIO = $manifest.virtio[0]
if (-not $Force) {
Write-Host "`nLatest available VirtIO: $($selectedVirtIO.version)" -ForegroundColor Cyan
$ans = Read-YesNoChoice -Message "Install this version? (Y to confirm, N to pick from list)" -DefaultOption 1
if ($ans -notmatch 1) {
$selectedVirtIO = Read-VersionChoice -ComponentName "VirtIO" -Versions $manifest.virtio
}
}
}

if (-not $SkipVirtIO) {
$FPAVirtIOLatestURL = ([Uri]::new([Uri]$ArchiveVirtIOURL, $VirtIOLatest.Href)).AbsoluteUri
if (-not $FPAVirtIOLatestURL.EndsWith('/')) { $FPAVirtIOLatestURL += '/' }

try {
$FPAVirtIOLatestSite = Invoke-WebRequest -Uri $FPAVirtIOLatestURL -UseBasicParsing -ErrorAction Stop
}
catch {
Write-Log -Message "Failed to access latest virtio-win directory at $FPAVirtIOLatestURL. Error: $_" -Level "Error"
else {
$selectedVirtIO = $manifest.virtio | Where-Object { $_.version -eq $VirtIOVersion } | Select-Object -First 1
if (-not $selectedVirtIO) {
Write-Log -Message "VirtIO version '$VirtIOVersion' not found in mirror release. Available: $(($manifest.virtio | ForEach-Object { $_.version }) -join ', ')" -Level "Error"
exit 1
}

if ($FPAVirtIOLatestSite.StatusCode -ne 200) {
Write-Log -Message "Failed to access latest virtio-win directory at $FPAVirtIOLatestURL. Status Code: $($FPAVirtIOLatestSite.StatusCode)" -Level "Error"
exit 1
}
Write-Log -Message "Selected VirtIO version: $($selectedVirtIO.version)" -Level "Info"

# --- Resolve QEMU-GA version ---
if ($QemuGAVersion -eq "latest") {
$selectedQemuGA = $manifest.qemu_ga[0]
if (-not $Force) {
Comment thread Update-VirtIO-QemuGA.ps1 Outdated
Comment thread Update-VirtIO-QemuGA.ps1
fs1n and others added 6 commits May 2, 2026 15:44
…v2.1.0

- mirror-scrape.js: merge new scrape results into existing manifest.json
  (preserve old versions, fresh wins on collision, exit non-zero on failure)
- mirror-virtio.yml: schedule Sundays 03:00 UTC, add concurrency, guard
  the commit step so a missing/empty manifest is never pushed
- Update-VirtIO-QemuGA.ps1: v2.1.0 cleanup
  - extract Resolve-AndInstallComponent helper to dedupe VirtIO/QEMU-GA flows
  - harden error handling: throw in helpers, exit 1 only at top level
  - add [CmdletBinding()] to Read-VersionChoice and Test-PendingReboot
  - add [ValidatePattern] on -VirtIOVersion / -QemuGAVersion
  - -Force now implies -AutoCleanup and -AutoReboot
  - fix docstring examples, fix typos, drop dead vars
- README: drop CAUTION block (script is fixed via manifest.json), document
  new version-pinning parameters, add How it works section
The 'install latest?' prompt fired before the up-to-date check, so
users with the latest version installed were asked to install it and
then immediately told to skip. Reorder: up-to-date check now runs
first; prompt is only reached if an upgrade is actually available.

The check is also re-run if the user picks an already-installed
version from the version list. The skip log line now includes both
the installed and the manifest version so the user understands the
relationship (e.g. installed 0.1.285, manifest 0.1.285-1, same core).
@fs1n fs1n merged commit 4715895 into main Jun 5, 2026
@fs1n fs1n deleted the refactor/new-update-script branch June 5, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants