Compare commits

...

5 Commits

Author SHA1 Message Date
Psychotoxical 7a6215d03d refactor(windows-signing): make signCommand opt-in via override config
Pinning bundle.windows.signCommand in the base tauri.conf.json broke
from-source builds: Tauri tries to invoke a signtool path that only
exists on the maintainer's machine, with a cert thumbprint they don't
have. The build-windows-check CI job already worked around this by
passing --config '{"bundle":{"windows":{"signCommand":null}}}'. If CI
needs that override, every external builder needs it too.

Invert: base config has no signCommand. Local signed builds opt in by
copying tauri.windows.signing.example.json to tauri.windows.signing.json
(gitignored), filling in local values, and running tauri:build:signed-win
which deep-merges the override via --config.

- Remove signCommand from src-tauri/tauri.conf.json
- Add src-tauri/tauri.windows.signing.example.json (template, committed)
- Gitignore src-tauri/tauri.windows.signing.json
- Add npm script tauri:build:signed-win
- Drop the --config signCommand:null workaround from build-windows-check
- Rewrite README signing section to reflect the override flow
2026-05-30 23:35:34 +02:00
Psychotoxical 941562481f docs(changelog): drop stale header banners
The "unsigned Windows installer" warning is no longer accurate now
that the local signing path is in place. The "Version jump 1.34.x
-> 1.40.0" explainer references a v2.0.0 milestone that is no
longer planned and is outdated for a header banner. The safety
investments banner is shortened to reflect that both certificates
are active.
2026-05-30 20:48:21 +02:00
Psychotoxical 2f57417066 ci(release): keep windows compile check, skip sign + upload
Per review feedback: keep a Windows build in the release matrix so
each release still catches Windows-only Rust cfg, Tauri config drift
and NSIS template breakage. The new build-windows-check job has no
releaseId (nothing is uploaded) and overrides signCommand to null
via --config, since the hosted runner has neither the Certum cert
nor SimplySign Desktop.

Signed Windows installers continue to be produced and uploaded
out-of-band by the maintainer. README wording rephrased so it does
not read as a fully automated release pipeline.
2026-05-30 20:14:32 +02:00
Psychotoxical 7c3f0a71fd ci(release): drop windows-latest from matrix (signed locally)
Certum SimplySign Cloud OV requires interactive OTP login via
SimplySign Desktop and cannot be driven from CI. The Windows
installer is built and signed on the maintainer's local machine
and uploaded manually to the GitHub release.

Matrix entry windows-latest removed, job renamed build-macos-windows
-> build-macos, generate-manifest needs[] adjusted. Affects both
release.yml and next.yml since both consume this reusable workflow.

generate-update-manifest.js is unaffected — it already skipped
Windows (the auto-updater is macOS-only until a Windows .sig flow
exists).
2026-05-30 19:47:15 +02:00
Psychotoxical de43ae3d7c feat(windows): enable local code signing via Certum SimplySign cert
Tauri bundle.windows.signCommand calls signtool for the app .exe,
NSIS plugin DLLs, and the final installer in one build pass — all
go out signed with the Certum OV cert.

Object-form signCommand is required: Tauri parses the string form
naively (split_whitespace) and breaks on whitespace in the signtool
path, even with quotes. The object form takes cmd + args[] cleanly.

README adds a maintainer section covering the SimplySign Desktop
prerequisite, the --bundles nsis flag (default 'all' fails because
MSI rejects -dev pre-release identifiers), the signtool verify
command, and a note that target/release/psysonic.exe ends up
unsigned on disk while the installer holds the signed copy.
2026-05-30 19:47:15 +02:00
6 changed files with 91 additions and 9 deletions
+44 -4
View File
@@ -238,7 +238,13 @@ jobs:
});
return data.id;
build-macos-windows:
# Windows is intentionally NOT in this matrix: the Certum SimplySign Cloud cert
# requires interactive OTP login via SimplySign Desktop and cannot be driven from a
# hosted runner. Signed Windows installers are produced and uploaded out-of-band by
# the maintainer (see README). A separate build-windows-check job below still
# compiles a Windows bundle each release to catch breakage early — it just does not
# upload anything.
build-macos:
if: ${{ inputs.build_platform_artifacts }}
needs: create-release
permissions:
@@ -251,8 +257,6 @@ jobs:
args: "--target aarch64-apple-darwin"
- platform: "macos-latest"
args: "--target x86_64-apple-darwin"
- platform: "windows-latest"
args: "--bundles nsis"
runs-on: ${{ matrix.settings.platform }}
steps:
- uses: actions/checkout@v5
@@ -322,9 +326,45 @@ jobs:
cp "${TARBALL}.sig" "Psysonic_${ARCH}.app.tar.gz.sig"
gh release upload "$RELEASE_TAG" "Psysonic_${ARCH}.app.tar.gz.sig" --clobber
# Compile + bundle the Windows NSIS installer on every release to catch breakage
# (Windows-only Rust cfg, Tauri config drift, NSIS template issues). Nothing is
# uploaded — see comment on build-macos for why CI cannot sign Windows. The base
# tauri.conf.json has no signCommand, so this produces an unsigned installer
# naturally; the maintainer signs and uploads locally via npm run tauri:build:signed-win.
build-windows-check:
if: ${{ inputs.build_platform_artifacts }}
needs: create-release
permissions:
contents: read
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
with:
ref: ${{ needs.create-release.outputs.source_commit_sha }}
- name: setup node
uses: actions/setup-node@v5
with:
node-version: lts/*
cache: "npm"
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: cache cargo
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri
- name: install npm dependencies
run: npm install
- name: tauri build (compile check only — no sign, no upload)
shell: bash
env:
VITE_LASTFM_API_KEY: ${{ secrets.VITE_LASTFM_API_KEY }}
VITE_LASTFM_API_SECRET: ${{ secrets.VITE_LASTFM_API_SECRET }}
run: |
npm run tauri:build -- --bundles nsis
generate-manifest:
if: ${{ inputs.build_platform_artifacts }}
needs: [create-release, build-macos-windows]
needs: [create-release, build-macos]
runs-on: ubuntu-24.04
permissions:
contents: write
+3
View File
@@ -34,6 +34,9 @@ src-tauri/target/
src-tauri/gen/
src-tauri/lcov.info
# Local Windows signing override (copy from tauri.windows.signing.example.json)
src-tauri/tauri.windows.signing.json
# Frontend test coverage
coverage/
+1 -5
View File
@@ -5,13 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
> **🛡️ A note on safety investments:** Making sure Psysonic is trusted on every OS takes real money out of my pocket — an Apple Developer Account (now active, which is why macOS builds are signed + notarized for everyone starting with this release) and a Windows code-signing certificate (ordered, currently in validation). If you'd like to help cover those costs, you can chip in at [ko-fi.com/psychotoxic](https://ko-fi.com/psychotoxic) — completely voluntary, no pressure at all. Every bit helps keep Psysonic free and safe across Windows, macOS and Linux.
>
> **⚠️ Windows users:** This is one of the last releases with an unsigned Windows installer. Until the certificate clears validation, any SmartScreen or antivirus warning on the installer is a false positive — the binary itself is safe.
> **🛡️ A note on safety investments:** Making sure Psysonic is trusted on every OS takes real money out of my pocket — an Apple Developer Account and a Windows code-signing certificate, both now active. If you'd like to help cover those costs, you can chip in at [ko-fi.com/psychotoxic](https://ko-fi.com/psychotoxic) — completely voluntary, no pressure at all. Every bit helps keep Psysonic free and safe across Windows, macOS and Linux.
>
> **🎉 macOS users:** Starting with **v1.40.0**, Psysonic is signed + notarized and can **update itself silently**. No more DMG downloading and dragging to Applications — the updater fetches the signed `.app` bundle, verifies the signature, replaces the app in place, and relaunches. Just click "Install now" when the update notification appears.
>
> **📦 Version jump 1.34.x → 1.40.0:** The 1.34.x patch series was bumped a lot as each small feature landed. 1.40.0 consolidates the last few weeks of work — macOS signing + auto-updater, the Device-Sync overhaul, theme work and contrast audits — into a single coherent release. The next major bump (2.0.0) is planned once Windows code-signing + Windows auto-updater are active as well.
## [1.47.0]
+24
View File
@@ -182,6 +182,30 @@ Build release:
npm run tauri:build
```
## Signed Windows installer (maintainer, manual)
CI builds a Windows bundle on every release as a compile check, but does not sign or publish it — the code-signing cert this project uses (Certum SimplySign Cloud OV) requires interactive OTP login and cannot be driven from a hosted runner. The signed installer that ships in a release is therefore produced locally by the maintainer.
`src-tauri/tauri.conf.json` intentionally does **not** pin a `signCommand`, so a regular `npm run tauri:build` works for everyone building from source (just produces an unsigned installer). Signing is opt-in via a separate override config:
1. Copy `src-tauri/tauri.windows.signing.example.json` to `src-tauri/tauri.windows.signing.json` (gitignored) and fill in your local `signtool` path, timestamp URL and cert SHA1 thumbprint. The object form (`{ "cmd": ..., "args": [...] }`) is required — Tauri's string form splits on whitespace and breaks if the `signtool` path contains spaces.
2. Make the cert available. For SimplySign, start **SimplySign Desktop** and complete OTP login so the cert shows up under `Cert:\CurrentUser\My`.
3. Build with the override merged in:
```bash
npm run tauri:build:signed-win
```
That's a shortcut for `npm run tauri:build -- --bundles nsis --config src-tauri/tauri.windows.signing.json`. `--bundles nsis` is required because Tauri's default would also build an MSI, which rejects the `-dev` pre-release identifier. `signtool` is invoked for the app `.exe`, every NSIS plugin DLL, and the final installer — all come out signed in one pass.
4. Verify the signed installer:
```powershell
signtool verify /pa /v "src-tauri\target\release\bundle\nsis\Psysonic_*-setup.exe"
```
Note: `src-tauri\target\release\psysonic.exe` ends up unsigned on disk — Tauri rewrites that file as a build artifact *after* signing. The signed copy is the one packed into the installer (extract with 7-Zip if you need to verify it directly).
5. Upload the signed `*-setup.exe` to the GitHub release.
---
# Privacy
+1
View File
@@ -10,6 +10,7 @@
"tauri": "tauri",
"tauri:dev": "tauri dev",
"tauri:build": "tauri build",
"tauri:build:signed-win": "tauri build --bundles nsis --config src-tauri/tauri.windows.signing.json",
"test": "vitest run && npm run check:css-imports",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage && npm run check:css-imports"
@@ -0,0 +1,18 @@
{
"$schema": "https://schema.tauri.app/config/2",
"bundle": {
"windows": {
"signCommand": {
"cmd": "REPLACE_WITH_FULL_PATH_TO_SIGNTOOL_EXE",
"args": [
"sign",
"/tr", "REPLACE_WITH_TIMESTAMP_URL",
"/td", "sha256",
"/fd", "sha256",
"/sha1", "REPLACE_WITH_CERT_THUMBPRINT_HEX",
"%1"
]
}
}
}
}