Fnos packaging (#2524)

* feat(packaging): add fnOS FPK packaging and CI workflow

Add packaging/fnos/ shell (manifest, lifecycle cmd scripts, install/
upgrade/uninstall wizards, desktop entry, EULA) plus in-repo build
script. A release now auto-builds langbot-<tag>-fnos.fpk via
.github/workflows/build-fnos-fpk.yaml, uploaded to the release assets.

* ci(fnos): skip release upload on manual dispatch

github.event.release.tag_name is empty when triggered via
workflow_dispatch, causing 'gh release upload' to fail with
'requires at least 2 arg(s)'. Restrict the step to release events.

* ci(fnos): normalize release asset name

Strip a trailing -fnos from the tag-derived version before appending
the suffix, avoiding langbot-<v>-fnos-fnos.fpk when the tag itself
already carries -fnos.

* ci(fnos): use release tag version for auto build, manifest for manual

Auto build (release/tag) reads version from tag like other release
workflows; build.sh strips the v prefix when injecting into manifest.
Manual dispatch falls back to the version maintained in manifest.

* feat(fnos): add post-install deployment notice to install wizard

Last wizard step now informs users that first startup takes about
5-10 minutes for dependency setup before the web UI is ready.

* docs(fnos): add packaging directory README

* refactor(fnos): rename app from ai.langbot to langbot

Rename appname, desktop entry, data share, build artifacts, and all
references from ai.langbot to langbot across packaging files.

---------

Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
sheetung
2026-09-14 00:31:19 +08:00
committed by GitHub
parent cbe6844342
commit 60bb67f025
22 changed files with 1140 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
# LangBot fnOS Packaging
This directory packages LangBot as a `.fpk` app for the fnOS App Store. It is a native deployment: no Docker involved — uv creates a Python virtual environment directly on the NAS, and Node.js v22 from the fnOS App Store provides the Box sandbox and npx MCP capabilities.
## Directory Structure
```
packaging/fnos/
├── manifest # App metadata (appname/version/port/dependency declarations)
├── build.sh # One-shot build script (shared by local and CI)
├── LICENSE
├── config/
│ ├── privilege # Privilege config (run-as: root)
│ └── resource # Persistent data share declaration (langbot/data)
├── cmd/ # Lifecycle scripts (fnOS invokes them with TRIM_* env vars)
│ ├── main # Service start/stop manager (start/stop/status, owns PID/log)
│ ├── install_init # Pre-install hook
│ ├── install_callback # Post-install hook: create venv, uv sync deps, seed config.yaml port
│ ├── upgrade_init # Pre-upgrade hook
│ ├── upgrade_callback # Post-upgrade hook
│ ├── uninstall_init # Pre-uninstall hook
│ ├── uninstall_callback # Post-uninstall hook (keeps data per wizard choice)
│ ├── config_init # Pre-config-change hook
│ └── config_callback # Post-config-change hook (apply new port etc.)
├── wizard/ # Install wizards (JSON forms; values passed as wizard_* env vars)
│ ├── install # On install: Node version, web port, deployment-time notice
│ ├── upgrade # On upgrade: Node version confirmation
│ └── uninstall # On uninstall: whether to keep data
├── app/
│ ├── ui/config # Desktop entry declaration (${wizard_port} placeholder, substituted by fnOS at install)
│ ├── desktop/langbot.main.url
│ ├── langbot/ # [generated] repo source synced via rsync (includes web/dist)
│ └── bin/ # [generated] offline uv binaries (x86_64/aarch64)
├── ICON.PNG / ICON_256.PNG # [generated] derived from res/logo-blue.png
└── langbot.fpk # [generated] final artifact
```
Paths marked `[generated]` are produced by `build.sh`, ignored via `.gitignore`; everything else is a git-tracked source file.
## Building
### Locally
```bash
bash packaging/fnos/build.sh
```
Dependencies: python3 + Pillow, node + npm (or pnpm), fnpack (official fnOS packaging CLI, download from https://developer.fnnas.com/docs/cli/fnpack).
The version comes from `version=` maintained in the manifest; it can also be injected: `FPK_VERSION=4.10.10-1 bash packaging/fnos/build.sh`.
### CI
[`.github/workflows/build-fnos-fpk.yaml`](../../.github/workflows/build-fnos-fpk.yaml) triggers automatically on Release publication and uploads `langbot-<version>-fnos.fpk` to the Release; it can also be triggered manually via workflow_dispatch.
Version sources (consistent with the other release workflows):
| Trigger | Version source |
|---|---|
| Release/tag auto build | Tag name (`v4.10.10-1` → in-package `4.10.10-1`; build.sh strips the `v` prefix on injection) |
| Manual workflow_dispatch / local build | Version maintained in manifest |
## Final Artifact
`langbot.fpk` (gzip + tar archive), containing:
- `manifest` — realigned and appended with a `checksum` field by fnpack
- `app.tgz` — app payload (source, web/dist, uv binaries, entry configs)
- `cmd/`, `config/`, `wizard/` — lifecycle scripts and wizards
- `ICON.PNG`, `ICON_256.PNG`, `LICENSE`
The first startup after installation takes about 5-10 minutes to finish dependency deployment (uv venv + sync); after that the web admin UI is reachable via the desktop icon or `http://<NAS-IP>:<port>` (default port 5300).
## References
- fnOS developer docs: https://developer.fnnas.com/
- fnOS app wizard: https://developer.fnnas.com/docs/core-concepts/wizard/
- fnpack CLI: https://developer.fnnas.com/docs/cli/fnpack