
TREK 插件发布完全指南从 GitHub 仓库到官方注册表的完整流水线【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK插件是 TREK 生态的扩展单元而发布则是把它们交给全世界 TREK 实例的方式。本文基于 TREK 仓库的官方文档wiki/Plugin-Publishing.md与trek-plugin-sdk的真实源码系统讲解 TREK 插件从本地开发、离线校验、打包、创建 GitHub Release、生成注册表条目到提交 PR 的完整发布流水线——你只需维护一个公开 GitHub 仓库和一行publish命令其余全部由 SDK 自动完成。读完本文你将掌握trek-pluginCLI 的五个发布步骤、所有离线/网络检查闸门、签名机制与更新策略能够独立发布一个可被发现、可被更新、可被验证的 TREK 插件。TREK 插件的分发不走传统的上传服务器模式它基于一个静态注册表——TREK-Plugins GitHub 仓库。没有上传服务器没有账户体系。插件作者把代码托管在自己的公开 GitHub 仓库把构建好的plugin.zip挂到 Release 上再通过一个 Pull Request 把条目登记进注册表。trek-plugin-sdk包内置的trek-pluginCLI 几乎承包了所有机械性工作——你几乎不需要手写 hash、大小、commit 或任何 JSON 字段。一、发布模型静态注册表 不可变 Release理解 TREK 插件发布先要理解它的两条根本约束GitHub Release 实质上是不可变的。注册表为每个版本的插件固定记录其 sha256一旦你覆盖已发布的 Release 字节就会破坏所有已安装该版本实例的校验和。这正是publish命令中步骤顺序的由来下文详述。注册表只存放元数据。TREK 实例从你的 GitHub Release 下载plugin.zip用注册表条目中的sha256和可选签名验证字节后再安装。注册表本身registry/plugins/id.json只是这些元数据的集合。你唯一需要的外部依赖是git和一个已认证的ghGitHub CLI。SDK 内部的 fork、release 创建、PR 提交全部通过gh完成见 plugin-sdk/src/cli/submit.ts 中的gh(repo,fork, ...)、gh(pr,create, ...)等调用。二、一步发布publish的五个步骤与顺序哲学最简单的发布路径是单条命令npx trek-plugin-sdk publish --repo you/trek-plugin-flight-tracker --tag v1.0.0publish按严格顺序执行整个发布流程共五步对应源码 plugin-sdk/src/cli/publish.ts 中[1/5]到[5/5]的日志标记check—— 在本地跑全部注册表闸门pack—— 构建plugin.ziprelease—— git tag、push、用gh release create创建带附件的 GitHub Releasepreflight—— 运行需要 tag 和 Release 已存在的网络闸门submit—— 向注册表打开 PR。顺序本身就是重点。早期版本是 pack → release → preflight → submit意味着README 没写这类问题是在 GitHub Release 已创建之后才被发现——Release 不可变作者为此烧掉了v1.0.0这个 tag只能弃掉重来一个只改了 README 的v1.0.1。现在的实现把能在工作区回答的闸门全部放到第 1 步任一失败就什么都不会打包、打 tag、推送或发布修好之后可以对着同一版本号重跑。命令末尾会打印 PR 链接。在交互式终端中它会主动提议签名没有密钥时自动创建脚本和 CI 环境不会被提示需显式传--sign。两个逃生舱口--no-checks跳过第 1 步重跑时用--no-preflight跳过第 4 步重跑时用。它们只是重跑时的出口首次发布不要使用。此外publish在打出 Release 前会做签名状态断言plugin-sdk/src/cli/signing.ts 的assertSigningAllowed如果插件此前是以签名形式发布的未签名的发布会在第 1 步直接被拒绝避免在不可变的 Release 上浪费 tag。如果你希望分步手工执行releasepack → GitHub Release → entry、preflight、submit开 PR三个子命令仍然独立存在。三、第一步托管并构建你的插件插件必须放在一个公开 GitHub 仓库中约定命名trek-plugin-id。用create-trek-plugin脚手架生成项目布局npx trek-plugin-sdk create flight-tracker --type widget # integration | page | widget | trip-page一个可发布的插件仓库根目录必须包含trek-plugin.json—— 清单文件详见 Plugin Developmentpackage.json—— 必须带 CommonJS 标记type: commonjsSDK 最多只能作为 devDependencyserver/index.js—— 构建后的服务端入口必需即使是纯 UI 插件也从这里经definePlugin()加载见 plugin-sdk/src/cli/checks/offline.ts 的codeServerEntry检查client/—— 构建后的前端仅page/widget/trip-page类型需要README.md—— 填写完整且包含真实截图质量闸门很严格见下文docs/screenshot.png—— 商店卡片图必须提交到仓库。需要特别提醒create生成的项目能跑、能打包但过不了validate——README 还是模板也没有截图。这两件事只能由你自己完成。四、本地验证status与validatenpx trek-plugin-sdk status # 我在哪还差什么——永不失败 npx trek-plugin-sdk validate . # 同样的检查但失败时以非零码退出status与validate运行的是同一套注册表闸门只是深度不同plugin-sdk/src/cli/checks/index.ts 中二者共享runOfflinestatus把它们按阶段Manifest / Code / Docs / Release / Repo分组打印成清单并提示下一步该执行哪条命令用于定位因此永不失败validate是闸门本身——同样的检查、同样的退出码是脚本和 CI 应使用的形式。离线就能抓到几乎所有注册表拒绝项完整清单见 plugin-sdk/src/cli/checks/offline.tsicon不是真实的 lucide 名称——TREK 会静默回退到Blocks图标本地打字错误看不出来但 CI 会拒绝README 缺少四个必需章节中的任何一个、还残留脚手架占位符、或真实正文不足 400 个字符MIN_PROSE_CHARS 400统计时剔除标题、代码、图片、表格见 plugin-sdk/src/cli/checks/readme.ts截图不能解析为磁盘上真实存在的文件仅 README 里有链接不算文件必须存在清单声明了某个权限但 README 从未解释它每个权限字符串必须原样出现在 README 中name/description/author超出注册表长度限制或名称混用拉丁字母与西里尔/希腊同形字homoglyph 仿冒攻击description缺省会以空字符串进入条目触发注册表 schema 的 minLength 检查egress[]中的主机没有对应的http:outbound:host权限——TREK 的网络允许列表与 iframe CSP 只从http:outbound权限构建运行期从不读取egress[]因此这样的主机在运行时会被静默拦截源码注释中称其为 the egress trapname/description中出现 emojiTREK 渲染时会剥离 emojitrek版本范围无界如3.0.0无法阻止插件在从未测试过的主机版本上运行。真正需要网络的闸门只有四个且都要求 Release 已存在tag 是否解析到条目固定的 commit、已发布的工件能否下载且哈希与固定的 sha256 一致并能用你的密钥验证、插件 id 是否已被其他 GitHub 所有者绑定、以及更新是否丢弃或轮换了已发布过的签名密钥。这些都在preflightpublish的第 4 步中运行。截图的获取npm i -D playwright npx playwright install chromium # 一次性安装——不是 SDK 的依赖 npx trek-plugin-sdk shot # 加 --dark 渲染暗色主题shot会启动 dev server在与 TREK 相同的主题化沙箱框架/preview中渲染你的插件输出 1600×900 的docs/screenshot.pngplugin-sdk/src/cli/shot.ts。Playwright 约 300MB因此不是 SDK 的依赖被按需惰性加载缺少时会提示安装命令。integration类型插件没有 UI 可渲染shot帮不上忙——此时应截图你的插件所改变的 TREK 界面。务必提交截图。注册表在固定的 commit上解析它只存在于工作区、未提交的图片在 CI 中必然失败哪怕本地status是绿的。五、打包packnpx trek-plugin-sdk pack . # 生成 ./plugin.zip npx trek-plugin-sdk pack . --out dist.zip # 自定义输出路径 npx trek-plugin-sdk pack . --json # 机器可读结果pack按安装器要求的精确布局构建plugin.zip并打印手工计算麻烦的sha256和size。它拒绝打包无法加载的插件——清单损坏、缺少server/index.js、包含原生二进制——但故意不强制发布闸门没写 README、缺截图也可以打包因为打包同样是向本地 TREK 侧载sideload试用插件的方式文档只需在真正发布时齐全对应源码 plugin-sdk/src/cli/pack.ts 中blocking(runOffline(...), artifact)只取blocks: artifact的阻断项。打包只包含运行时需要的文件——trek-plugin.json、README.md、LICENSE、package.json以及server/和client/目录树——并剔除node_modules、.git、source map.map和.ts源码。它拒绝原生二进制.node、binding.gyp、prebuilds/并强制执行与安装器相同的体积上限限制项上限单文件25 MB归档总大小50 MB条目数4000docs/故意不随包发布。商店直接从固定 commit 处的仓库拉取docs/screenshot.png因此请把图片提交到 GitHub 但留在 zip 之外——pack会自动处理。pack产出的plugin.zip同时也是侧载的工件把它交给实例管理员或直接拖到Admin → Plugins即可完全绕过注册表安装——无需 PR、无需审查、无需 SHA-256/签名固定。侧载插件会被标记且永不自动更新因此下面的注册表 PR 仍是让插件可被发现、可更新的正途。更多背景见 Plugins。六、创建 GitHub Releasetag 采用vX.Y.Z格式其中X.Y.Z必须等于清单中的version并把打包好的plugin.zip作为 Release 资产上传gh release create v1.0.0 plugin.zip --repo you/trek-plugin-flight-tracker优先上传plugin.zip资产——它就是你打包时的原始字节注册表会固定其哈希。不要依赖 GitHub 自动生成的源码归档source archives它们不是安装器布局字节也不稳定。七、生成注册表条目entrynpx trek-plugin-sdk entry \ --repo you/trek-plugin-flight-tracker \ --tag v1.0.0 \ --out registry/plugins/flight-tracker.jsonentry读取你的清单和plugin.zip生成完整条目plugin-sdk/src/cli/entry.ts自动推导commitSha—— 通过git rev-parse tag^{commit}解析^{commit}会对带注释的 tag 解引用到实际 commit见resolveCommitdownloadUrl—— 由 repo、tag 和资产名拼出sha256—— 对plugin.zip的字节做 SHA-256size—— 字节数apiVersion—— 默认 1可从清单覆盖trek—— 清单中的版本范围原样照抄。trek范围是条目中唯一的兼容性字段TREK 用它闸控安装与激活。旧的minTrekVersion/maxTrekVersion已被弃用且不再生成前者只是重复了范围的下界后者是包含语义、无法表达4.0.0。注册表仍接受在trek字段出现之前发布的旧条目携带这两个字段但不会为新条目生成它们。entry会拒绝为没有可用trek范围的清单生成条目——因为 TREK 本来就会拒绝安装它。可用旗标--zip默认plugin.zip、--commit sha覆盖 commit 解析、--asset指定不同名字的 Release 资产、--merge更新场景见下文、--out写出文件。buildEntry还会把清单中的requiredAddons、pluginDependencies和operatorEgress镜像到条目仅非空时生成保持普通条目字节不变。这一点至关重要TREK 在下载工件之前就从注册表索引解析依赖条目遗漏它们会让 CI 报 manifest requiredAddons ! entry requiredAddons——而这在早期版本中确实发生过release 已创建、字节已固定之后才发现。一条命令releasenpx trek-plugin-sdk release . --repo you/trek-plugin-flight-tracker --tag v1.0.0release一步完成pack →gh release create→ entry并把条目打印到 stdout。接受--out、--notes、--commit和--merge需要已认证的ghCLI。八、Preflight需要 Release 存在的检查在打开 PR 之前先对已推送的 Release 运行注册表剩余的 CI 检查避免一次审查往返npx trek-plugin-sdk preflight --repo you/trek-plugin-flight-tracker --tag v1.0.0preflight运行validate的全部检查外加四个真正需要网络的闸门plugin-sdk/src/cli/checks/network.tstag 解析到固定的commitShanetwork.tag-resolves带注释的 tag 会被解引用到 commit 再比对该 commit 处的清单和 README 与条目一致且通过质量闸门network.manifest-at-commit、network.readme-at-commit发布的工件可下载、哈希等于固定的 sha256、不含原生二进制、能用你的密钥验证network.artifact大小允许 4096 字节的 GitHub 资产填充余量签名会做 Ed25519 校验插件 id 未被绑定到其他 GitHub 所有者network.owner-binding读取注册表的OWNERS.json且更新不会丢弃或轮换已发布的签名密钥network.signing-downgrade。在固定 commit 上重新评定清单和 README 并非与本地通过的重复作者写完 README 却忘记提交就会出现绿树红 tag——而 CI 评分的正是 tag 指向的版本。--entry file.json可检查手写条目--all检查所有版本而非仅最新版。一次全绿的 preflight 意味着 CI 也会绿。SDK 的 plugin-sdk/test/checks-parity.test.ts 专门守护这一承诺——注册表有而 SDK 没有的闸门就是假绿这是被禁止的。九、打开注册表 PR最快捷的路径——submit代劳 fork/branch/commit/PR 全程npx trek-plugin-sdk submit --repo you/trek-plugin-flight-tracker --tag v1.0.0它会 fork TREK-Plugins只 fork 一次基于当前上游main开分支写入更新时合并进registry/plugins/id.json推送并打开 PR最后打印 PR 链接plugin-sdk/src/cli/submit.ts。加--draft创建草稿 PR--registry owner/name指定镜像仓库需要已认证的gh。手工方式fork 注册表把生成的文件添加为registry/plugins/id.json向main开 PR。只添加这一个文件——dist/在合并时自动生成CI 会拒绝手工修改它。条目遵循注册表的schema/plugin-entry.schema.jsonschema/example-entry.json是标准形状。size是必填的常被遗漏commitSha、downloadUrl、sha256、trek、apiVersion以及每个版本上的nativeModules: false也都是必填项——全部由trek-plugin entry代填。CI 会拒绝trek与固定 commit 处清单不一致的条目对仍携带minTrekVersion的旧条目还会检查其下限与范围一致。十、CI 到底强制什么注册表 CI 对每个变更的registry/plugins/*.json运行scripts/validate-entry.mjs和scripts/check-readme.mjs。几乎所有规则都是你的trek-plugin.json和README.md的纯函数因此trek-plugin validate在打任何 tag 之前就能离线检查——你永远不该从 CI 那里第一次听说这些规则。条目检查validate-entry.mjsschema 合法 ·id与文件名一致且匹配 slug 模式^[a-z][a-z0-9-]{2,39}$· 首次注册时id绑定到你的 GitHub 所有者之后任何人无法改指所有权变更需要维护者覆盖· homoglyph/混合脚本名称检查 · Release tag 存在且解析到commitSha· 该 commit 处清单对齐id、version、type、apiVersion、nativeModules不得为true·下载工件的 SHA-256 与固定值一致且大小在界内 · 归档内无原生二进制· 声明http:outbound时egress[]必须存在且不能是裸*。任何唯一 slug 都可用但registry、install、rescan除外——安装加载器会拒绝它们与 admin API 路由段冲突。README 检查check-readme.mjs在固定 commit 处获取仓库根目录必须存在 · 包含What it does / Screenshots / Permissions / Setup四个章节 · 至少有一张能解析为真实图片的截图相对路径docs/screenshot.png相对该 commit 解析· 真实正文 ≥ 400 字符剔除标题/代码/图片/表格后· 无残留脚手架占位符 ·解释清单声明的每个权限。十一、出处与完整性commitSha固定了维护者审查的确切源码git tag 是可移动的sha256固定了 TREK 将要运行的确切工件字节Release 资产是可变的。TREK 安装时会将下载字节与sha256比对不匹配则拒绝安装。条目上的reviewedAt日期表示维护者查看了那个确切 commit——它不是持续保证。reviewedAt与boundOwner由 CI 在合并时维护不要自行设置。十二、签名你的 Release可选但推荐sha256证明字节是注册表担保的那些字节作者签名则额外证明字节是你签的——即使注册表被攻破也无法以你的名义分发攻击者代码。条目 schema 允许两个可选字段条目上的authorPublicKey和每个版本上的signature。TREK 离线验证签名minisign / Ed25519不依赖外部服务并在首次安装时固定你的密钥信任首次使用TOFU之后用不同密钥签名的版本会被拒绝直到管理员重新信任。最省事的方式让 SDK 代劳SDK 内置无依赖的 Ed25519 实现不需要 minisign。在终端中publish会主动提议签名解释利弊、没有密钥时自动创建、然后签名。脚本和 CI 不会被提示直接传--signnpx trek-plugin-sdk publish --repo you/repo --tag v1.2.0 --sign--sign对确切工件字节签名并同时填好authorPublicKey条目级和signature版本级。若插件此前以签名形式发布publish会在第 1 步拒绝未签名的 Release——在任何打包、打 tag、发布之前——因为 GitHub Release 不可变到第 4 步才发现问题就浪费了 tag。请备份~/.trek-plugin/signing.key——丢失它意味着你再也无法发布签名的更新。手工 minisign 方式minisign -G # 生成 minisign.key保密 minisign.pub把minisign.pub中的 base64 载荷行放入条目作为authorPublicKey跨版本稳定然后每个版本执行minisign -Sm plugin.zip # 生成 plugin.zip.minisig把plugin.zip.minisig中的 base64 行作为该版本的signature放在其sha256旁边{ id: flight-tracker, authorPublicKey: RWQ…base64 minisign public key…, versions: [{ version: 1.2.0, sha256: 3b2a…, signature: RUR…base64 .minisig payload… }] }签名是可选的而且是一扇可以晚些时候再走、但永远回不来的单向门。没有authorPublicKey/signature的条目只靠sha256安装从未签名到签名不会破坏任何人——因为在有签名版本安装之前没有任何东西被固定在 v1.4.0 才加密钥是真实可行的选择。但反过来永远不行插件一旦以签名形式发布未签名的更新会在所有已安装实例上被拒绝SIGNATURE_MISSING密钥轮换需要注册表维护者覆盖allow-key-change加每个实例的管理员重新信任。所以——随时可以签名但请把密钥备份好。十三、更新你的插件修改清单中的version提交然后用新 tag 再次运行publish——它会检测到已有条目并把新版本前插保持最新在前。手工方式重新pack打新的vX.Y.ZRelease再用--merge把新版本折叠到既有条目上npx trek-plugin-sdk entry --repo you/trek-plugin-flight-tracker --tag v1.1.0 \ --merge registry/plugins/flight-tracker.json \ --out registry/plugins/flight-tracker.json--merge前插新版本数组保持最新在前并保留条目其余部分且会校验签名一致性——签名密钥与已发布的不同、或已签名插件发未签名更新都会被拒绝见 plugin-sdk/src/cli/entry.ts 的mergePath分支。然后把更新后的文件提 PR。各实例在下一次注册表轮询时看到更新是否应用始终是管理员的显式操作若新版本申请了更多权限管理员必须重新批准——详见 Plugin Permissions。小结发布核对清单公开 GitHub 仓库仓库根目录含trek-plugin.json、package.jsonCommonJS 标记、构建后的server/index.js、需要的client/、写好的README.md、已提交的docs/screenshot.pngtrek-plugin status/validate全绿离线含 README ≥ 400 字符、四章节齐全、截图可解析、权限全部解释trek-plugin pack生成plugin.zipsha256 / size 由此得到打 tagvX.Y.Z等于清单version并gh release create上传plugin.ziptrek-plugin entry生成条目或release一步完成trek-plugin preflight验证 tag、commit、工件哈希、所有者绑定、签名状态trek-plugin submit开 PR或手工 fork PR。整个流程的核心设计是先在本地、后动远端先校验、后发布。任何能被工作区回答的问题都不该等到 GitHub Release 创建之后才发现——这既是publish五步顺序的由来也是validate/preflight/CI 三级闸门存在的意义。遵循这份指南你的插件就能以可验证、可更新、可信赖的方式进入 TREK 的官方注册表。【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考