From 54e1867bfc303f631b8cd03b3f3d513adff2b9ab Mon Sep 17 00:00:00 2001 From: IgorRachkov <89467086+igor04091968@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:18:39 +0300 Subject: [PATCH] Add installer build script, CI workflow, silent params and optional signing --- .github/workflows/build-installer.yml | 34 +++++++++++++++++++ windows/installer/AWatch-rus-Setup.iss | 36 +++++++++++++++++++++ windows/installer/README-INSTALLER.md | 45 ++++++++++++++++++++------ windows/installer/build-installer.ps1 | 33 +++++++++++++++++++ 4 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/build-installer.yml create mode 100644 windows/installer/build-installer.ps1 diff --git a/.github/workflows/build-installer.yml b/.github/workflows/build-installer.yml new file mode 100644 index 0000000..8ff6009 --- /dev/null +++ b/.github/workflows/build-installer.yml @@ -0,0 +1,34 @@ +name: Build Windows installer + +on: + workflow_dispatch: + push: + paths: + - 'windows/**' + - '.github/workflows/build-installer.yml' + +jobs: + build: + runs-on: windows-latest + env: + SIGNTOOL_CMD: ${{ secrets.SIGNTOOL_CMD }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Inno + shell: pwsh + run: | + choco install innosetup --no-progress -y + + - name: Build installer + shell: pwsh + run: | + ./windows/installer/build-installer.ps1 + + - name: Upload Setup.exe artifact + uses: actions/upload-artifact@v4 + with: + name: awatch-rus-setup + path: windows/installer/output/*.exe + if-no-files-found: error diff --git a/windows/installer/AWatch-rus-Setup.iss b/windows/installer/AWatch-rus-Setup.iss index aa90e52..cb65a56 100644 --- a/windows/installer/AWatch-rus-Setup.iss +++ b/windows/installer/AWatch-rus-Setup.iss @@ -23,6 +23,8 @@ Compression=lzma2 SolidCompression=yes WizardStyle=modern SetupLogging=yes +; Optional production code signing. Configure SIGNTOOL_CMD in CI/local env +SignTool=byparam $q$zSIGNTOOL_CMD $f$q DisableWelcomePage=no AllowNoIcons=yes UninstallDisplayIcon={app}\tools\validate-deployment.ps1 @@ -72,6 +74,11 @@ var AfkCheck: TNewCheckBox; WindowCheck: TNewCheckBox; +procedure ApplyCmdParamIfPresent(const ParamName: string; Edit: TEdit); +forward; +procedure ApplyCmdBoolIfPresent(const ParamName: string; Check: TNewCheckBox); +forward; + procedure InitializeWizard; begin ConfigPage := CreateCustomPage(wpSelectTasks, @@ -131,6 +138,35 @@ begin WindowCheck.Top := ScaleY(224); WindowCheck.Caption := 'Enable Window watcher'; WindowCheck.Checked := True; + ApplyCmdParamIfPresent('SERVERHOST', ServerHostEdit); + ApplyCmdParamIfPresent('SERVERPORT', ServerPortEdit); + ApplyCmdParamIfPresent('DOMAIN', DomainEdit); + ApplyCmdParamIfPresent('USERS', UsersEdit); + ApplyCmdParamIfPresent('INSTALLROOT', InstallRootEdit); + ApplyCmdParamIfPresent('STATEROOT', StateRootEdit); + ApplyCmdBoolIfPresent('AFKENABLED', AfkCheck); + ApplyCmdBoolIfPresent('WINDOWENABLED', WindowCheck); +end; + + +procedure ApplyCmdParamIfPresent(const ParamName: string; Edit: TEdit); +var + V: string; +begin + V := ExpandConstant('{param:' + ParamName + '|}'); + if Trim(V) <> '' then + Edit.Text := V; +end; + +procedure ApplyCmdBoolIfPresent(const ParamName: string; Check: TNewCheckBox); +var + V: string; +begin + V := Lowercase(Trim(ExpandConstant('{param:' + ParamName + '|}'))); + if (V = '1') or (V = 'true') or (V = 'yes') then + Check.Checked := True + else if (V = '0') or (V = 'false') or (V = 'no') then + Check.Checked := False; end; function NextButtonClick(CurPageID: Integer): Boolean; diff --git a/windows/installer/README-INSTALLER.md b/windows/installer/README-INSTALLER.md index 52f17a1..1f08c94 100644 --- a/windows/installer/README-INSTALLER.md +++ b/windows/installer/README-INSTALLER.md @@ -5,20 +5,47 @@ This directory contains a ready-to-build scaffold for a classic Setup.exe instal ## Files - `AWatch-rus-Setup.iss` — Inno Setup script. - `Invoke-AWatchRusInstall.ps1` — wrapper that invokes `deploy-ensemble.ps1` with installer parameters. +- `build-installer.ps1` — one-click local build script for Inno Setup. -## Build -1. Install Inno Setup 6 on Windows build host. -2. Open `AWatch-rus-Setup.iss` in Inno Setup Compiler. -3. Build to produce `output/AWatch-rus-Setup.exe`. +## Local build (one-click) +```powershell +cd .\windows\installer +.\build-installer.ps1 +``` + +Optional custom path to compiler: +```powershell +.\build-installer.ps1 -IsccPath 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' +``` + +## Silent deployment parameters (SCCM/Intune/GPO) +Installer supports command-line parameters: +- `/SERVERHOST=aw.example.local` +- `/SERVERPORT=5600` +- `/DOMAIN=CONTOSO` +- `/USERS=user1,user2` +- `/INSTALLROOT="C:\Program Files\ActivityWatch"` +- `/STATEROOT="C:\ProgramData\ActivityWatch"` +- `/AFKENABLED=true|false` +- `/WINDOWENABLED=true|false` + +Example: +```powershell +AWatch-rus-Setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART ` + /SERVERHOST=aw.example.local /SERVERPORT=5600 /DOMAIN=CONTOSO ` + /USERS=user1,user2 /AFKENABLED=true /WINDOWENABLED=true +``` + +## CI build and optional code signing +A GitHub Actions workflow builds the installer on `windows-latest` and uploads `Setup.exe` as an artifact. + +Optional production signing is enabled via `SignTool=byparam ...` in `.iss` and expects `SIGNTOOL_CMD`. +Set repository secret `SIGNTOOL_CMD` with your full sign command template. ## Behavior - Requires Administrator privileges. - Copies toolkit scripts into `{app}\tools`. -- Collects server/domain/users parameters via wizard page. +- Collects server/domain/users parameters via wizard page (or command-line silent params). - Runs `Invoke-AWatchRusInstall.ps1` -> `deploy-ensemble.ps1`. - Runs validation at the end. - Uninstall step removes `ActivityWatch` scheduled tasks. - -## Notes -- Default publisher URL is a placeholder (`https://example.local/awatch-rus`), replace it. -- For silent enterprise rollout, extend `[Run]` and parse `/SERVERHOST=...` style custom switches if needed. diff --git a/windows/installer/build-installer.ps1 b/windows/installer/build-installer.ps1 new file mode 100644 index 0000000..1c3c420 --- /dev/null +++ b/windows/installer/build-installer.ps1 @@ -0,0 +1,33 @@ +[CmdletBinding()] +param( + [string]$IsccPath = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe", + [string]$IssPath = "$PSScriptRoot\AWatch-rus-Setup.iss", + [switch]$SkipClean +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $IssPath)) { + throw "ISS file not found: $IssPath" +} +if (-not (Test-Path -LiteralPath $IsccPath)) { + throw "ISCC.exe not found: $IsccPath" +} + +$outputDir = Join-Path $PSScriptRoot 'output' +if ((-not $SkipClean) -and (Test-Path -LiteralPath $outputDir)) { + Remove-Item -LiteralPath $outputDir -Recurse -Force +} + +Write-Host "Building installer from: $IssPath" +& $IsccPath $IssPath +if ($LASTEXITCODE -ne 0) { + throw "Inno Setup build failed with code: $LASTEXITCODE" +} + +$artifact = Get-ChildItem -Path $outputDir -Filter '*.exe' -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1 +if (-not $artifact) { + throw "Build finished but no .exe artifact found in: $outputDir" +} + +Write-Host "Installer artifact: $($artifact.FullName)"