Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,43 @@ jobs:
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Updater artifact signing (NOT OS code-signing). Signs each bundle and
# assembles latest.json so the in-app auto-updater trusts the release.
# Create ONE repo secret: TAURI_SIGNING_PRIVATE_KEY = contents of the
# private key from `tauri signer generate`. The key has no passphrase, so
# do NOT create the PASSWORD secret (GitHub rejects empty secret values) —
# the reference below resolves to an empty string when the secret is
# absent, which is exactly "no password". Without the key the build still
# runs but produces no .sig/latest.json and auto-update will not work.
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
#
# --- OS code-signing (intentionally OFF; unsigned v1) ----------------
# Releases are unsigned today; users follow the "open anyway" flow (see
# docs/installation.md). To enable later, add the secrets below — no
# other workflow change is needed (Tauri auto-signs when they exist):
#
# macOS (Developer ID, $99/yr — Tauri auto-signs AND notarizes):
# APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
# APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
# APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
# APPLE_ID: ${{ secrets.APPLE_ID }}
# APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} # app-specific pw
# APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
#
# Windows (Azure Trusted Signing — also add a bundle.windows.signCommand
# using trusted-signing-cli in tauri.conf.json):
# AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
# AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
# AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
with:
tagName: ${{ github.event_name == 'workflow_dispatch' && inputs.releaseTag || github.ref_name }}
releaseName: Notey ${{ github.event_name == 'workflow_dispatch' && inputs.releaseTag || github.ref_name }}
releaseBody: 'See the assets below to download and install this version.'
releaseDraft: true # artifacts are unsigned (v1) — a human publishes after review
# Draft so a human reviews unsigned artifacts before publishing. NOTE:
# the updater endpoint (releases/latest/download/latest.json) only
# resolves once the draft is PUBLISHED and marked "latest" — auto-update
# goes live at publish time, not at build time.
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

_Nothing yet._
### Added
- In-app auto-updater: on startup Notey checks the GitHub Releases endpoint and
shows a banner to install the new signed build and restart
(`tauri-plugin-updater`).

### Changed
- Release workflow now signs updater artifacts and emits `latest.json`; it is also
wired (commented) for later macOS/Windows OS code-signing. Release builds remain
unsigned for now — see [docs/installation.md](docs/installation.md) for the
per-OS "open anyway" steps.

## [0.1.0] - 2026-06-17

Expand Down
35 changes: 35 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,41 @@ npx tauri build --debug --no-bundle # debug binary at src-tauri/target/debug/not
npx tauri build # release bundles for your platform
```

## Releasing

Releases are built by `.github/workflows/release.yml`, which runs
`tauri-apps/tauri-action` across five targets (macOS arm64/x64, Linux x64/arm64,
Windows x64) and uploads the bundles to a **draft** GitHub Release.

One-time setup (maintainers): create **one** repo secret under **Settings →
Secrets and variables → Actions** so the in-app updater artifacts get signed —
`TAURI_SIGNING_PRIVATE_KEY` (contents of the private key from
`npm run tauri signer generate`). The key has no passphrase, so do **not** create
a `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` secret — GitHub rejects empty secret
values, and the workflow already resolves the missing reference to an empty
string (i.e. "no password"). The matching public key lives in
`src-tauri/tauri.conf.json` under `plugins.updater.pubkey`.

To cut a release:

1. Bump the version in **all three** files, kept in lockstep: `package.json`,
`src-tauri/Cargo.toml`, and `src-tauri/tauri.conf.json`.
2. Update `CHANGELOG.md` (move **Unreleased** items under the new version).
3. Tag and push:

```sh
git tag vX.Y.Z
git push origin vX.Y.Z # triggers the Release workflow
```

4. When the workflow finishes, review the **draft** release and **publish** it
(mark it as "latest"). Publishing is what makes the updater endpoint
(`releases/latest/download/latest.json`) resolve — **in-app auto-update only
goes live once the draft is published.**

Release artifacts are currently unsigned (OS code-signing is wired but disabled;
see the comment block in `release.yml` to enable Apple/Azure signing later).

## Testing

```sh
Expand Down
34 changes: 32 additions & 2 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,38 @@ Download the artifact for your platform and install it the usual way for your OS
(open the `.dmg` on macOS, the `.AppImage`/`.deb` on Linux, or the installer on
Windows).

> Release artifacts are currently unsigned. Your OS may warn you on first launch;
> allow the app to run via your platform's standard "open anyway" flow.
### Opening an unsigned build

Release artifacts are currently **unsigned**, so your OS warns you the first time
you launch. This is expected — follow your platform's "open anyway" flow once and
the app runs normally thereafter:

- **macOS** — Gatekeeper shows *"Notey can't be opened because it is from an
unidentified developer."* Either **right-click (or Control-click) the app →
Open → Open**, or clear the quarantine flag from a terminal:

```sh
xattr -dr com.apple.quarantine /Applications/Notey.app
```

- **Windows** — SmartScreen shows *"Windows protected your PC."* Click
**More info → Run anyway**.

- **Linux** — make the AppImage executable, then run it:

```sh
chmod +x Notey_*.AppImage
./Notey_*.AppImage
```

Or install the Debian package: `sudo dpkg -i Notey_*.deb` (or
`sudo apt install ./Notey_*.deb` to pull in dependencies).

### Updates

Once installed, Notey checks for new releases on startup and shows an **in-app
banner** offering to install and restart when a newer version is published — no
manual re-download needed.

## First launch

Expand Down
25 changes: 23 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"@tauri-apps/plugin-dialog": "^2.7.1",
"@tauri-apps/plugin-global-shortcut": "^2.3.1",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-updater": "^2.10.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
Expand Down
Loading