Repository navigation
Conversation
SemiBase-Setup.exe needs a script before it can provision anything.
This one carries semibase.exe into {app}, the EDB installer stored
uncompressed for [Code] to extract, and the C:\DISTR log folder.
PrepareToInstall refuses a missing superuser password, a password that
is not printable ASCII, and a superuser password with " or a trailing
\, so a refusal exits 7 before a file is copied. Setup's parser drops
every " from its command line, measured here, so a password parameter
that does not appear verbatim in GetCmdTail is refused as well.
A windows-latest job builds semibase.exe, fetches the cached EDB payload, compiles the setup and runs it with no superuser password: it must exit 7, install nothing and leave postgresql-x64-17 Disabled.
Until now a usable 17 or a clean machine made Setup copy semibase.exe
and exit 0 with nothing provisioned. PrepareToInstall now does the work
before a file is copied, so exit 0 means provisioned.
On a clean machine it runs the EDB installer with an option file under
{tmp}, deleted as soon as EDB returns, and reads the install back from
the registry like any registered 17. It then sets the service to
Automatic, starts it, waits up to 60 s for the port, and runs
semibase site with the passwords in Setup's environment and its output
in C:\DISTR\Logs\SemiBase\site-*.log. A non-zero EDB or site exit, or
a port that stays closed, is a refusal naming the log.
ExtractTemporaryFile matches the DestName of a [Files] entry, measured
with a scratch setup and recorded in installer.md.
Acceptance case 2: Setup with SEMIBASE_SUPER_PASSWORD=root and a writer token in its environment must exit 0, leave postgresql-x64-17 Automatic and let semiplot read semiplot_tags with password semiplot.
An interactive Setup had no way to take the superuser and scada_writer passwords: it refused every run that came without a parameter or a SEMIBASE_* variable. A password page now holds both, prefilled from the same resolution, and PrepareToInstall reads its passwords from the page in every mode, so the checks keep one input. Next on the page refuses an empty superuser field, an unprintable or EDB-breaking password, and an empty writer field when no PostgreSQL is registered; PrepareToInstall still enforces each rule. Under /SILENT Setup simulates Next on the page, so the page check returns True there and silent runs refuse exactly as before.
The setup replaces the bare Windows binary as the commissioning path, and Inno Setup needs a Windows runner while the image needs Linux. The one release job becomes build, installer and release: the Windows binary only feeds the setup, and the release page carries the Linux binary and SemiBase-Setup.exe. "Latest" is still decided once in the build job, and the image is still built and smoke-run before the release and pushed after it.
The setup replaced winget, the bare Windows binary and the manual restart, but every doc still described them. deployment.md now gives the silent command line with Start-Process -Wait, the parameters, the SEMIBASE_* fallbacks, exit codes 0 and 7, the setup and site logs, the three state tables in operator terms, and the recovery section every engine refusal points to, including the manual semibase.exe run. README, CLAUDE.md, the architecture index, provisioning.md and overview.md follow the three-job release and the two release assets; installer.md gains what the setup does.
Every refusal came before the [Files] copy and the release no longer attaches the Windows binary, so a machine where Setup never succeeded had no semibase.exe for the manual recovery, and an offline site could not get one. Every run now copies the carried binary to C:\DISTR\Tools\SemiBase before any check. The EDB password rules (ASCII, ", trailing \) refused a registered 17 whose password reaches semibase byte for byte; they now hold on the fresh-install row only, which also refuses a leading - and leading or trailing spaces nobody measured. An unquoted space in a password parameter no longer passes as its first half. SEMIBASE_WRITER_PASSWORD is always set, so a cleared field does not let the caller's value reset scada_writer. The port probe dials localhost like semibase and tells a failed probe from a closed port; registry values cmd.exe would change are refused; an exception reaches the setup log; the dead [Dirs] entry and the one-read Fresh field are gone. The payload has a fixed name, so the pin lives in the fetch script, and Inno Setup is pinned to the measured 6.7.3 in one composite action. CI now runs every reachable engine row, the remaining password rules, the variable channel on the fresh install with a watch on the option file, a superuser-only re-run, a writer password change under full statement logging, and a wrong registered port.
The release installer job compiled SemiBase-Setup.exe and attached it without ever running it. It now runs the shipped setup once with no password, requires the refusal, and requires the semibase.exe the setup copied out to print the tag. The build steps come from the shared build-setup action, so release and CI compile the same way.
The recovery section points at the copy every run leaves in C:\DISTR\Tools\SemiBase and gives per-state inputs for the manual run; the password rules, refusal rows, pens step, port and writer re-run notes match the setup; CLAUDE.md, installer.md and the plan describe the new CI cases, and the plan records skipped items as skipped.
The example "/SUPERPASSWORD=два слова" lost its quotes in Start-Process and was non-ASCII, so Setup refused it. A password with a space now goes through the variable, or quoted inside the -ArgumentList string, the form measured to reach Setup intact.
Elevated Setup wrote its logs to C:\DISTR\Logs\SemiBase and the
recovery semibase.exe to C:\DISTR\Tools\SemiBase. C:\ gives every
authenticated user Modify on folders made under it and lets any user
create one, so a user could pre-create either path as a junction and
redirect Setup's log writes and CopyFile, or swap the recovery binary
that the deployment guide runs elevated with the superuser password.
A protected DACL on the leaf folder does not help: measured, a user
who can modify the parent renames it and plants a junction in its
place. Locking C:\DISTR and C:\DISTR\Logs would touch folders other
products own, so both now live in {commonpf}\SemiBase Setup, where
only administrators can create or change anything.
ParameterRefusal compared only a prefix of the raw tail, so
/SUPERPASSWORD=Aa1z" arrived as Aa1z and passed, and EDB would create
the cluster with a password other than the one typed. The value must
now end at the end of the tail, at a space, or at a quote closing one
opened right before /NAME=; "/SUPERPASSWORD=two words" still passes.
Files: Installer/SemiBase.iss, .github/scripts/installer-case.ps1,
.github/workflows/ci.yml, docs/deployment.md,
docs/architecture/installer.md,
docs/plans/20261019-windows-installer.md, CLAUDE.md, README.md
An unquoted /SUPERPASSWORD=abc /def reached Setup as two arguments: the value abc matched the command tail verbatim and /def passed the stray-argument check because it starts with /. Inno 6.7.3 ignores an unknown switch, so EDB and site took abc, Setup exited 0 and the typed password did not log in; the same held for /WRITERPASSWORD. Every argument must now be a password parameter or a switch Inno's InitializeSetup loop reads (Setup.MainFunc.pas, SetupLdr.dpr at is-6_7_3), so switches after the passwords still work. The refusal names the argument by number only, since its text may be the rest of a password. A scratch probe confirmed that Inno ignores unknown switches and that the documented forms still pass; installer.md records it. CI case 5 adds both split forms, a /NOCANCEL after the password, and "/SUPERPASSWORD=two words\", which only the whole value carries to the trailing-\ rule. The plan's case 9 line and its ci.yml comment now say what case 6 watches.
The major 17 stood as a literal in the version check, the --expected-major argument and five messages, and the 60 s in the port wait refusal copied PortWaitMilliseconds. A change to either left the other copy wrong. PgMajor now feeds PgInstallation, PgService, PgDataDir and every message, and the refusal reads the constant. The password page derived the writer rule a second time, with its own wording. It now calls FreshInstallRefusal with ProbeMachine False, so the fresh row's rules and texts live in one function. LogPath creates the log folder, which LogRefusal and SiteRefusal each did before. IsSetupSwitch also accepts the two password parameters, so it is now IsKnownArgument. No refusal text changes.
installer-case.ps1 holds the setup's paths, but the diagnostics step spelled out the token file and the log folder again and carried its own redaction loop, and the cases named postgresql-x64-17 per step and ran psql as postgres three different ways. A path or name change had to be made in several places. The helper now holds $PgInstallation, $PgService, Invoke-Super and Write-Redacted, which Write-Logs uses, and the diagnostics step dot-sources it. Shellcheck covers .github/scripts/*.sh too, which it passes with no change, as bash.md asks of every script.
The pin docs said a bump edits the fetch script alone, while installer.md keeps a measured table of the same values. "The Windows job" now names the build job, since installer also runs on Windows. release.yml's image run is the only run of the shipped Linux binary, not of all shipped bytes, since the setup smoke run runs the Windows one. The CLAUDE.md paragraphs this branch edited are rewrapped at 100 columns, and the Windows build job paragraph names the helper and the wider shellcheck.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Commissioning a machine today takes three manual steps: install PostgreSQL with
winget, runsemibase site, restart the service. A suite installer cannot chain that.SemiBase-Setup.exe(Inno Setup) does it in one run. It carries the EDB PostgreSQL 17 installer, pinned by SHA256, installs it when the machine has no PostgreSQL, uses a registered 17 when there is one, refuses every other engine state, then runssemibase site --restart-service. Exit code 0 means provisioned. Passwords reachsemibasethrough the environment, never a command line.Plan:
docs/plans/20261019-windows-installer.md. Stacked on #19.Verification: in progress, task by task. The
installerCI job runs the setup silently onwindows-latest, one case per state the plan lists.