diff --git a/.github/workflows/winget2.yml b/.github/workflows/winget2.yml new file mode 100644 index 0000000..a43ea88 --- /dev/null +++ b/.github/workflows/winget2.yml @@ -0,0 +1,157 @@ +name: WinGet2 + +on: + workflow_dispatch: + +jobs: + validate-and-test: + runs-on: windows-2025 + + env: + MANIFEST_DIR: winget + PACKAGE_ID: RcloneUI.RcloneUI + EXPECTED_NAME: Rclone UI + EXPECTED_PUBLISHER: Rclone UI + EXPECTED_VERSION: 2.6.0 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Show winget version + shell: pwsh + run: winget --version + + - name: Validate manifest (schema/rules) + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + if (-not (Test-Path $env:MANIFEST_DIR)) { throw "Missing $env:MANIFEST_DIR" } + + winget validate --manifest $env:MANIFEST_DIR --disable-interactivity --verbose-logs ` + | Tee-Object -FilePath "$pwd\winget-validate.txt" + + - name: Enable local manifest installs + shell: pwsh + run: | + # Required to install directly from a local manifest folder. :contentReference[oaicite:2]{index=2} + winget settings --enable LocalManifestFiles + + - name: Install PowerShell YAML module (for parsing the manifest) + shell: pwsh + run: | + Install-Module -Name powershell-yaml -Force -Scope CurrentUser + + - name: Check installer URLs + verify SHA256 for all installers (x64 & arm64) + shell: pwsh + run: | + Import-Module powershell-yaml + $manifestFiles = Get-ChildItem -Path $env:MANIFEST_DIR -Include *.yml,*.yaml -File -Recurse + if (-not $manifestFiles) { throw "No manifest files found in $env:MANIFEST_DIR" } + + $rows = @() + foreach ($f in $manifestFiles) { + $y = (Get-Content -Raw $f.FullName) | ConvertFrom-Yaml + if ($y.ManifestType -ne 'installer') { continue } + + foreach ($inst in $y.Installers) { + $url = $inst.InstallerUrl + $sha = ($inst.InstallerSha256 ?? $inst.InstallerSha256Hash ?? $inst.Sha256) # tolerate naming + $arch = $inst.Architecture + $scope = $inst.Scope + + $out = Join-Path $env:RUNNER_TEMP ("installer_{0}_{1}{2}" -f $arch, $scope, [IO.Path]::GetExtension($url)) + Write-Host "Downloading $url -> $out" + Invoke-WebRequest -Uri $url -OutFile $out -UseBasicParsing + + $got = (Get-FileHash -Path $out -Algorithm SHA256).Hash.ToLower() + $ok = $got -eq $sha.ToLower() + $rows += [pscustomobject]@{ + File = $out; Architecture=$arch; Scope=$scope; Url=$url; ExpectedSHA=$sha; ActualSHA=$got; Match=$ok + } + if (-not $ok) { throw "SHA256 mismatch for $url" } + } + } + $rows | Format-Table | Out-String | Tee-Object "$pwd\hash-check.txt" + + - name: Matrix install tests (x64 / user & machine) + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + $scopes = @('user','machine') + foreach ($scope in $scopes) { + Write-Host "=== INSTALL TEST scope=$scope (x64) ===" + + # Ensure any previous install is gone for this scope + winget list --id $env:PACKAGE_ID -e | Tee-Object -FilePath "$pwd\winget-list-before-$scope.txt" + winget uninstall --id $env:PACKAGE_ID -e --scope $scope --silent --accept-source-agreements --disable-interactivity --source winget ` + --verbose-logs 2>$null; $true | Out-Null # ignore errors if not installed + # Uninstall flags & scope filtering. :contentReference[oaicite:5]{index=5} + + # Install from the local manifest (requires setting enabled earlier) + winget install --manifest $env:MANIFEST_DIR --scope $scope --architecture x64 ` + --silent --accept-package-agreements --disable-interactivity --verbose-logs ` + | Tee-Object -FilePath "$pwd\winget-install-$scope.txt" + # Local manifest install & options. :contentReference[oaicite:6]{index=6} + + # Post-install: verify presence via winget list + winget list --id $env:PACKAGE_ID -e | Tee-Object -FilePath "$pwd\winget-list-after-$scope.txt" + + # Verify declared AppsAndFeaturesEntries in the registry + if ($scope -eq 'machine') { + $roots = @( + 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall', + 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' + ) + } else { + $roots = @('HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall') + } + + $found = $false + foreach ($root in $roots) { + if (Test-Path $root) { + Get-ChildItem $root | ForEach-Object { + $dispName = (Get-ItemProperty $_.PsPath -ErrorAction SilentlyContinue).DisplayName + $publisher = (Get-ItemProperty $_.PsPath -ErrorAction SilentlyContinue).Publisher + $version = (Get-ItemProperty $_.PsPath -ErrorAction SilentlyContinue).DisplayVersion + if ($dispName -eq $env:EXPECTED_NAME) { + $found = $true + "$scope ARP entry: Name=$dispName Publisher=$publisher Version=$version" ` + | Tee-Object -FilePath "$pwd\arp-$scope.txt" + if ($publisher -ne $env:EXPECTED_PUBLISHER -or $version -ne $env:EXPECTED_VERSION) { + throw "ARP mismatch for $scope. Expected Publisher='$env:EXPECTED_PUBLISHER' Version='$env:EXPECTED_VERSION'. Got Publisher='$publisher' Version='$version'." + } + } + } + } + } + if (-not $found) { throw "ARP entry '$env:EXPECTED_NAME' not found for $scope scope." } + + # Dependency check: Edge WebView2 Runtime present? + winget list --id Microsoft.EdgeWebView2Runtime -e | Tee-Object -FilePath "$pwd\webview2-$scope.txt" + # Quick dependency presence check. :contentReference[oaicite:7]{index=7} + + # Uninstall and verify it’s gone + winget uninstall --id $env:PACKAGE_ID -e --scope $scope --silent --accept-source-agreements --disable-interactivity --source winget ` + --verbose-logs | Tee-Object -FilePath "$pwd\winget-uninstall-$scope.txt" + winget list --id $env:PACKAGE_ID -e | Tee-Object -FilePath "$pwd\winget-list-final-$scope.txt" + } + + # - name: Collect WinGet logs + step outputs + # if: always() + # uses: actions/upload-artifact@v4 + # with: + # name: winget-ci-logs + # path: | + # *.txt + # ${{ env.LOCALAPPDATA }}\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir\*.log + # if-no-files-found: ignore + + - name: CI summary + if: always() + shell: pwsh + run: | + "## WinGet CI Summary`n" | Out-File $env:GITHUB_STEP_SUMMARY -Append + Get-Content "$pwd\winget-validate.txt" -ErrorAction SilentlyContinue | Out-File $env:GITHUB_STEP_SUMMARY -Append + "`n---`nHashes:`n" | Out-File $env:GITHUB_STEP_SUMMARY -Append + Get-Content "$pwd\hash-check.txt" -ErrorAction SilentlyContinue | Out-File $env:GITHUB_STEP_SUMMARY -Append diff --git a/winget/RcloneUI.Rclone-UI.installer.yaml b/winget/RcloneUI.Rclone-UI.installer.yaml index ad26d8b..a08526f 100644 --- a/winget/RcloneUI.Rclone-UI.installer.yaml +++ b/winget/RcloneUI.Rclone-UI.installer.yaml @@ -19,7 +19,7 @@ Installers: - Architecture: x64 Scope: user InstallerUrl: https://github.com/rclone-ui/rclone-ui/releases/download/v2.6.0/Rclone.UI_x64.exe - InstallerSha256: c40ed89dc2f512ff4ed12e1801a75a52c46e8c48c534515cdc0c413a9ccfeaa4 + InstallerSha256: C40ED89DC2F512FF4ED12E1801A75A52C46E8C48C534515CDC0C413A9CCFEAA4 InstallerSwitches: Silent: /S SilentWithProgress: /S @@ -31,7 +31,7 @@ Installers: - Architecture: x64 Scope: machine InstallerUrl: https://github.com/rclone-ui/rclone-ui/releases/download/v2.6.0/Rclone.UI_x64.exe - InstallerSha256: c40ed89dc2f512ff4ed12e1801a75a52c46e8c48c534515cdc0c413a9ccfeaa4 + InstallerSha256: C40ED89DC2F512FF4ED12E1801A75A52C46E8C48C534515CDC0C413A9CCFEAA4 InstallerSwitches: Silent: /S SilentWithProgress: /S @@ -43,7 +43,7 @@ Installers: - Architecture: arm64 Scope: user InstallerUrl: https://github.com/rclone-ui/rclone-ui/releases/download/v2.6.0/Rclone.UI_arm64.exe - InstallerSha256: 69968f8e3b32a42b826ccad56b91972ac8ae659a2682404f3103d31d62df3e0 + InstallerSha256: 69968F8E3B32A42B826CCAD56B91972AC8AE659A2682404F3103D31D62DF3E0 InstallerSwitches: Silent: /S SilentWithProgress: /S @@ -55,7 +55,7 @@ Installers: - Architecture: arm64 Scope: machine InstallerUrl: https://github.com/rclone-ui/rclone-ui/releases/download/v2.6.0/Rclone.UI_arm64.exe - InstallerSha256: 69968f8e3b32a42b826ccad56b91972ac8ae659a2682404f3103d31d62df3e0 + InstallerSha256: 69968F8E3B32A42B826CCAD56B91972AC8AE659A2682404F3103D31D62DF3E0 InstallerSwitches: Silent: /S SilentWithProgress: /S