Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ jobs:
with:
shared-key: ci-shared
- run: cargo fmt --all --check
- name: Test Store submission preparation
shell: pwsh
run: .\scripts\ci\test-store-submission-preparation.ps1
- run: cargo test --manifest-path rust/Cargo.toml
- run: cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings

Expand Down
9 changes: 9 additions & 0 deletions rust/installer/codexbar.iss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ DefaultDirName={localappdata}\Programs\Ceiling
DefaultGroupName=Ceiling
DisableProgramGroupPage=yes
DisableDirPage=auto
DisableStartupPrompt=yes
PrivilegesRequired=lowest
UsePreviousAppDir=yes
CloseApplications=yes
Expand Down Expand Up @@ -209,6 +210,14 @@ begin
Result := NeedsVCRedistRestart or NeedsWebView2Restart;
end;

function GetCustomSetupExitCode(): Integer;
begin
if NeedRestart() then
Result := 3010
else
Result := 0;
end;

function CanLaunchCeiling(): Boolean;
begin
Result := not NeedsVCRedistRestart and not NeedsWebView2Restart;
Expand Down
79 changes: 79 additions & 0 deletions scripts/ci/test-store-submission-preparation.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#Requires -Version 5.1

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$tempRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("ceiling-store-test-" + [guid]::NewGuid())
$currentPath = Join-Path $tempRoot "current.json"
$preparedPath = Join-Path $tempRoot "prepared.json"
$missingParametersPath = Join-Path $tempRoot "missing-parameters.json"
$missingParametersPreparedPath = Join-Path $tempRoot "missing-parameters-prepared.json"
$installerUrl = "https://downloads.ceiling.win/releases/v1.5.21/Ceiling-1.5.21-Store-Setup.exe"
$expectedParameters = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART"

try {
New-Item -ItemType Directory -Path $tempRoot | Out-Null
@{
Packages = @(
@{
PackageUrl = "https://downloads.ceiling.win/releases/v1.5.19/Ceiling-1.5.19-Store-Setup.exe"
Languages = @("en-us")
Architectures = @("X64")
IsSilentInstall = $false
InstallerParameters = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /RESTARTEXITCODE=3010"
PackageType = "exe"
}
)
} | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $currentPath -Encoding utf8

& (Join-Path $repoRoot "scripts\prepare-store-submission.ps1") `
-CurrentPackagePath $currentPath `
-InstallerUrl $installerUrl `
-OutputPath $preparedPath

$prepared = Get-Content -LiteralPath $preparedPath -Raw | ConvertFrom-Json
$package = @($prepared.Packages)[0]
if ($package.PackageUrl -ne $installerUrl) {
throw "Store preparation did not update PackageUrl."
}
if ($package.InstallerParameters -ne $expectedParameters) {
throw "Store preparation did not normalize InstallerParameters."
}
if ($package.InstallerParameters.Length -ne 40) {
throw "Expected 40-character Store installer parameters, got $($package.InstallerParameters.Length)."
}
if ($package.Architectures -ne "X64" -or $package.PackageType -ne "exe") {
throw "Store preparation changed unrelated package metadata."
}

$package.PSObject.Properties.Remove("InstallerParameters")
$prepared | ConvertTo-Json -Depth 10 |
Set-Content -LiteralPath $missingParametersPath -Encoding utf8
& (Join-Path $repoRoot "scripts\prepare-store-submission.ps1") `
-CurrentPackagePath $missingParametersPath `
-InstallerUrl $installerUrl `
-OutputPath $missingParametersPreparedPath
$missingParametersPackage = @(
(Get-Content -LiteralPath $missingParametersPreparedPath -Raw | ConvertFrom-Json).Packages
)[0]
$propertyNames = @($missingParametersPackage.PSObject.Properties.Name)
if ($propertyNames -cnotcontains "InstallerParameters" -or
$propertyNames -ccontains "installerParameters") {
throw "Store preparation added InstallerParameters with unexpected casing."
}

$installerScript = Get-Content -LiteralPath (Join-Path $repoRoot "rust\installer\codexbar.iss") -Raw
if ($installerScript -notmatch '(?m)^DisableStartupPrompt=yes\r?$') {
throw "Installer no longer suppresses the startup prompt internally."
}
if ($installerScript -notmatch '(?m)^function GetCustomSetupExitCode\(\): Integer;\r?$') {
throw "Installer no longer returns 3010 for a successful install requiring restart."
}

Write-Host "Store submission parameters are valid and preserve installer behavior."
} finally {
if (Test-Path -LiteralPath $tempRoot) {
Remove-Item -LiteralPath $tempRoot -Recurse -Force
}
}
1 change: 1 addition & 0 deletions scripts/local-check.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ try {
Invoke-Step "Frontend build" "pnpm" @("--dir", "apps\desktop-tauri", "run", "build")
}
if ($All -or $ReleaseDoctor) {
Invoke-Step "Store submission preparation" "powershell.exe" @("-File", "scripts\ci\test-store-submission-preparation.ps1")
$args = @("-File", "scripts\release-doctor.ps1")
if ($Version) {
$args += @("-Version", $Version)
Expand Down
28 changes: 27 additions & 1 deletion scripts/prepare-store-submission.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ param(
[string]$InstallerUrl,

[Parameter(Mandatory = $true)]
[string]$OutputPath
[string]$OutputPath,

[ValidateLength(1, 40)]
[string]$InstallerParameters = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART"
)

Set-StrictMode -Version Latest
Expand Down Expand Up @@ -45,6 +48,18 @@ if (-not $packageUrlProperty) {

$packageUrlProperty.Value = $InstallerUrl

# Partner Center caps InstallerParameters at 40 characters. Startup-prompt
# suppression and the 3010 restart exit code live in codexbar.iss, so this
# command keeps the Store install fully silent without exceeding that limit.
$installerParametersProperty = $packages[0].PSObject.Properties |
Where-Object { $_.Name -ieq "installerParameters" } |
Select-Object -First 1
if ($installerParametersProperty) {
$installerParametersProperty.Value = $InstallerParameters
} else {
$packages[0] | Add-Member -NotePropertyName "InstallerParameters" -NotePropertyValue $InstallerParameters
}
Comment thread
tsouth89 marked this conversation as resolved.

$outputDirectory = Split-Path -Parent $OutputPath
if ($outputDirectory -and -not (Test-Path -LiteralPath $outputDirectory)) {
New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null
Expand All @@ -63,4 +78,15 @@ if ($preparedPackageUrlProperty.Value -ne $InstallerUrl) {
throw "Prepared Microsoft Store submission does not contain the expected installer URL."
}

$preparedInstallerParametersProperty = @($preparedPackagesProperty.Value)[0].PSObject.Properties |
Where-Object { $_.Name -ieq "installerParameters" } |
Select-Object -First 1
if (-not $preparedInstallerParametersProperty -or
$preparedInstallerParametersProperty.Value -ne $InstallerParameters) {
throw "Prepared Microsoft Store submission does not contain the expected installer parameters."
}
if ($preparedInstallerParametersProperty.Value.Length -gt 40) {
throw "Prepared Microsoft Store installer parameters exceed Partner Center's 40-character limit."
}

Write-Host "Prepared Microsoft Store package update for $InstallerUrl"
Loading