From 4f43abaad33d74e952165a84903f92c802d2b8b9 Mon Sep 17 00:00:00 2001
From: Dmitry Beskov <43372966+besdar@users.noreply.github.com>
Date: Sat, 16 May 2026 14:13:33 +0000
Subject: [PATCH 1/2] Automation: Add initial configuration and script for
Holepunch.Keet
---
Tasks/Holepunch.Keet/Config.yaml | 4 +
Tasks/Holepunch.Keet/Script.ps1 | 136 +++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
create mode 100644 Tasks/Holepunch.Keet/Config.yaml
create mode 100644 Tasks/Holepunch.Keet/Script.ps1
diff --git a/Tasks/Holepunch.Keet/Config.yaml b/Tasks/Holepunch.Keet/Config.yaml
new file mode 100644
index 0000000000..bed775c492
--- /dev/null
+++ b/Tasks/Holepunch.Keet/Config.yaml
@@ -0,0 +1,4 @@
+Type: PackageTask
+WinGetIdentifier: Holepunch.Keet
+Skip: false
+Notes: MSIX installer from Keet static server
diff --git a/Tasks/Holepunch.Keet/Script.ps1 b/Tasks/Holepunch.Keet/Script.ps1
new file mode 100644
index 0000000000..f2aaf650e9
--- /dev/null
+++ b/Tasks/Holepunch.Keet/Script.ps1
@@ -0,0 +1,136 @@
+# Script to update Holepunch.Keet manifest
+# Keet is distributed via MSIX from https://static.keet.io/downloads/
+
+# Fetch the directory listing from the downloads page
+try {
+ $DownloadsPage = Invoke-WebRequest -Uri 'https://static.keet.io/downloads/' -ErrorAction SilentlyContinue
+
+ # Parse version directories from the HTML directory listing
+ # Look for href links like 4.15.0/
+ $VersionMatches = [regex]::Matches($DownloadsPage.Content, '(\d+\.\d+\.\d+)')
+
+ if ($VersionMatches.Count -gt 0) {
+ # Extract version numbers and sort them to find the latest
+ $Versions = $VersionMatches | ForEach-Object { $_.Groups[1].Value } |
+ Sort-Object -Property @{ Expression = { [version]$_ } } -Descending
+
+ $Version = $Versions[0]
+ }
+
+ # Try to get the release date from the directory listing
+ # The HTML shows dates like "15-May-2026 21:44"
+ $VersionDates = [regex]::Matches($DownloadsPage.Content, "$([regex]::Escape($Version))\s+(\d+-\w+-\d+\s+\d+:\d+)")
+
+ if ($VersionDates.Count -gt 0) {
+ try {
+ $DateString = $VersionDates[0].Groups[1].Value
+ # Parse date string like "15-May-2026 21:44"
+ $ReleaseTime = [datetime]::ParseExact($DateString, 'dd-MMM-yyyy HH:mm', [cultureinfo]::InvariantCulture)
+ } catch {
+ Write-Warning "Could not parse release date: $_"
+ }
+ }
+} catch {
+ Write-Warning "Could not fetch downloads page: $_"
+}
+
+if (-not $Version) {
+ Write-Warning "Could not determine latest Keet version"
+ exit
+}
+
+# Normalize version to standard format for winget (e.g., 4.15.0 -> 4.15.0.0)
+if ($Version -notmatch '\d+\.\d+\.\d+\.\d+') {
+ if ($Version -match '^\d+\.\d+\.\d+$') {
+ $Version = "$Version.0"
+ }
+}
+
+# Get installer URL - use the three-part version (strip the .0 we added)
+$UrlVersion = $Version -replace '\.0$'
+$InstallerUrl = "https://static.keet.io/downloads/$UrlVersion/Keet.msix"
+
+# Try to get SHA256 hash
+$InstallerSha256 = $null
+try {
+ $Response = Invoke-WebRequest -Uri $InstallerUrl -Method Head -ErrorAction SilentlyContinue
+ if ($Response.StatusCode -eq 200) {
+ # Download the file to compute hash (this can be slow)
+ $TempFile = [System.IO.Path]::GetTempFileName()
+ Invoke-WebRequest -Uri $InstallerUrl -OutFile $TempFile -ErrorAction SilentlyContinue
+ $InstallerSha256 = (Get-FileHash -Path $TempFile -Algorithm SHA256).Hash
+ Remove-Item -Path $TempFile -Force
+ }
+} catch {
+ Write-Warning "Could not compute hash for installer: $_"
+}
+
+# Set version
+$this.CurrentState.Version = $Version
+
+# Add installer information for x64
+$InstallerInfo1 = [ordered]@{
+ Architecture = 'x64'
+ InstallerType = 'msix'
+ InstallerUrl = $InstallerUrl
+}
+if ($InstallerSha256) {
+ $InstallerInfo1['InstallerSha256'] = $InstallerSha256
+}
+$this.CurrentState.Installer += $InstallerInfo1
+
+# Add installer information for arm64
+$InstallerInfo2 = [ordered]@{
+ Architecture = 'arm64'
+ InstallerType = 'msix'
+ InstallerUrl = $InstallerUrl
+}
+if ($InstallerSha256) {
+ $InstallerInfo2['InstallerSha256'] = $InstallerSha256
+}
+$this.CurrentState.Installer += $InstallerInfo2
+
+switch -Regex ($this.Check()) {
+ 'New|Changed|Updated' {
+ try {
+ if ($ReleaseTime) {
+ $this.CurrentState.ReleaseTime = $ReleaseTime
+ }
+
+ # Add locale information (en-US)
+ $this.CurrentState.Locale += [ordered]@{
+ Locale = 'en-US'
+ Key = 'Documentations'
+ Value = @(
+ [ordered]@{
+ DocumentLabel = 'GitHub'
+ DocumentUrl = 'https://github.com/holepunchto/keet'
+ }
+ [ordered]@{
+ DocumentLabel = 'Website'
+ DocumentUrl = 'https://keet.io/'
+ }
+ )
+ }
+
+ # Add license information
+ $this.CurrentState.Locale += [ordered]@{
+ Locale = 'en-US'
+ Key = 'LicenseUrl'
+ Value = 'https://github.com/holepunchto/keet/blob/main/LICENSE'
+ }
+
+ $this.Print()
+ $this.Write()
+ } catch {
+ $_ | Out-Host
+ $this.Log($_, 'Warning')
+ }
+ }
+ 'Changed|Updated' {
+ $this.Message()
+ }
+ 'Updated' {
+ $this.Submit()
+ }
+}
From 13edc765966f38490b32585e0ba86e59687f49e0 Mon Sep 17 00:00:00 2001
From: Dmitry Beskov <43372966+besdar@users.noreply.github.com>
Date: Sat, 16 May 2026 14:26:13 +0000
Subject: [PATCH 2/2] Automation: Refactor script to improve version fetching
and error handling for Holepunch.Keet
---
Tasks/Holepunch.Keet/Script.ps1 | 92 +++++++++++++--------------------
1 file changed, 37 insertions(+), 55 deletions(-)
diff --git a/Tasks/Holepunch.Keet/Script.ps1 b/Tasks/Holepunch.Keet/Script.ps1
index f2aaf650e9..faffb783cd 100644
--- a/Tasks/Holepunch.Keet/Script.ps1
+++ b/Tasks/Holepunch.Keet/Script.ps1
@@ -1,72 +1,54 @@
-# Script to update Holepunch.Keet manifest
-# Keet is distributed via MSIX from https://static.keet.io/downloads/
+$Prefix = 'https://static.keet.io/downloads/'
+$DownloadsPage = Invoke-WebRequest -Uri $Prefix | Read-ResponseContent
-# Fetch the directory listing from the downloads page
-try {
- $DownloadsPage = Invoke-WebRequest -Uri 'https://static.keet.io/downloads/' -ErrorAction SilentlyContinue
-
- # Parse version directories from the HTML directory listing
- # Look for href links like 4.15.0/
- $VersionMatches = [regex]::Matches($DownloadsPage.Content, '(\d+\.\d+\.\d+)')
-
- if ($VersionMatches.Count -gt 0) {
- # Extract version numbers and sort them to find the latest
- $Versions = $VersionMatches | ForEach-Object { $_.Groups[1].Value } |
- Sort-Object -Property @{ Expression = { [version]$_ } } -Descending
-
- $Version = $Versions[0]
+$ReleaseEntries = [regex]::Matches(
+ $DownloadsPage,
+ '\k/\s+(?\d{2}-[A-Za-z]{3}-\d{4}\s+\d{2}:\d{2})'
+) | ForEach-Object -Process {
+ [ordered]@{
+ Version = $_.Groups['Version'].Value
+ ReleaseTime = $_.Groups['ReleaseTime'].Value
}
-
- # Try to get the release date from the directory listing
- # The HTML shows dates like "15-May-2026 21:44"
- $VersionDates = [regex]::Matches($DownloadsPage.Content, "$([regex]::Escape($Version))\s+(\d+-\w+-\d+\s+\d+:\d+)")
-
- if ($VersionDates.Count -gt 0) {
- try {
- $DateString = $VersionDates[0].Groups[1].Value
- # Parse date string like "15-May-2026 21:44"
- $ReleaseTime = [datetime]::ParseExact($DateString, 'dd-MMM-yyyy HH:mm', [cultureinfo]::InvariantCulture)
- } catch {
- Write-Warning "Could not parse release date: $_"
- }
- }
-} catch {
- Write-Warning "Could not fetch downloads page: $_"
-}
+} | Sort-Object -Property @{ Expression = { [version]$_.Version } } -Descending
-if (-not $Version) {
- Write-Warning "Could not determine latest Keet version"
- exit
+if (-not $ReleaseEntries) {
+ throw 'Could not determine latest Keet version'
}
-# Normalize version to standard format for winget (e.g., 4.15.0 -> 4.15.0.0)
-if ($Version -notmatch '\d+\.\d+\.\d+\.\d+') {
- if ($Version -match '^\d+\.\d+\.\d+$') {
- $Version = "$Version.0"
- }
-}
+$LatestRelease = $ReleaseEntries[0]
+$UrlVersion = $LatestRelease.Version
+$InstallerUrl = "${Prefix}${UrlVersion}/Keet.msix"
+$ReleaseTime = $null
-# Get installer URL - use the three-part version (strip the .0 we added)
-$UrlVersion = $Version -replace '\.0$'
-$InstallerUrl = "https://static.keet.io/downloads/$UrlVersion/Keet.msix"
+try {
+ $ReleaseTime = [datetime]::ParseExact($LatestRelease.ReleaseTime, 'dd-MMM-yyyy HH:mm', [System.Globalization.CultureInfo]::InvariantCulture)
+} catch {
+ $_ | Out-Host
+ $this.Log($_, 'Warning')
+}
-# Try to get SHA256 hash
$InstallerSha256 = $null
try {
- $Response = Invoke-WebRequest -Uri $InstallerUrl -Method Head -ErrorAction SilentlyContinue
- if ($Response.StatusCode -eq 200) {
- # Download the file to compute hash (this can be slow)
- $TempFile = [System.IO.Path]::GetTempFileName()
- Invoke-WebRequest -Uri $InstallerUrl -OutFile $TempFile -ErrorAction SilentlyContinue
- $InstallerSha256 = (Get-FileHash -Path $TempFile -Algorithm SHA256).Hash
- Remove-Item -Path $TempFile -Force
+ $Checksums = Invoke-WebRequest -Uri "${Prefix}${UrlVersion}/checksums.txt" | Read-ResponseContent
+ $ChecksumMatch = [regex]::Match($Checksums, '(?im)^(?[a-f0-9]{64})\s+\*?Keet\.msix$')
+ if ($ChecksumMatch.Success) {
+ $InstallerSha256 = $ChecksumMatch.Groups['Sha256'].Value.ToUpperInvariant()
+ } else {
+ $this.Log("No SHA256 checksum found for version ${UrlVersion}", 'Warning')
}
} catch {
- Write-Warning "Could not compute hash for installer: $_"
+ $_ | Out-Host
+ $this.Log($_, 'Warning')
+}
+
+if (-not $InstallerSha256) {
+ $InstallerFile = Get-TempFile -Uri $InstallerUrl
+ $InstallerSha256 = (Get-FileHash -Path $InstallerFile -Algorithm SHA256).Hash
+ Remove-Item -Path $InstallerFile -Force -ErrorAction 'Continue' -ProgressAction 'SilentlyContinue'
}
# Set version
-$this.CurrentState.Version = $Version
+$this.CurrentState.Version = "${UrlVersion}.0"
# Add installer information for x64
$InstallerInfo1 = [ordered]@{