This guide explains exactly how to produce signed, installable Windows artifacts for TestBuddy and how to configure the CI pipeline to produce release builds and signed installers.
build_windows.ps1/build_windows.bat— build the EXE (PyInstaller) and compile NSIS installer (ifmakensisis available).testbuddy_installer.nsi— NSIS installer script (referencesdist/TestBuddy.exe).- GitHub Actions workflow:
.github/workflows/windows_build.ymlthat:- Installs dependencies
- Runs tests
- Builds EXE and runs NSIS (on Windows runner)
- Generates
CHECKSUMS.txt(SHA256) - Uploads artifacts
- Optionally signs artifacts if signing secrets are present
- Creates a GitHub Release and attaches artifacts
- Windows code signing certificate (PFX) with private key.
- Obtain from a CA (DigiCert, Sectigo, GlobalSign). EV certificates are recommended for broad trust.
- GitHub repo-level secrets (to enable automatic signing):
SIGN_CERT_PFX— base64-encoded contents of the PFX fileSIGN_CERT_PASSWORD— password for the PFX
Run locally and copy the output into the SIGN_CERT_PFX secret value in GitHub:
$bytes = [System.IO.File]::ReadAllBytes('C:\path\to\your-cert.pfx')
$base64 = [Convert]::ToBase64String($bytes)
# Save temporarily
Set-Content -Path C:\tmp\cert.pfx.b64 -Value $base64
# Open the file and copy-paste the single-line content into the repo secret
notepad C:\tmp\cert.pfx.b64Add the PFX password as SIGN_CERT_PASSWORD in GitHub Secrets.
osslsigncode(open-source): used on Windows runner (installed via Chocolatey). Works with PFX.signtool(Microsoft): preferred for EV certs / MS recommended signing. If you prefersigntool, you can modify the workflow to callsigntoolinstead; it requires the Windows SDK or a runner that hassigntool.exeavailable.
- Option A: Push a commit to
mainbranch (workflow runs automatically) - Option B: Run
Build Windowsworkflow manually from the Actions UI (workflow_dispatch)
pyinstallercreatesdist/TestBuddy.exe(one-file, windowed).- NSIS compiles
TestBuddy-Setup.exeifmakensisis available on the runner. CHECKSUMS.txtis produced with SHA256 lines for each artifact.- Optional signing step (if secrets present) produces
*-signed.exevariants. - The release flow creates a tag like
vYYYYMMDD-<run_number>and publishes a Release, attaching artifacts andCHECKSUMS.txt.
- Download artifacts from the workflow run or Release.
- Verify SHA256 matches the values in
CHECKSUMS.txt:Get-FileHash .\TestBuddy-Setup.exe -Algorithm SHA256 Get-Content CHECKSUMS.txt
- Install on a clean VM (Windows 10/11) and verify:
- App launches
- Sessions load
- Export features work (PDF, DOCX, CSV, HTML, Markdown, JSON, TXT)
- Document Intelligence analyze works (with Tesseract installed)
- Uninstall removes program files
- Upload PFX as repo secret as above.
- Modify the workflow step
Optional: Sign artifactsto callsigntool.exe sign /f cert.pfx /p <password> /tr http://timestamp.digicert.com /td sha256 /fd sha256 <file> - On hosted runners,
signtoolmay not be present. You'll need either to install Windows SDK in the runner (adds time), or use a self-hosted Windows runner that hassigntoolinstalled and your signing cert available.
For the most trustworthy signing (EV certs) use signtool.exe on a self-hosted Windows runner that has the Windows SDK installed and signtool available. Steps:
- Provision a secure Windows VM (Azure, AWS, or on-prem).
- Install Windows SDK (contains
signtool.exe). - Securely copy your PFX to the VM (or use an HSM) and protect it; store it in a protected folder accessible only to the runner account.
- Register the VM as a self-hosted runner in GitHub Actions (Repository settings → Actions → Runners → New self-hosted runner).
- Modify the workflow to run the signing step on the self-hosted runner by adding
runs-on: [self-hosted, windows]to the signing job, and callsigntool:
signtool sign /f C:\path\to\cert.pfx /p "PFX_PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "C:\path\to\TestBuddy.exe"- After signing, upload signed artifacts back to the Actions job workspace and attach them to the Release as shown earlier.
Security note: keep your private key secret. Prefer using an HSM or Azure Key Vault with a signing proxy rather than storing PFX on disk.
- Sign all binaries and installer before publishing to avoid "Unknown Publisher" warnings.
- Consider using an official code-signing service or HSM for private key security.
- Publish checksums on the website and in the release notes.
- For automated distribution, consider pushing artifacts to a CDN or S3 bucket and use the installer to fetch updates.
If a workflow fails:
- Open the Actions run and expand logs for the failing step.
- For signing issues, ensure the PFX is valid and not password-protected with non-ASCII characters that could break environment handling.
- For NSIS errors, ensure makensis is available and the path to the EXE referenced in
testbuddy_installer.nsimatches the build output.
If you'd like, I can:
- Switch the workflow to use
signtooland/or a self-hosted signing runner. - Add automatic changelog generation using Conventional Commits or
release-drafter. - Add an auto-update server or mechanism.
*** End of guide ***