Releases on git.crt.fyi from a workflow: a v* tag push runs .forgejo/workflows/release.yml (tag = package.json version and every version copy, the full CI, Linux AppImage + deb and Windows NSIS on the VDS runners, privacy scan with the private terms, one Forgejo release with short CHANGELOG-summary notes, the installers and SHA256SUMS, older release entries deleted, tags kept); workflow_dispatch dry run makes a draft test-<sha> and deletes it; desktop.yml folded in, ci.yml and release.yml share .forgejo/actions/linux-setup and ci-run; tools/forgejo-release.ts (notes, upsert, prune, delete; uploads over 100 MB go to the origin because Cloudflare refuses them); desktop-release.ts upload-forgejo adds the notarized DMG and updater bundle from the Mac; docs/desktop-release.md release order

This commit is contained in:
CRTkafa 2026-10-13 07:44:17 +08:00
parent e5f148e534
commit 2590b2e828
11 changed files with 871 additions and 229 deletions

View file

@ -31,9 +31,55 @@ in `~/Desktop/storebound-dist/desktop-0.1.0` was never published, so no installe
`tauri.conf.json`, `Cargo.toml` and the app's entry in `Cargo.lock`. CI runs this check; `src-tauri/tests/d5.rs`
checks the app's copies from the Rust side.
- `bun tools/desktop-version.ts --set 0.8.0` writes a new version into package.json and all of them.
- **Release order** (one commit, one version): build and check the desktop artifacts (`mac`, `add`), `publish` them
(it refuses a folder whose version is not package.json's), then `npm publish` of the same version (CONTRIBUTING.md).
The app goes first, so `npx storebound desktop` of the new CLI finds its own version.
- **Release order** (one commit, one version): see "The release on git.crt.fyi" below. The app goes first
(`publish` refuses a folder whose version is not package.json's), then `npm publish` of the same version
(CONTRIBUTING.md), so `npx storebound desktop` of the new CLI finds its own version.
## The release on git.crt.fyi
One version tag, one Forgejo release: git.crt.fyi/CRT/storebound/releases keeps only the newest entry (older entries
are deleted after a successful release; their git tags stay). Notes are short: the CHANGELOG section's summary
paragraph (at most 4 lines), the install line and links, never the whole section. So the section's first paragraph
is the release summary: write it for that.
1. **Version and changelog** on main: `bun tools/desktop-version.ts --set 0.8.0`, a `## 0.8.0 · <date>` section
that starts with a summary paragraph, `bun run ci`, push.
2. **Tag push:** `git tag v0.8.0 && git push origin v0.8.0`. `.forgejo/workflows/release.yml` then:
- checks that the tag is `v` + package.json's version, every version copy matches (tools/desktop-version.ts) and
the CHANGELOG has the section;
- runs the full CI (`bun run ci`, the same steps as ci.yml: `.forgejo/actions/linux-setup` and `ci-run`);
- builds the AppImage + deb (Linux runner) and the NSIS installer (Windows runner), with the checks described
under "Windows and Linux" below;
- scans every artifact with the private terms (secret `FORBIDDEN_TERMS`), writes SHA256SUMS;
- creates or updates the release "storebound 0.8.0" (`tools/forgejo-release.ts upsert`: found by tag, assets of
the same name replaced, SHA256SUMS merged, read back), then deletes the older release entries
(`forgejo-release.ts prune --keep v0.8.0`).
3. **macOS on the Mac** (the DMG cannot be built or notarized on these runners): `bun tools/desktop-release.ts mac`,
then `add` of the runners' Linux / Windows files (signs them for the updater, see below), then
`bun tools/desktop-release.ts upload-forgejo --out ~/.storebound-releases/desktop/0.8.0 --yes`: the signed DMG and
the updater bundle with their `.sig` join the same release, SHA256SUMS is merged. It refuses an unsigned DMG and
a release the workflow has not made yet. Token: `FORGEJO_TOKEN`, else the git credential helper of git.crt.fyi.
4. **storebound.dev:** `bun tools/desktop-release.ts publish --out ... --yes` (below).
5. **npm:** `npm publish` of the same version: the owner's step (CONTRIBUTING.md).
Option, not set up: an npm automation token as the Actions secret `NPM_TOKEN` and a manual `npm` job in
release.yml (`needs: release`, workflow_dispatch only, `npm publish` after the Mac's upload) would let the owner
publish with one click in Forgejo instead of a terminal. The token can publish any version of the package, so it
stays off until the owner wants it.
**Dry run** (no version, nothing public): Actions > release > Run workflow with `dry` ticked (the default), or
`POST /api/v1/repos/CRT/storebound/actions/workflows/release.yml/dispatches` with
`{"ref":"main","inputs":{"dry":"on","windows":"on"}}` (over the API a boolean input is "on"; "true" counts as off).
The same jobs run on that commit; the release job makes a DRAFT `test-<sha>` with the real files, reads it back,
prints what `prune` would delete, and deletes the draft at the end (also when a step failed). `dry` off needs a `tag`
input and remakes that tag's release.
**Secrets** (repo Settings > Actions > Secrets): `RELEASE_TOKEN`, a token of CRT with scope `write:repository`
(name `storebound-release-workflow`; releases, assets, the dry run's tag) and `FORBIDDEN_TERMS`, the contents of
`forbidden-terms.txt` (never printed: hits show `x***`), and `FORGEJO_ORIGIN`, the server's IP: git.crt.fyi is
behind Cloudflare, which refuses uploads over 100 MB (the AppImage, the DMG) with a 502, so `forgejo-release.ts`
uploads assets to the origin directly (`curl --resolve`, TLS still checked for git.crt.fyi). On the Mac the same IP
is in `~/.storebound-keys/forgejo-origin`. Rotate the token: create a new one under CRT's
Settings > Applications with that scope, put it into the secret, delete the old one.
## Keys and private files (outside every repository)
@ -144,8 +190,8 @@ and choose Open Anyway (once).
## Windows and Linux (Forgejo Actions)
`.forgejo/workflows/desktop.yml` runs on a `desktop-v*` tag or by hand (workflow_dispatch; tick "windows" for the
Windows installer too: a tag push builds Linux only).
The `linux` and `windows` jobs of `.forgejo/workflows/release.yml` (a `v*` tag push, or a dry run by hand; untick
"windows" in a dry run to build Linux only).
- **Linux** (`runs-on: ubuntu-22.04`, a container): AppImage and .deb built with the path-free environment, then:
- self-tests of the extracted AppImage and the unpacked .deb;
@ -181,8 +227,8 @@ installer compare with `Get-FileHash` of `C:\storebound-target\release\bundle\ns
### Runner setup
Forgejo runs in Docker on the VDS. `.forgejo/workflows/ci.yml` (`bun run ci`, Rust tests and clippy included) runs on
every push and pull request to main; `desktop.yml` as above. Neither publishes anything (Jenkins still publishes
site/). Workflow artifacts of this public repository can be downloaded by anyone for 14 days.
every push and pull request to main; `release.yml` as above makes the Forgejo release (Jenkins still publishes
site/, and `publish` storebound.dev/desktop). Workflow artifacts of this public repository can be downloaded by anyone for 14 days.
1. **Actions in Forgejo (done).** `FORGEJO__actions__ENABLED=true` and
`FORGEJO__actions__DEFAULT_ACTIONS_URL=https://data.forgejo.org` in the compose file; the Actions unit is on for
@ -314,8 +360,8 @@ files stay where they are, because links and checksums must not change.
1. A signed, notarized macOS build from the release commit (the Developer ID certificate is on the Mac). The gates
above must pass.
2. Forgejo Actions enabled, the Linux runner registered, a `desktop-v0.1.0` tag built, `add` of the AppImage and
deb.
2. Forgejo Actions enabled, the Linux and Windows runners registered, a dry run of release.yml green, then the
`v` tag, `add` of the AppImage, deb and setup.exe from the release.
3. Windows: a runner, or ship macOS + Linux first. The page and latest.json list only what exists.
4. `publish --yes` to stable. Then open storebound.dev/#download on each OS and run `storebound desktop --download`.
5. An updater round trip: publish 0.1.1 to beta, switch a 0.1.0 install to Beta, Check for updates, Install.