ci: unsigned windows-msi workflow + DUAL-SHIP CI artifact section
Some checks failed
windows-msi / full-msi-unsigned (push) Has been cancelled

GitHub Actions builds full MSI when WiX present; sign step commented (secret names only).
This commit is contained in:
George Lambert 2026-10-14 00:06:41 -04:00
commit 1d6ce81a54
4 changed files with 159 additions and 13 deletions

105
.github/workflows/windows-msi.yml vendored Normal file
View file

@ -0,0 +1,105 @@
# Unsigned full elevated MSI (Product-Full.wxs + build-full-msi.ps1).
# Artifact is NOT Authenticode-signed. Sign step is commented; secret names only.
# See platform/windows/wix/CI-SIGN-NOTARY.md and platform/windows/wix/DUAL-SHIP.md § CI artifact.
name: windows-msi
on:
workflow_dispatch:
push:
paths:
- "platform/windows/**"
- "cmd/**"
- "internal/**"
- "go.mod"
- "go.sum"
- ".github/workflows/windows-msi.yml"
pull_request:
paths:
- "platform/windows/**"
- "cmd/**"
- "internal/**"
- "go.mod"
- "go.sum"
- ".github/workflows/windows-msi.yml"
permissions:
contents: read
jobs:
full-msi-unsigned:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Install WiX Toolset v3
shell: pwsh
run: |
choco install wixtoolset --version 3.14.1 -y --no-progress
$wixBin = "${env:ProgramFiles(x86)}\WiX Toolset v3.14\bin"
if (-not (Test-Path -LiteralPath (Join-Path $wixBin "candle.exe"))) {
# Fallback: any WiX v3.* bin on Program Files
$found = Get-ChildItem -Path "${env:ProgramFiles(x86)}" -Filter "candle.exe" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match 'WiX Toolset' } |
Select-Object -First 1
if ($found) { $wixBin = $found.Directory.FullName }
}
if (-not (Test-Path -LiteralPath (Join-Path $wixBin "candle.exe"))) {
Write-Error "WiX candle.exe not found after install. Full MSI job requires WiX v3."
}
"WIX_BIN=$wixBin" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
"PATH=$wixBin;$env:PATH" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
Write-Host "WiX bin: $wixBin"
& (Join-Path $wixBin "candle.exe") -?
- name: Build full MSI (unsigned)
shell: pwsh
run: |
$candle = Get-Command candle -ErrorAction SilentlyContinue
$light = Get-Command light -ErrorAction SilentlyContinue
if (-not $candle -or -not $light) {
Write-Error "WiX candle/light not on PATH — refusing unsigned MSI build (fail closed)."
}
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\build-full-msi.ps1 -Arch amd64
$msi = Get-ChildItem -Path platform\windows\wix\out -Filter "VeraePrintStamp-windows-*.msi" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if (-not $msi) {
Write-Error "build-full-msi.ps1 did not produce VeraePrintStamp-windows-*.msi under platform/windows/wix/out"
}
Write-Host "MSI: $($msi.FullName) ($([math]::Round($msi.Length/1MB, 2)) MB)"
Get-FileHash -Algorithm SHA256 -Path $msi.FullName | Format-List
"MSI_PATH=$($msi.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
"MSI_NAME=$($msi.Name)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
# --- Future Authenticode (NOT enabled) ---
# Wire only after certs exist in the org secret store. Never commit PFX or passwords.
# Secret / var names (placeholders only — see CI-SIGN-NOTARY.md):
# secrets.WINDOWS_CERT_PFX_BASE64
# secrets.WINDOWS_CERT_PFX_PASSWORD
# secrets.WINDOWS_CERT_THUMBPRINT # optional if cert pre-installed
# vars.WINDOWS_SIGN_TIMESTAMP_URL # RFC 3161 TSA
# secrets.WINDOWS_TRUSTED_SIGNING_* # optional Azure Trusted Signing instead of PFX
# Steps (when live): import PFX → signtool sign EXE + MSI → never upload PFX as artifact.
# - name: Sign MSI + EXEs (Authenticode)
# if: ${{ false }}
# shell: pwsh
# env:
# WINDOWS_CERT_PFX_BASE64: ${{ secrets.WINDOWS_CERT_PFX_BASE64 }}
# WINDOWS_CERT_PFX_PASSWORD: ${{ secrets.WINDOWS_CERT_PFX_PASSWORD }}
# WINDOWS_SIGN_TIMESTAMP_URL: ${{ vars.WINDOWS_SIGN_TIMESTAMP_URL }}
# run: |
# Write-Error "Sign step not enabled — unsigned artifact only."
- name: Upload unsigned MSI artifact
uses: actions/upload-artifact@v4
with:
name: VeraePrintStamp-windows-msi-unsigned
path: platform/windows/wix/out/VeraePrintStamp-windows-*.msi
if-no-files-found: error
retention-days: 14

View file

@ -16,20 +16,22 @@ Repo now includes **authoring/docs scaffolds** for the two commercial gaps that
|----------|------|------------|----------------| |----------|------|------------|----------------|
| **WiX tray presence MSI skeleton** | [`platform/windows/wix/`](../platform/windows/wix/) — `VeraeTrayShortcuts.wxs`, `VeraeTrayShortcutsFragment.wxs`, [`README.md`](../platform/windows/wix/README.md); driver [`scripts/build-tray-msi.ps1`](../platform/windows/scripts/build-tray-msi.ps1) | Non-elevated **per-user** WiX v3 product + shortcut fragment: stages `verae-tray.ps1`, Start Menu `Programs\Verae\Verae Tray.lnk`, Startup `Verae Tray.lnk`. **ProductVersion** wired from `Get-VeraePackageVersion` → `internal/job.HelperVersion` (or `VERSION=` / `-Version`). `build-tray-msi.ps1` runs **candle/light** when present; otherwise prints WiX install tip (exit 0). | Full elevated commercial MSI (printers, Program Files, Authenticode, NSIS parity, CI-signed MSI in `dist/`). No MSI binary without the WiX toolset on the build host. | | **WiX tray presence MSI skeleton** | [`platform/windows/wix/`](../platform/windows/wix/) — `VeraeTrayShortcuts.wxs`, `VeraeTrayShortcutsFragment.wxs`, [`README.md`](../platform/windows/wix/README.md); driver [`scripts/build-tray-msi.ps1`](../platform/windows/scripts/build-tray-msi.ps1) | Non-elevated **per-user** WiX v3 product + shortcut fragment: stages `verae-tray.ps1`, Start Menu `Programs\Verae\Verae Tray.lnk`, Startup `Verae Tray.lnk`. **ProductVersion** wired from `Get-VeraePackageVersion` → `internal/job.HelperVersion` (or `VERSION=` / `-Version`). `build-tray-msi.ps1` runs **candle/light** when present; otherwise prints WiX install tip (exit 0). | Full elevated commercial MSI (printers, Program Files, Authenticode, NSIS parity, CI-signed MSI in `dist/`). No MSI binary without the WiX toolset on the build host. |
| **Menubar notarize checklist** | [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../platform/macos/menubar/NOTARIZE-CHECKLIST.md) | Operator step list: unsigned build → codesign hardened runtime → `ditto` zip → `notarytool` (keychain profile **or** API key placeholders) → staple → `spctl`. No secrets. | Automated sign/notarize in `build-menubar-app.sh`, stapled `.app.zip`/DMG release, or CI keychain import. | | **Menubar notarize checklist** | [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../platform/macos/menubar/NOTARIZE-CHECKLIST.md) | Operator step list: unsigned build → codesign hardened runtime → `ditto` zip → `notarytool` (keychain profile **or** API key placeholders) → staple → `spctl`. No secrets. | Automated sign/notarize in `build-menubar-app.sh`, stapled `.app.zip`/DMG release, or CI keychain import. |
| **Full elevated MSI (StageFull + light)** | [`Product-Full.wxs`](../platform/windows/wix/Product-Full.wxs) + [`scripts/build-full-msi.ps1`](../platform/windows/scripts/build-full-msi.ps1) (+ outline, [`SILENT_PROPS.md`](../platform/windows/wix/SILENT_PROPS.md), [`CI-SIGN-NOTARY.md`](../platform/windows/wix/CI-SIGN-NOTARY.md), [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md)) | Elevated WiX v3 product: perMachine, Feature/ComponentGroups for **bin** (`verae-print.exe` required), **scripts**, **docs**, Start Menu; silent public props; distinct UpgradeCode. `build-full-msi.ps1` creates `StageFull/{bin,scripts}`, copies or Go-builds EXEs, copies scripts/LICENSE/README, stamps **ProductVersion** from `Get-VeraePackageVersion`, runs candle/light → `VeraePrintStamp-windows-*-<version>.msi`. WiX missing → **exit 1** + clear tip. Version defaults on build-windows / build-pkg / NSIS / build-installer aligned to HelperVersion. Commented deferred CA + `InstallExecuteSequence` stubs for `install-printer.ps1` (no binaries required). Dual-ship runbook documents NSIS vs MSI clean-VM gates. | **Not** Authenticode-signed; printer CAs still **commented** (not scheduled/tested); properties not yet honored by live CAs; not Intune-proven; NSIS still primary full install; no live sign/notary CI. | | **Full elevated MSI (StageFull + light)** | [`Product-Full.wxs`](../platform/windows/wix/Product-Full.wxs) + [`scripts/build-full-msi.ps1`](../platform/windows/scripts/build-full-msi.ps1) (+ outline, [`SILENT_PROPS.md`](../platform/windows/wix/SILENT_PROPS.md), [`CI-SIGN-NOTARY.md`](../platform/windows/wix/CI-SIGN-NOTARY.md), [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md)) | Elevated WiX v3 product: perMachine, Feature/ComponentGroups for **bin** (`verae-print.exe` required), **scripts**, **docs**, Start Menu; silent public props; distinct UpgradeCode. `build-full-msi.ps1` creates `StageFull/{bin,scripts}`, copies or Go-builds EXEs, copies scripts/LICENSE/README, stamps **ProductVersion** from `Get-VeraePackageVersion`, runs candle/light → `VeraePrintStamp-windows-*-<version>.msi`. WiX missing → **exit 1** + clear tip. Version defaults on build-windows / build-pkg / NSIS / build-installer aligned to HelperVersion. Commented deferred CA + `InstallExecuteSequence` stubs for `install-printer.ps1` (no binaries required). Dual-ship runbook documents NSIS vs MSI clean-VM gates. | **Not** Authenticode-signed; printer CAs still **commented** (not scheduled/tested); properties not yet honored by live CAs; not Intune-proven; NSIS still primary full install; CI builds **unsigned** MSI only (sign step not live). |
| **CI unsigned full MSI** | [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml) + DUAL-SHIP § CI artifact | `windows-latest`: install WiX v3 → `build-full-msi.ps1` → upload artifact `VeraePrintStamp-windows-msi-unsigned`. Future Authenticode secret **names** only in workflow comments / CI-SIGN-NOTARY. | No live `signtool`; no certs in git; not a production download channel. |
### Issue 1 — what landed vs still open ### Issue 1 — what landed vs still open
| Done (advanced) | Still left (Issue 1 commercial) | | Done (advanced) | Still left (Issue 1 commercial) |
|-----------------|----------------------------------| |-----------------|----------------------------------|
| `Product-Full.wxs` File components match StageFull; candle/light-ready | **Uncomment + test** printer deferred CAs on clean VM (DUAL-SHIP VM C); parity with NSIS | | `Product-Full.wxs` File components match StageFull; candle/light-ready | **Uncomment + test** printer deferred CAs on clean VM (DUAL-SHIP VM C); parity with NSIS |
| `build-full-msi.ps1` StageFull + ProductVersion + exit codes | Live CI: signtool / Trusted Signing on MSI + EXEs (**not shipped**) | | `build-full-msi.ps1` StageFull + ProductVersion + exit codes | Live CI: **signtool / Trusted Signing** on MSI + EXEs (workflow sign step commented; secret names only) |
| `CI-SIGN-NOTARY.md` GHA/Forgejo draft (secret **names** only) | Live notarytool staple on macOS runners; clean-VM Gatekeeper proof | | `CI-SIGN-NOTARY.md` GHA/Forgejo draft (secret **names** only) | Live notarytool staple on macOS runners; clean-VM Gatekeeper proof |
| `SILENT_PROPS.md` msiexec one-liner + exit codes for full MSI | Properties honored by **scheduled** CAs (config write, skip printers/key) | | `SILENT_PROPS.md` msiexec one-liner + exit codes for full MSI | Properties honored by **scheduled** CAs (config write, skip printers/key) |
| HelperVersion path on build-windows / build-pkg / NSIS / build-installer / full MSI | Dual-ship **clean-VM validation** then thin NSIS; Intune silent smoke | | HelperVersion path on build-windows / build-pkg / NSIS / build-installer / full MSI | Dual-ship **clean-VM validation** then thin NSIS; Intune silent smoke |
| Commented CA + `InstallExecuteSequence` stubs (`install-printer` schedule) | Publish 0.3.6 download blobs + refresh `DOWNLOADS-MANIFEST` checksums | | Commented CA + `InstallExecuteSequence` stubs (`install-printer` schedule) | Publish 0.3.6 download blobs + refresh `DOWNLOADS-MANIFEST` checksums |
| [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md) NSIS+MSI side-by-side runbook | macOS menubar automated notarize (checklist exists; script default still unsigned) | | [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md) NSIS+MSI side-by-side + **CI artifact** section | macOS menubar automated notarize (checklist exists; script default still unsigned) |
| Site product string → **0.3.6**; manifest header notes HelperVersion vs last-published 0.3.2 | Do **not** claim Authenticode / notary / dual-ship complete | | Site product string → **0.3.6**; manifest header notes HelperVersion vs last-published 0.3.2 | Do **not** claim Authenticode / notary / dual-ship complete |
| [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml) unsigned MSI on `windows-latest` + artifact upload | Wire org secrets and enable sign step; publish signed assets to site |
**Still use for day-to-day presence (no WiX / no Apple certs):** **Still use for day-to-day presence (no WiX / no Apple certs):**
Windows `scripts/build-tray-startmenu.ps1` + `install-tray-startup.ps1`; macOS `verae-print menubar --install` / unsigned `build-menubar-app.sh`. Full product install remains NSIS (`installer-windows.nsi`) and macOS `pkg/build-pkg.sh`. Optional: `build-tray-msi.ps1` (WiX tip exit 0); `build-full-msi.ps1` (needs WiX; exit 1 if missing). Windows `scripts/build-tray-startmenu.ps1` + `install-tray-startup.ps1`; macOS `verae-print menubar --install` / unsigned `build-menubar-app.sh`. Full product install remains NSIS (`installer-windows.nsi`) and macOS `pkg/build-pkg.sh`. Optional: `build-tray-msi.ps1` (WiX tip exit 0); `build-full-msi.ps1` (needs WiX; exit 1 if missing).
@ -63,7 +65,8 @@ Related but out of scope for “done” above (still backlog-adjacent): Linux `.
| WiX-free Start Menu stub | [`platform/windows/scripts/build-tray-startmenu.ps1`](../platform/windows/scripts/build-tray-startmenu.ps1) | Explicitly “future MSI can supersede” | | WiX-free Start Menu stub | [`platform/windows/scripts/build-tray-startmenu.ps1`](../platform/windows/scripts/build-tray-startmenu.ps1) | Explicitly “future MSI can supersede” |
| **WiX tray presence skeleton** (per-user, non-elevated) | [`platform/windows/wix/`](../platform/windows/wix/) + [`scripts/build-tray-msi.ps1`](../platform/windows/scripts/build-tray-msi.ps1) | **Scaffold shipped** — ProductVersion ← HelperVersion; candle/light when present, else WiX tip; not full product MSI | | **WiX tray presence skeleton** (per-user, non-elevated) | [`platform/windows/wix/`](../platform/windows/wix/) + [`scripts/build-tray-msi.ps1`](../platform/windows/scripts/build-tray-msi.ps1) | **Scaffold shipped** — ProductVersion ← HelperVersion; candle/light when present, else WiX tip; not full product MSI |
| **WiX full elevated MSI** (StageFull driver) | [`Product-Full.wxs`](../platform/windows/wix/Product-Full.wxs) + [`scripts/build-full-msi.ps1`](../platform/windows/scripts/build-full-msi.ps1) | **Authoring + stage/light path** — MSI when WiX present; unsigned; printer CAs commented stubs; dual-ship NSIS | | **WiX full elevated MSI** (StageFull driver) | [`Product-Full.wxs`](../platform/windows/wix/Product-Full.wxs) + [`scripts/build-full-msi.ps1`](../platform/windows/scripts/build-full-msi.ps1) | **Authoring + stage/light path** — MSI when WiX present; unsigned; printer CAs commented stubs; dual-ship NSIS |
| **Dual-ship runbook** | [`wix/DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md) | **Docs** — NSIS + MSI clean-VM matrix; thin-NSIS exit criteria | | **CI unsigned full MSI** | [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml) | **Live workflow** — WiX install → `build-full-msi.ps1` → unsigned artifact; sign step commented (secret names only) |
| **Dual-ship runbook** | [`wix/DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md) | **Docs** — NSIS + MSI clean-VM matrix; CI artifact section; thin-NSIS exit criteria |
| Shared version helper | [`platform/windows/scripts/common.ps1`](../platform/windows/scripts/common.ps1) `Get-VeraePackageVersion` | Aligns tray/full MSI/NSIS drivers with `HelperVersion` | | Shared version helper | [`platform/windows/scripts/common.ps1`](../platform/windows/scripts/common.ps1) `Get-VeraePackageVersion` | Aligns tray/full MSI/NSIS drivers with `HelperVersion` |
| End-user Windows readme | [`platform/windows/README-WINDOWS.txt`](../platform/windows/README-WINDOWS.txt), [`README.txt`](../platform/windows/README.txt) | Documents NSIS flow; states **no elevated MSI** for tray | | End-user Windows readme | [`platform/windows/README-WINDOWS.txt`](../platform/windows/README-WINDOWS.txt), [`README.txt`](../platform/windows/README.txt) | Documents NSIS flow; states **no elevated MSI** for tray |
| Packaging policy doc | [PACKAGING.md](PACKAGING.md) | “**No elevated MSI**” for tray presence by design | | Packaging policy doc | [PACKAGING.md](PACKAGING.md) | “**No elevated MSI**” for tray presence by design |
@ -84,18 +87,19 @@ NSIS product already covers much of the *install experience* (files under Progra
| **Custom actions parity with NSIS** | Printers, scheduled helper, per-user key | Port `install-printer.ps1`, helper registration into deferred/impersonated CAs (stubs commented in Product-Full) | | **Custom actions parity with NSIS** | Printers, scheduled helper, per-user key | Port `install-printer.ps1`, helper registration into deferred/impersonated CAs (stubs commented in Product-Full) |
| **Per-user vs per-machine story** | Tray is user-level today; MSI is typically machine | Machine full MSI + optional per-user tray MSI (both authored; product decision open) | | **Per-user vs per-machine story** | Tray is user-level today; MSI is typically machine | Machine full MSI + optional per-user tray MSI (both authored; product decision open) |
| **Version drift in build scripts** | **Largely fixed** — HelperVersion path on build-windows, build-full-msi, build-pkg, build-installer, NSIS fallbacks **0.3.6**; site index product string **0.3.6** | Keep smoke failing on new hard-coded older defaults; `DOWNLOADS-MANIFEST` still checksums **last-published 0.3.2** blobs until release upload | | **Version drift in build scripts** | **Largely fixed** — HelperVersion path on build-windows, build-full-msi, build-pkg, build-installer, NSIS fallbacks **0.3.6**; site index product string **0.3.6** | Keep smoke failing on new hard-coded older defaults; `DOWNLOADS-MANIFEST` still checksums **last-published 0.3.2** blobs until release upload |
| **CI job that builds + signs MSI** | Reproducible release | Windows runner: go test/build → WiX → signtool → upload + checksums (**not live**) | | **CI job that builds + signs MSI** | Reproducible release | **Unsigned build live** (`.github/workflows/windows-msi.yml`); signtool / Trusted Signing still **not live** (secret names only) |
| **MSIX / Print Support App** (later) | Modern print path in original spec | Explicitly **deferred** unless enterprise asks; not blocking first MSI | | **MSIX / Print Support App** (later) | Modern print path in original spec | Explicitly **deferred** unless enterprise asks; not blocking first MSI |
### Windows backlog order (suggested) ### Windows backlog order (suggested)
1. ~~Freeze install surface / WiX file components + StageFull driver~~ (**done**: outline + Product-Full + `build-full-msi.ps1`). 1. ~~Freeze install surface / WiX file components + StageFull driver~~ (**done**: outline + Product-Full + `build-full-msi.ps1`).
2. ~~Dual-ship runbook + commented printer CA schedule stubs~~ (**done**: [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md); Product-Full commented `InstallExecuteSequence`). 2. ~~Dual-ship runbook + commented printer CA schedule stubs~~ (**done**: [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md); Product-Full commented `InstallExecuteSequence`).
3. **Uncomment** + test printer/helper deferred CAs on clean VM (DUAL-SHIP VM C); keep NSIS primary until parity. 3. ~~CI unsigned full MSI workflow + artifact~~ (**done**: [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml); DUAL-SHIP § CI artifact).
4. Authenticode on binaries + MSI (**not shipped** — draft in `CI-SIGN-NOTARY.md` only). 4. **Uncomment** + test printer/helper deferred CAs on clean VM (DUAL-SHIP VM C); keep NSIS primary until parity.
5. Honor silent props in live CAs + Intune sample command line proof. 5. Authenticode on binaries + MSI (**not shipped** — enable commented sign step; secret names in workflow + `CI-SIGN-NOTARY.md`).
6. Publish 0.3.6 artifacts; refresh site `DOWNLOADS-MANIFEST` checksums; keep smoke on HelperVersion drift. 6. Honor silent props in live CAs + Intune sample command line proof.
7. Deprecate or thin NSIS once MSI is the primary download (exit criteria in DUAL-SHIP.md). 7. Publish 0.3.6 artifacts; refresh site `DOWNLOADS-MANIFEST` checksums; keep smoke on HelperVersion drift.
8. Deprecate or thin NSIS once MSI is the primary download (exit criteria in DUAL-SHIP.md).
--- ---

View file

@ -1,8 +1,10 @@
# CI — Authenticode (Windows) + notarytool (macOS) # CI — Authenticode (Windows) + notarytool (macOS)
**Status:** draft sketch only. No live pipeline, no secrets in git. **Status:** unsigned MSI CI is live (`.github/workflows/windows-msi.yml`); **sign/notary steps remain draft**. No secrets in git.
**Audience:** release engineers wiring GitHub Actions or Forgejo Actions. **Audience:** release engineers wiring GitHub Actions or Forgejo Actions.
**Related:** [`Product-Full.wxs`](Product-Full.wxs), [`SILENT_PROPS.md`](SILENT_PROPS.md), **Related:** [`Product-Full.wxs`](Product-Full.wxs), [`SILENT_PROPS.md`](SILENT_PROPS.md),
[`DUAL-SHIP.md`](DUAL-SHIP.md) § CI artifact,
[`.github/workflows/windows-msi.yml`](../../../.github/workflows/windows-msi.yml),
[`docs/COMMERCIAL-INSTALLER-BACKLOG.md`](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md), [`docs/COMMERCIAL-INSTALLER-BACKLOG.md`](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md),
[`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../../macos/menubar/NOTARIZE-CHECKLIST.md), [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../../macos/menubar/NOTARIZE-CHECKLIST.md),
[`platform/macos/pkg/build-pkg.sh`](../../macos/pkg/build-pkg.sh). [`platform/macos/pkg/build-pkg.sh`](../../macos/pkg/build-pkg.sh).
@ -191,9 +193,13 @@ Menubar-only accessory: follow [`NOTARIZE-CHECKLIST.md`](../../macos/menubar/NOT
--- ---
## What this draft does **not** do ## What is live vs what this draft does **not** do
- Enable a workflow file in-repo (operators copy/adapt). **Live:** [`.github/workflows/windows-msi.yml`](../../../.github/workflows/windows-msi.yml) builds an **unsigned** full MSI when WiX is installed on `windows-latest` and uploads the artifact (see DUAL-SHIP § CI artifact).
**Not done:**
- Enable Authenticode `signtool` / Trusted Signing in that workflow (commented; secret **names** only).
- Provide real certs, Team IDs, or TSA URLs. - Provide real certs, Team IDs, or TSA URLs.
- Replace NSIS as primary Windows download. - Replace NSIS as primary Windows download.
- Automate menubar notarization inside `build-menubar-app.sh` (still checklist + backlog). - Automate menubar notarization inside `build-menubar-app.sh` (still checklist + backlog).

View file

@ -168,12 +168,43 @@ Until then: **ship NSIS as primary**; MSI is dual-ship candidate only.
--- ---
## CI artifact (unsigned full MSI)
GitHub Actions workflow [`.github/workflows/windows-msi.yml`](../../../.github/workflows/windows-msi.yml) builds the elevated full MSI on `windows-latest` when WiX v3 (`candle`/`light`) is available:
1. Checkout + Setup Go (`go-version-file: go.mod`).
2. Install WiX Toolset v3 (Chocolatey) and put `candle`/`light` on `PATH`.
3. Run `platform/windows/scripts/build-full-msi.ps1 -Arch amd64` (StageFull → candle/light).
4. Upload **unsigned** artifact `VeraePrintStamp-windows-msi-unsigned` (`platform/windows/wix/out/VeraePrintStamp-windows-*.msi`).
| Fact | Detail |
|------|--------|
| Trigger | `workflow_dispatch`; push/PR on Windows packaging + Go paths |
| Signed? | **No** — artifact is dual-ship candidate only; SmartScreen will warn |
| Use for | Clean-VM B (files-only) smoke; CI proof that authoring lights |
| Not for | Production download, Intune primary, or “MSI replaces NSIS” claims |
**Future sign step (names only — not enabled):** org secrets/vars documented in the workflow comments and [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md):
| Name | Kind |
|------|------|
| `WINDOWS_CERT_PFX_BASE64` | secret |
| `WINDOWS_CERT_PFX_PASSWORD` | secret |
| `WINDOWS_CERT_THUMBPRINT` | secret (optional) |
| `WINDOWS_SIGN_TIMESTAMP_URL` | var |
| `WINDOWS_TRUSTED_SIGNING_*` | secret (optional Azure path) |
Do **not** put PFX bytes or passwords in git. Do not upload the PFX as a workflow artifact. Until sign is live, treat CI MSI like a local `build-full-msi.ps1` output for dual-ship gates only.
---
## Quick links ## Quick links
| Doc | Path | | Doc | Path |
|-----|------| |-----|------|
| Full MSI authoring | [Product-Full.wxs](Product-Full.wxs) | | Full MSI authoring | [Product-Full.wxs](Product-Full.wxs) |
| Stage/light driver | [../scripts/build-full-msi.ps1](../scripts/build-full-msi.ps1) | | Stage/light driver | [../scripts/build-full-msi.ps1](../scripts/build-full-msi.ps1) |
| CI unsigned MSI workflow | [../../../.github/workflows/windows-msi.yml](../../../.github/workflows/windows-msi.yml) |
| Silent properties | [SILENT_PROPS.md](SILENT_PROPS.md) | | Silent properties | [SILENT_PROPS.md](SILENT_PROPS.md) |
| Sign/notary draft | [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md) | | Sign/notary draft | [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md) |
| Commercial backlog | [docs/COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md) | | Commercial backlog | [docs/COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md) |