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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The two Windows files differ only in that one installs and one does not — `-se

> After a direct `.dmg` (macOS), `*-setup.exe` (Windows NSIS) or `.AppImage` (Linux) install, Markpad self-updates from GitHub releases via the in-app *Check for Updates…* entry (macOS app menu, or Settings elsewhere). Chocolatey and Snap keep Markpad current through those package managers instead.
>
> **`.deb` and `.rpm` are one-time installs.** `tauri-plugin-updater` cannot replace a package-managed install, and there is no apt or dnf repository to update from — upgrading means downloading a newer package from the releases page. *Check for Updates…* will report that a newer version exists but cannot install it ([#570](https://github.com/sftwrdotdev/Markpad/issues/570)).
> **`.deb` and `.rpm` are one-time installs.** `tauri-plugin-updater` cannot replace a package-managed install, and there is no apt or dnf repository to update from — upgrading means downloading a newer package from the releases page. *Check for Updates…* recognises a package-managed install and tells you so.

## What Markpad renders

Expand Down
4 changes: 3 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ sudo snap install markpad

两个 Windows 文件的区别只在装不装:`-setup.exe` 会把 Markpad 装进 Program Files 和开始菜单,不带 `-setup` 的那个放哪儿就在哪儿运行。

> 通过 `.dmg`(macOS)、`*-setup.exe`(Windows NSIS)或 `.AppImage`(Linux)直接安装之后,Markpad 会通过应用内的 *检查更新…*(macOS 在应用菜单,其它平台在设置里)从 GitHub 发行版自更新。Snap、Chocolatey、`.deb` 和 `.rpm` 的用户请继续通过各自的分发渠道更新。
> 通过 `.dmg`(macOS)、`*-setup.exe`(Windows NSIS)或 `.AppImage`(Linux)直接安装之后,Markpad 会通过应用内的 *检查更新…*(macOS 在应用菜单,其它平台在设置里)从 GitHub 发行版自更新。Snap 和 Chocolatey 的更新由这两个包管理器负责。
>
> **`.deb` 和 `.rpm` 是一次性安装。** `tauri-plugin-updater` 替换不了由包管理器装上的文件,也没有 apt 或 dnf 源可以更新 —— 升级要去发行页面下载新的安装包。*检查更新…* 会认出这类安装并直接告诉你。

## Markpad 能渲染什么

Expand Down
32 changes: 13 additions & 19 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The build workflow reads both at signing time on macOS, Windows, and Linux runne

### 3. Send the public key content

Send the **single-line content** of `~/.tauri/markpad-updater.key.pub` (no comments, no header lines) to the developer who'll commit it to `src-tauri/tauri.conf.json` under `plugins.updater.pubkey`. This already happened for the current keypair — the committed value is the live public key, not a placeholder — so steps 1–3 are kept as history for anyone who ever has to redo the setup. While the field held a placeholder, auto-update was inert: the app surfaced a clean error state instead of contacting the update server.
Send the **single-line content** of `~/.tauri/markpad-updater.key.pub` (no comments, no header lines) to the developer who'll commit it to `src-tauri/tauri.conf.json` under `plugins.updater.pubkey`. The committed value is the live public keysteps 1–3 are here for whoever has to redo the setup, not for the next release.

### 4. CRITICAL: the pubkey is permanent

Expand All @@ -56,11 +56,13 @@ So: **do not create a repository named `Markpad` under `alecdotdev`, do not fork

The failure is quiet and unfixable from here: `latest.json` 404s, the updater reports no update available, and users on old versions simply stop being offered new ones. It is not a code-execution risk — the pinned `pubkey` means whoever serves that URL cannot produce a signature that installs.

**`build.yml` checks this before creating a release.** It fetches that URL and asserts the feed's download URLs still name this repository, so it tests what actually matters rather than whether a repository exists at the old location — occupying it while serving a correct feed would pass, correctly. A network failure warns instead of blocking.
**`build.yml` checks this before creating a release.** It fetches that URL and asserts the feed's download URLs still name this repository. A network failure warns instead of blocking.

## Per-release workflow

The workflow uses `npm ci`, so its installed dependency graph is exactly the committed lockfile. Do not replace it with `npm install` in release jobs. The same applies to [`snapcraft.yaml`](snapcraft.yaml), which builds the snap outside GitHub Actions; `scripts/releaseWorkflow.test.ts` guards both.
The workflow uses `npm ci`, so its installed dependency graph is exactly the committed lockfile. Do not replace it with `npm install` in release jobs. `scripts/releaseWorkflow.test.ts` guards that.

[`snapcraft.yaml`](snapcraft.yaml) builds nothing. It packages the `.deb` the release already shipped (`plugin: dump`, `source-type: deb`), so the snap carries the same binary as the `.deb` and the AppImage. The same test asserts it is packaging rather than building.

1. **Bump the version:**
```bash
Expand All @@ -71,8 +73,7 @@ The workflow uses `npm ci`, so its installed dependency graph is exactly the com
`[package].version`, and the `Markpad` entry in
[`src-tauri/Cargo.lock`](src-tauri/Cargo.lock). The lock is the one that gets
forgotten by hand: nothing in the editing loop reads it, so a bump without it
lands green and stays wrong until someone's `cargo build` rewrites the line.
That is how the 2.7.2/2.7.3 skew was found, one release after it shipped.
lands green and stays wrong.

It stops there. Committing, tagging and dispatching stay below, on purpose.
2. **Commit, tag, push:**
Expand All @@ -84,6 +85,9 @@ The workflow uses `npm ci`, so its installed dependency graph is exactly the com
3. **Trigger the workflow:**
- GitHub UI: Actions → "Build and Release" → Run workflow → master
- Or CLI: `gh workflow run build.yml --ref master`

Only one release build runs at a time — a second dispatch queues behind the
first instead of racing it to the same draft.
4. **Wait** ~30 min for matrix builds to finish, plus ~2 min for `generate-update-feed`.
5. **Open the draft release** on the [Releases page](https://github.com/sftwrdotdev/Markpad/releases). Verify the assets:
- **macOS**: `*.dmg`, `*.app.tar.gz`, `*.app.tar.gz.sig`
Expand All @@ -92,17 +96,7 @@ The workflow uses `npm ci`, so its installed dependency graph is exactly the com
- **Linux**: `*.deb`, `*.rpm`, `*.AppImage`, `*.AppImage.sig`
- **Update feed**: `latest.json` (one entry per successfully built platform)
6. **Click "Publish release"** — this is the gate. It activates auto-update for all clients pointing at `releases/latest/download/latest.json`, **and** it starts [`publish-packages.yml`](.github/workflows/publish-packages.yml), which pushes to Chocolatey and the Snap Store.
7. **Watch `Publish Packages` finish.** Two independent jobs; either can fail without affecting the release that already went out. Re-run the failed job after fixing, or run the workflow by hand with the tag as input.

### Why package managers publish after the release, not during the build

Chocolatey and the Snap Store used to be pushed from inside `build.yml`'s platform matrix, so an irreversible external side effect happened *before* anything decided whether a release existed.

That is not hypothetical. Chocolatey's `markpad-app` 2.7.2 was published at 15:37 UTC on 2026-08-07 by run `31192564528` — a run that then failed on Linux and produced no release. The release users actually got came out of a different run three hours later. A Chocolatey version cannot be un-pushed.

Both steps also carried `continue-on-error: true`, which turned a dead channel into a green check: the snap build failed from v2.6.11 onward and the Snap Store went on serving 2.6.11 for three months and six versions, while every release told people to `sudo snap install markpad`. Neither job swallows a failure now. `scripts/releaseWorkflow.test.ts` holds both properties.

`publish-packages.yml` also takes `workflow_dispatch` with a tag, so it can be exercised against an already-published release without cutting a new one — worth doing after any change to `snapcraft.yaml` or the Chocolatey packaging, since neither is reachable from a pull request.
7. **Watch `Publish Packages` finish.** Two independent jobs, neither swallowing a failure; either can fail without affecting the release that already went out. Fix, then re-run it with the tag as `workflow_dispatch` input — that path also works against an already-published tag, which is the only way to exercise `snapcraft.yaml` or the Chocolatey packaging without cutting a release, since neither is reachable from a pull request.

## First auto-update-capable release

Expand All @@ -116,7 +110,7 @@ Mention this clearly in the release notes for the first auto-update-capable vers

- **macOS** uses one universal binary (`darwin-aarch64` + `darwin-x86_64` share the same `.app.tar.gz` and signature).
- **Windows** uses NSIS — the auto-updater downloads `*-setup.exe` (verified by `*-setup.exe.sig`) and runs it in `passive` install mode. The existing raw portable `.exe` distribution path is preserved alongside, so users who download the portable `.exe` directly continue to work; only the auto-updater path uses the NSIS installer.
- **Linux**: only `AppImage` users get auto-updates — `tauri-plugin-updater` doesn't support `.deb` or `.rpm`, and there is no apt or dnf repository either. `.deb` and `.rpm` are therefore one-time installs: those users upgrade by downloading a newer package. *Check for Updates…* still offers them the update and then fails to install it, because `__TAURI_BUNDLE_TYPE` is not patched into the Linux binary and every Linux package therefore takes the AppImage install path — see #570. This is stated in the README as well; if a repository is ever published, both change together.
- **Linux**: only `AppImage` users get auto-updates — `tauri-plugin-updater` doesn't support `.deb` or `.rpm`, and there is no apt or dnf repository either. `.deb` and `.rpm` are therefore one-time installs: those users upgrade by downloading a newer package, and the app's *Check for Updates…* tells them so rather than offering one. This is stated in the README as well; if a repository is ever published, both change together.
- **Snap / Chocolatey**: independent distribution channels, published by `publish-packages.yml` after the release is published. Their update mechanisms are unaffected. The Chocolatey package wraps the release's own `Markpad_<version>_x64.exe` rather than a second build, which is what `packaging/choco/tools/VERIFICATION.txt` promises.

## Troubleshooting
Expand All @@ -128,8 +122,8 @@ Mention this clearly in the release notes for the first auto-update-capable vers
| `latest.json` missing entirely | The `generate-update-feed` job didn't run — usually because no `*.sig` files were uploaded. Check the `Upload * Artifacts` steps. |
| Users don't see the update | (1) Did you click *Publish release*? Drafts aren't visible to clients. (2) Is the user on a version older than the first auto-update-capable release? They need a one-time manual reinstall. |
| Update download succeeds but install fails with signature error | Pubkey mismatch — the Secrets and `tauri.conf.json` `pubkey` belong to different keypairs. |
| `Strip host-coupled libraries from AppImage` fails | Run [`scripts/strip-appimage.sh`](scripts/strip-appimage.sh) locally against the AppImage from the draft release — it needs no signing key. It failed in two of the three v2.7.2 attempts, once because `signer sign` had a stray flag and once because it was reading the deprecated `TAURI_PRIVATE_KEY` names on a CLI too old to accept the current ones. |
| `Publish Packages` / snap job fails | Read the snapcraft error rather than re-running: `Environment validation failed for part 'markpad'` means the `rust-deps` part in `snapcraft.yaml` is gone or renamed. Fix, then re-run the workflow with the tag as `workflow_dispatch` input. |
| An AppImage check fails | Three scripts run against it and the log says which: [`check-appimage-libraries.sh`](scripts/check-appimage-libraries.sh) (what it bundles), [`strip-appimage.sh`](scripts/strip-appimage.sh) (removing the host-coupled ones), [`smoke-appimage.sh`](scripts/smoke-appimage.sh) (whether it starts). All three run locally against the AppImage from the draft release; no signing key, no FUSE. |
| `Publish Packages` / snap job fails | Read the snapcraft error rather than re-running. `snapcraft.yaml` only unpacks a `.deb`, so the two live failures are: the job did not put `markpad.deb` next to it (the message names the path), or the `snapcraft` snap the runner installs changed under us — the job prints `snap list snapcraft`. Fix, then re-run with the tag as `workflow_dispatch` input. |
| `Publish Packages` / chocolatey job fails on push | A version can only be pushed to Chocolatey once. If it is already there, nothing needs doing; if it is not, check `CHOCO_API_KEY`. |

## Out of scope (not handled by this workflow)
Expand Down
18 changes: 18 additions & 0 deletions samples/markdown-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ A list item can hold anything:
- [ ] An unfinished one
- [ ] Nested, and also clickable

**The editor writes the markers.** Press `Enter` inside an item and the next line carries the same one: a bullet keeps the character it was written with, a numbered item increments, a task item arrives unticked. `Tab` and `Shift`+`Tab` change the level. `Enter` on an item with nothing in it clears the marker and leaves the list, which is how you get out.

A list can also be started from the keyboard: `Ctrl`/`Cmd` + `Shift` + `8` for bullets, `7` for numbers, `9` for a task list.

## 4. Quotes and alerts

> An ordinary blockquote.
Expand Down Expand Up @@ -260,6 +264,18 @@ An empty cell is written with two pipes — `| 1 || 3 |` — which is why the sp
|---|---|---|
| 1 || 3 |

**None of that has to be typed by hand.** With the caret in a table:

| Key | Does |
|---|---|
| `Tab` / `Shift`+`Tab` | move to the next / previous cell — `Tab` in the last one appends a row |
| `Ctrl`/`Cmd` + `Enter` | insert a row below, `Shift` for above |
| `Ctrl`/`Cmd` + `Shift` + `C` | insert a column |
| `Ctrl`/`Cmd` + `Shift` + `Backspace` | delete the column |
| `Ctrl`/`Cmd` + `Alt`/`Option` + `T` | insert a table to begin with |

Every edit reformats the table, so the pipes stay lined up — including in CJK text, where a character is two columns wide. To delete a row, delete its line. The rest of the table commands are in the command palette (`F1`).

## 7. Thematic breaks

Three or more of `-`, `*` or `_` on their own line, all the same rule:
Expand All @@ -285,6 +301,8 @@ The [CommonMark spec][spec] and the [GFM spec][gfm] disagree in about twenty pla

A link to a heading in this document: [back to the table](#what-is-supported-and-what-travels). Type `](#` in the editor and Markpad completes the headings for you.

`Ctrl`/`Cmd` + `K` inserts a link around whatever is selected.

### Wikilinks

Markpad understands Obsidian's spelling and rewrites it before rendering:
Expand Down
18 changes: 18 additions & 0 deletions samples/markdown-syntax.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ HTML 实体也认:&copy; &mdash; &hellip; &#8594; &amp;
- [ ] 未完成
- [ ] 嵌套的也能点

**标记由编辑器替你写。** 在列表项里按 `Enter`,下一行会带上同样的标记:符号列表沿用你写的那个字符,有序列表编号递增,任务项默认未勾选。`Tab` 和 `Shift`+`Tab` 换层级。在一个空的列表项上按 `Enter` 会清掉标记、离开列表——这是走出列表的方式。

列表也可以直接用键盘起头:`Ctrl`/`Cmd` + `Shift` + `8` 符号列表、`7` 有序列表、`9` 任务列表。

## 4. 引用与提示框

> 普通的引用块。
Expand Down Expand Up @@ -262,6 +266,18 @@ const nested = true;
|---|---|---|
| 1 || 3 |

**这些都不用手敲。** 光标在表格里时:

| 按键 | 作用 |
|---|---|
| `Tab` / `Shift`+`Tab` | 跳到下一个 / 上一个单元格——在最后一格按 `Tab` 会补一行 |
| `Ctrl`/`Cmd` + `Enter` | 在下方插入一行,加 `Shift` 是上方 |
| `Ctrl`/`Cmd` + `Shift` + `C` | 插入一列 |
| `Ctrl`/`Cmd` + `Shift` + `Backspace` | 删掉这一列 |
| `Ctrl`/`Cmd` + `Alt`/`Option` + `T` | 从头插入一张表 |

每次编辑都会重排整张表,竖线始终对齐——中日韩字符按两列宽算,所以中文表格也齐。要删掉一行,把那一行删掉就是。其余的表格命令在命令面板里(`F1`)。

## 7. 分隔线

`-`、`*` 或 `_` 三个以上单独成行,三种是同一条线:
Expand All @@ -287,6 +303,8 @@ ___

指向本文档某个标题的链接:[回到那张表](#支持什么以及走得出去多远)。在编辑器里输入 `](#`,Markpad 会把标题列出来给你选。

`Ctrl`/`Cmd` + `K` 给选中的文字套上链接。

### Wikilink

Markpad 认识 Obsidian 的写法,并在渲染前把它改写成标准链接:
Expand Down
8 changes: 5 additions & 3 deletions snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ parts:
# left to go wrong, because none of it is here.
#
# `markpad.deb` is put next to this file by the job that runs snapcraft:
# .github/workflows/publish-packages.yml takes it from the release being
# published, and .github/workflows/test_snap.yml from the latest release.
# Missing, snapcraft fails at pull with the path in the message.
# .github/workflows/publish-packages.yml, which takes it from the release
# being published. That is the only thing that executes this file — #601
# removed the pull-request check — so a change here is first run against a
# published tag. Missing, snapcraft fails at pull with the path in the
# message.
markpad:
plugin: dump
source: markpad.deb
Expand Down
Loading