Skip to content

Commit 71f3251

Browse files
committed
Add Windows Store validation trial workflow
1 parent 77101aa commit 71f3251

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
name: Store Validation Trial
2+
3+
on:
4+
push:
5+
branches:
6+
- codex/store-validation
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
BUILD_CONFIGURATION: Release
14+
BUILD_PLATFORM: x64
15+
DIST_DIR: dist/Q1View-windows-x64
16+
STORE_VERSION: 1.0.16.0
17+
STORE_PUBLISHER: CN=A89D24B3-A271-4AE1-9B9E-BFAE414EB0C6
18+
19+
jobs:
20+
validate:
21+
name: Install, WACK, and capture on Windows
22+
runs-on: windows-2022
23+
timeout-minutes: 60
24+
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v5
28+
29+
- name: Add MSBuild to PATH
30+
uses: microsoft/setup-msbuild@v3
31+
32+
- name: Build applications
33+
shell: pwsh
34+
run: |
35+
msbuild Viewer\Viewer.sln /m /restore /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=$env:BUILD_PLATFORM /p:PlatformToolset=v143
36+
msbuild Comparer\Comparer.sln /m /restore /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=$env:BUILD_PLATFORM /p:PlatformToolset=v143
37+
.\build\Package-Q1View.ps1 `
38+
-Configuration $env:BUILD_CONFIGURATION `
39+
-Platform $env:BUILD_PLATFORM `
40+
-OutputDir $env:DIST_DIR
41+
42+
- name: Build Store submission MSIX
43+
shell: pwsh
44+
run: |
45+
New-Item -ItemType Directory -Force "artifacts\store-submission" | Out-Null
46+
.\build\Package-Q1ViewMsix.ps1 `
47+
-SourceDir $env:DIST_DIR `
48+
-OutputDir "dist" `
49+
-AppVersion $env:STORE_VERSION `
50+
-Publisher $env:STORE_PUBLISHER `
51+
-SkipSigning
52+
Copy-Item "dist\Q1View-windows-x64.msix" "artifacts\store-submission\Q1View-windows-x64.msix"
53+
54+
- name: Create certificate for sideload validation
55+
id: dev_cert
56+
shell: pwsh
57+
run: |
58+
New-Item -ItemType Directory -Force "artifacts\validation" | Out-Null
59+
$cert = New-SelfSignedCertificate `
60+
-Type Custom `
61+
-Subject "CN=Q1ViewValidation" `
62+
-KeyUsage DigitalSignature `
63+
-FriendlyName "Q1View Store validation" `
64+
-CertStoreLocation "Cert:\CurrentUser\My" `
65+
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3")
66+
$cerPath = Join-Path $PWD "artifacts\validation\Q1ViewValidation.cer"
67+
Export-Certificate -Cert $cert -FilePath $cerPath | Out-Null
68+
Import-Certificate -FilePath $cerPath -CertStoreLocation "Cert:\LocalMachine\TrustedPeople" | Out-Null
69+
"thumbprint=$($cert.Thumbprint)" | Out-File $env:GITHUB_OUTPUT -Encoding utf8 -Append
70+
71+
- name: Build signed validation MSIX
72+
shell: pwsh
73+
run: |
74+
.\build\Package-Q1ViewMsix.ps1 `
75+
-SourceDir $env:DIST_DIR `
76+
-OutputDir "dist" `
77+
-AppVersion $env:STORE_VERSION `
78+
-Publisher "CN=Q1ViewValidation" `
79+
-CertificateThumbprint "${{ steps.dev_cert.outputs.thumbprint }}"
80+
Copy-Item "dist\Q1View-windows-x64.msix" "artifacts\validation\Q1View-validation.msix"
81+
Get-AuthenticodeSignature "artifacts\validation\Q1View-validation.msix" |
82+
Format-List * | Out-File "artifacts\validation\signature.txt"
83+
84+
- name: Install package and record identity
85+
shell: pwsh
86+
run: |
87+
Add-AppxPackage -Path "artifacts\validation\Q1View-validation.msix"
88+
$pkg = Get-AppxPackage -Name "KyuwonKim.Q1View"
89+
if (-not $pkg) {
90+
throw "The installed Q1View validation package was not found."
91+
}
92+
$pkg | Format-List Name, PackageFullName, PackageFamilyName, InstallLocation, Status |
93+
Out-File "artifacts\validation\installed-package.txt"
94+
95+
- name: Prepare screenshot input images
96+
shell: pwsh
97+
run: |
98+
choco install imagemagick.app --no-progress --yes
99+
New-Item -ItemType Directory -Force "artifacts\screenshots\input" | Out-Null
100+
$magick = (Get-Command magick.exe -ErrorAction Stop).Source
101+
& $magick "docs\images\viewer-video.webp" -crop "960x540+100+108" +repage "artifacts\screenshots\input\reference.png"
102+
& $magick "artifacts\screenshots\input\reference.png" -quality 72 "artifacts\screenshots\input\encoded.jpg"
103+
if ($LASTEXITCODE -ne 0) {
104+
throw "Failed to make screenshot input images."
105+
}
106+
107+
- name: Capture installed application windows
108+
continue-on-error: true
109+
shell: pwsh
110+
run: |
111+
New-Item -ItemType Directory -Force "artifacts\screenshots" | Out-Null
112+
choco install qres --no-progress --yes
113+
$qres = Get-Command QRes.exe -ErrorAction SilentlyContinue
114+
if ($qres) {
115+
& $qres.Source /x:1920 /y:1080
116+
}
117+
118+
Add-Type -AssemblyName System.Drawing
119+
Add-Type -AssemblyName System.Windows.Forms
120+
Add-Type @"
121+
using System;
122+
using System.Runtime.InteropServices;
123+
public static class Q1WindowTools {
124+
[DllImport("user32.dll")]
125+
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
126+
}
127+
"@
128+
129+
$pkg = Get-AppxPackage -Name "KyuwonKim.Q1View"
130+
$reference = (Resolve-Path "artifacts\screenshots\input\reference.png").Path
131+
$encoded = (Resolve-Path "artifacts\screenshots\input\encoded.jpg").Path
132+
133+
function Capture-AppWindow([string]$exeName, [string]$arguments, [string]$destination) {
134+
$exePath = Join-Path $pkg.InstallLocation $exeName
135+
$process = Start-Process -FilePath $exePath -ArgumentList $arguments -PassThru
136+
try {
137+
foreach ($attempt in 1..20) {
138+
Start-Sleep -Milliseconds 500
139+
$process.Refresh()
140+
if ($process.HasExited) {
141+
throw "$exeName exited before its window could be captured."
142+
}
143+
if ($process.MainWindowHandle -ne 0) {
144+
break
145+
}
146+
}
147+
if ($process.MainWindowHandle -eq 0) {
148+
throw "No visible window was created for $exeName."
149+
}
150+
[Q1WindowTools]::ShowWindowAsync($process.MainWindowHandle, 3) | Out-Null
151+
Start-Sleep -Seconds 3
152+
153+
$bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
154+
"$exeName primary screen: $($bounds.Width)x$($bounds.Height)" |
155+
Out-File "artifacts\screenshots\display.txt" -Append
156+
if ($bounds.Width -lt 1366 -or $bounds.Height -lt 768) {
157+
throw "Screen resolution $($bounds.Width)x$($bounds.Height) is below Store screenshot minimum."
158+
}
159+
$bitmap = New-Object System.Drawing.Bitmap($bounds.Width, $bounds.Height)
160+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
161+
try {
162+
$graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
163+
$bitmap.Save($destination, [System.Drawing.Imaging.ImageFormat]::Png)
164+
}
165+
finally {
166+
$graphics.Dispose()
167+
$bitmap.Dispose()
168+
}
169+
}
170+
finally {
171+
if (-not $process.HasExited) {
172+
Stop-Process -Id $process.Id -Force
173+
}
174+
}
175+
}
176+
177+
Capture-AppWindow "Viewer.exe" "`"$reference`"" "artifacts\screenshots\viewer.png"
178+
Capture-AppWindow "Comparer.exe" "`"$reference|$encoded`"" "artifacts\screenshots\comparer.png"
179+
180+
- name: Uninstall smoke-tested package
181+
shell: pwsh
182+
run: |
183+
$pkg = Get-AppxPackage -Name "KyuwonKim.Q1View"
184+
if (-not $pkg) {
185+
throw "Q1View package disappeared before uninstall testing."
186+
}
187+
Remove-AppxPackage -Package $pkg.PackageFullName
188+
if (Get-AppxPackage -Name "KyuwonKim.Q1View") {
189+
throw "Q1View package was still installed after Remove-AppxPackage."
190+
}
191+
"Package installed and uninstalled cleanly." |
192+
Out-File "artifacts\validation\install-uninstall-result.txt"
193+
194+
- name: Run Windows App Certification Kit
195+
continue-on-error: true
196+
timeout-minutes: 30
197+
shell: pwsh
198+
run: |
199+
$appCert = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\App Certification Kit" `
200+
-Filter appcert.exe -Recurse -ErrorAction SilentlyContinue |
201+
Select-Object -First 1
202+
if (-not $appCert) {
203+
throw "appcert.exe was not found on the Windows runner."
204+
}
205+
"Using WACK: $($appCert.FullName)" | Out-File "artifacts\validation\wack-command.txt"
206+
& $appCert.FullName reset
207+
& $appCert.FullName test `
208+
-appxpackagepath (Resolve-Path "artifacts\validation\Q1View-validation.msix").Path `
209+
-reportoutputpath (Join-Path $PWD "artifacts\validation\WACKReport.xml")
210+
if ($LASTEXITCODE -ne 0) {
211+
throw "WACK failed with exit code $LASTEXITCODE. See WACKReport.xml."
212+
}
213+
214+
- name: Upload validation output
215+
if: always()
216+
uses: actions/upload-artifact@v6
217+
with:
218+
name: Q1View-store-validation-trial
219+
path: artifacts/

0 commit comments

Comments
 (0)