Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6f6413e
ci(installer): probe the EDB 17 installer on a runner
mrcsin Oct 19, 2026
0b7eebd
ci(installer): wait for the EDB uninstaller
mrcsin Oct 19, 2026
e837805
ci(installer): probe EDB password characters
mrcsin Oct 19, 2026
4649439
ci(installer): probe the allowed password set
mrcsin Oct 19, 2026
8110d42
ci(installer): remove the EDB installer probe
mrcsin Oct 19, 2026
085cf8f
docs(installer): record the EDB 17 installer facts
mrcsin Oct 19, 2026
64e66a0
docs(installer): state how initcluster was compared
mrcsin Oct 19, 2026
a8d6995
build(installer): pin and fetch the EDB payload
mrcsin Oct 19, 2026
89cbf7e
build(installer): add the setup skeleton and password checks
mrcsin Oct 19, 2026
8c7c7cc
ci(installer): build the setup and refuse a passwordless run
mrcsin Oct 19, 2026
158ae1b
docs(plans): mark the installer skeleton task done
mrcsin Oct 19, 2026
8d82970
docs(plans): restore LF line endings in the plan
mrcsin Oct 19, 2026
d63ec34
build(installer): detect the PostgreSQL engine state
mrcsin Oct 19, 2026
e485c7e
ci(installer): refuse a registered major other than 17
mrcsin Oct 19, 2026
40b2968
docs(plans): mark the engine state task done
mrcsin Oct 19, 2026
cc8c132
build(installer): install and provision PostgreSQL 17
mrcsin Oct 19, 2026
5ff67d9
ci(installer): provision the runner's PostgreSQL 17
mrcsin Oct 19, 2026
796ae39
docs(plans): mark the provisioning run task done
mrcsin Oct 19, 2026
62e4fc9
build(installer): ask for the passwords interactively
mrcsin Oct 19, 2026
2a8accf
ci(installer): run the full setup case list
mrcsin Oct 19, 2026
5c4b2e3
ci(installer): drop the stale semibase.exe checks
mrcsin Oct 19, 2026
704245c
docs(plans): mark the full CI case list task done
mrcsin Oct 19, 2026
b20a9f8
ci(release): attach the setup to the release
mrcsin Oct 19, 2026
2d30572
docs(plans): mark the release setup task done
mrcsin Oct 19, 2026
f0baae3
docs(plans): mark the acceptance check task done
mrcsin Oct 19, 2026
61daac6
docs(installer): document the setup and its recovery
mrcsin Oct 19, 2026
8fa733b
fix(installer): copy the recovery tool, test all rows
mrcsin Oct 19, 2026
916dccb
fix(release): smoke-run the setup before publishing
mrcsin Oct 19, 2026
9786cae
docs(installer): align the docs with the setup fixes
mrcsin Oct 20, 2026
7ca0ab6
docs(deployment): route a password with a space right
mrcsin Oct 20, 2026
de16426
fix(installer): move setup writes out of C:\DISTR
mrcsin Oct 20, 2026
f72dbc9
fix(installer): refuse a / word Setup does not read
mrcsin Oct 20, 2026
d36434d
refactor(installer): give each setup fact one home
mrcsin Oct 20, 2026
a4f9e1a
refactor(ci): share the installer case helpers
mrcsin Oct 20, 2026
f6cbc10
docs(repo): correct the pin and CI job claims
mrcsin Oct 20, 2026
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
46 changes: 46 additions & 0 deletions .github/actions/build-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Build the setup
description: Fetch the pinned EDB payload, install Inno Setup and compile Installer/Output/SemiBase-Setup.exe

inputs:
app-version:
description: AppVersion; VersionInfoVersion takes its part before the first -, digits and dots only
required: true
semibase-exe:
description: Path of the semibase.exe the setup carries
required: true

runs:
using: composite
steps:
- name: Cache the EDB payload
uses: actions/cache@v6
with:
path: Installer/payload
key: edb-payload-${{ hashFiles('Installer/fetch-postgresql.sh') }}

# shell: bash is Git Bash; a bare bash on the PATH may be WSL's
- name: Fetch the EDB payload
shell: bash
run: bash Installer/fetch-postgresql.sh

# The jrsoftware.org direct download intermittently serves a corrupted file, so winget
# (preinstalled on windows runners) installs it instead. The version is the one the setup's
# command-line and silent-mode behaviour was measured on (docs/architecture/installer.md#inno-setup).
# Machine scope keeps the Program Files (x86) path the next step calls.
- name: Install Inno Setup
shell: pwsh
run: |
winget install --id JRSoftware.InnoSetup --exact --version 6.7.3 --scope machine --silent `
--accept-source-agreements --accept-package-agreements --disable-interactivity
if ($LASTEXITCODE -ne 0) { exit 1 }

- name: Compile the setup
shell: pwsh
env:
APP_VERSION: ${{ inputs.app-version }}
SEMIBASE_EXE: ${{ inputs.semibase-exe }}
run: |
$fileVersion = $env:APP_VERSION.Split('-')[0]
& "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" "/DAppVersion=$env:APP_VERSION" `
"/DFileVersion=$fileVersion" "/DSemibaseExe=$env:SEMIBASE_EXE" Installer\SemiBase.iss
if ($LASTEXITCODE -ne 0) { exit 1 }
86 changes: 86 additions & 0 deletions .github/scripts/installer-case.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Helpers for the setup's end-to-end cases; each installer step dot-sources this file.

$SetupExe = "$env:GITHUB_WORKSPACE\Installer\Output\SemiBase-Setup.exe"
$LogDir = "$env:ProgramFiles\SemiBase Setup\Logs"
$ToolExe = "$env:ProgramFiles\SemiBase Setup\semibase.exe"
$TokenFile = "$env:RUNNER_TEMP\case-passwords.txt"
# The registry key and service of the runner's 17 and of the one the setup installs
$PgInstallation = 'postgresql-x64-17'
$PgService = 'postgresql-x64-17'

function Fail([string] $message) {
Write-Host "::error::$message"
exit 1
}

function New-Token {
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 24 | ForEach-Object { [char] $_ })
}

# Setup is a GUI program, so the call operator would not wait for it. ProcessStartInfo passes the
# argument string as written, so a " reaches Setup; Start-Process would rebuild the string.
function Invoke-Setup([string] $arguments = '') {
$start = [Diagnostics.ProcessStartInfo]::new($SetupExe, "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART $arguments")
$start.UseShellExecute = $false
$since = Get-Date
$setup = [Diagnostics.Process]::Start($start)
$setup.WaitForExit()
$logs = @(Get-ChildItem "$LogDir\*.log" -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -ge $since } | Sort-Object LastWriteTime)
[pscustomobject]@{ ExitCode = $setup.ExitCode; Logs = $logs }
}

# The setup and site logs carry no password by design; the redaction keeps a regression out of
# the public job log
function Write-Redacted([string] $text, [string[]] $tokens = @()) {
foreach ($token in $tokens) { $text = $text.Replace($token, '<REDACTED>') }
Write-Host $text
}

function Write-Logs($run, [string[]] $tokens = @()) {
foreach ($log in $run.Logs) {
Write-Host "--- $($log.Name)"
Write-Redacted "$(Get-Content -Raw $log.FullName)" $tokens
}
}

function Get-SiteLog($run) {
$site = $run.Logs | Where-Object { $_.Name -like 'site-*' } | Select-Object -Last 1
if (-not $site) { Fail 'the run wrote no site log' }
"$(Get-Content -Raw $site.FullName)"
}

# A refusal is exit 7 with its reason as the last line of the newest setup log: LogRefusal
# appends to a log of the same second, so earlier lines may belong to an earlier run
function Assert-Refused($run, [string] $want) {
if ($run.ExitCode -ne 7) { Fail "want exit 7, a refusal from PrepareToInstall, with '$want', got $($run.ExitCode)" }
$log = $run.Logs | Where-Object { $_.Name -like 'setup-*' } | Select-Object -Last 1
$last = if ($log) { Get-Content $log.FullName | Select-Object -Last 1 }
Write-Host "refusal: $last"
if (-not "$last".Contains($want)) { Fail "the setup log does not end with '$want'" }
}

function Assert-NoPostgresService {
if (Get-Service postgresql* -ErrorAction SilentlyContinue) { Fail 'a refused run left a postgresql* service' }
}

function Assert-NothingRegistered {
foreach ($key in 'Installations', 'Services') {
$path = "HKLM:\SOFTWARE\PostgreSQL\$key"
if ((Test-Path $path) -and @(Get-ChildItem $path).Count -ne 0) { Fail "$path is not empty" }
}
}

function Assert-Login([string] $role, [string] $password, [string] $database = 'scada_archive') {
$env:PGPASSWORD = $password
& "$env:PGBIN\psql.exe" -w -h 127.0.0.1 -U $role -d $database -tAc 'SELECT 1' | Out-Null
if ($LASTEXITCODE -ne 0) { Fail "$role cannot log in to $database with the expected password" }
}

# Returns the trimmed output of one statement run as postgres
function Invoke-Super([string] $password, [string] $sql) {
$env:PGPASSWORD = $password
$out = & "$env:PGBIN\psql.exe" -w -h 127.0.0.1 -U postgres -d postgres -qtAc $sql
if ($LASTEXITCODE -ne 0) { Fail "psql as postgres failed on: $sql" }
"$out".Trim()
}
Loading
Loading