release-desktop.sh

One-shot pipeline.

8 minmedium

The release script bumps the version, builds the binary + installer, tags git, and uploads everything to GitHub. One command, one new release that the auto-updater finds. Grit scaffolds this as scripts/release-desktop.sh.

The full pipeline

Terminal
$scripts/release-desktop.sh 1.2.3

That runs:

  1. Bump wails.json's productVersion + outputfilename
  2. Bump version.go's AppVersion constant
  3. Regenerate branded NSIS bitmaps from icon.ico
  4. Download + cache the offline WebView2 runtime (first time only)
  5. wails build -nsis -platform windows/amd64 -trimpath -ldflags '-s -w'
  6. Run makensis on the slim variant
  7. Tag v1.2.3 + git push
  8. gh release create with three assets (raw .exe, full installer, slim installer)

Prerequisites

  • bash, jq, python3 on PATH (Git Bash on Windows gives you all)
  • wails CLI
  • makensis — Windows NSIS install
  • gh — GitHub CLI, signed in (gh auth login)
  • powershell.exe on PATH (needed for the bitmap generation step)

Versioning

Semantic versioning:

v1.0.0 Initial release
v1.0.1 Bug fix only
v1.1.0 New feature, backward-compatible
v2.0.0 Breaking change

For internal-only POS apps, you can be looser — many shops just use date-based versions like 2026.06.12. The important rule is that versions sort lexically + the auto-updater recognises a higher value as newer.

Three assets per release

  • Raw .exe (FieldPOS-v1.2.3.exe) — what the auto-updater downloads and swaps. ~15 MB.
  • Full installer (FieldPOS-Setup-v1.2.3.exe) — ~150 MB with bundled WebView2 runtime. Customer-facing.
  • Slim installer (FieldPOS-Setup-Slim-v1.2.3.exe) — ~22 MB, downloads WebView2 online. Easier email attachment.
Always upload the raw .exe. The auto-updater looks for it (not the installer). If you only upload installers, running v1.0 binaries can't find a swap target — the in-app update silently fails.

GitHub Actions alternative

For teams, automate via GitHub Actions instead of running the script locally:

.github/workflows/release.yml
on:
push:
tags: ['v*']
jobs:
release:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: pnpm/action-setup@v2
- run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
- run: choco install nsis -y
- run: scripts/release-desktop.sh ${{ github.ref_name }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Push a tag locally, GitHub Actions runs the same script in CI, the release appears on the Releases page, every running v1 binary sees the new release on its next 6-hour check.

Code signing — optional but worth it

An unsigned .exe shows the Windows SmartScreen warning the first time a customer runs it. A code-signing cert (~$200/year) skips this. Add a signing step to the script:

signtool sign /f cert.pfx /p "$CERT_PWD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 \
"build/bin/FieldPOS-v$VERSION.exe"

Quick check

You forgot to upload the raw .exe — only the installers are in the GitHub release. What happens for users running v1.0?

Try it

For chapter 4's assignment, ship a release:

  1. Install v0.1.0 of your scaffolded app via the installer
  2. Make a small visible change (change a label, add a route)
  3. Run scripts/release-desktop.sh 0.1.1
  4. Confirm v0.1.1 appears on github.com/<you>/<repo>/releases with 3 assets
  5. Open the installed v0.1.0 — the "Update available" banner should appear
  6. Click Install & restart. App relaunches as v0.1.1.

What's next

Final chapter — Branded installers. NSIS deep dive: full vs slim variants, branded MUI bitmaps from your icon.

Spot a typo? Have an idea?

Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled — suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.

Suggest an improvement on GitHub