Skip to content

feat(track): Lithe-IDEA 组织插件自动合入,组织外插件仍需审查 - #50

Merged
xiaoyumuxi merged 1 commit into
mainfrom
feat/track-org-auto-merge
Nov 4, 2026
Merged

xiaoyumuxi merged 1 commit into
mainfrom
feat/track-org-auto-merge

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

改动类型

  • 收录新插件
  • 新增版本
  • 修改插件信息
  • 撤回版本 / 下架插件(请写明原因)
  • 脚本、CI 或文档

插件

  • 插件 ID:不涉及(本 PR 不改 lithe-plugin-index.json)
  • 来源仓库:不涉及
  • 版本 / Release 链接:不涉及

改动内容

#49 让 bot 自动发现并收录 Lithe-IDEA 组织的 lithe-plugin-* 仓库,但所有追踪结果仍在同一个 PR 里等人工合并。这个 PR 把扫描按插件仓库的所有者分成两轮:repository 属于 Lithe-IDEA 组织的插件(含首次收录)校验通过后由工作流直接合入 main;其他插件仍开 PR 等维护者审查。

scripts/track-releases.mjs

  • 新增 --scope organization|external。isOrganizationEntry 按 repository 的所有者(不区分大小写)判断是否属于 Lithe-IDEA;inScope 决定一轮扫描要处理哪些条目,不传 --scope 时处理全部,行为与原来一致。
  • 原来 main 里的追踪循环抽成可测试的 trackIndex(index, { scope, onlyPlugin, request, downloadArchive, readManifests })。external 这一轮不做组织发现,所以组织外插件永远不会被自动首次收录;发现的新插件只会出现在 organization 这一轮。
  • --scope 传入未知值时退出码 2;--plugin 与 --scope 的参数值都不会被误当成索引路径。

.github/workflows/track-releases.yml

  • 一个 job 用 matrix 跑两轮(max-parallel: 1,先组织后组织外,fail-fast: false),每轮维护一个 PR:
    Lithe-IDEA 组织插件 组织外插件
    分支 bot/track-organization-releases bot/track-releases
    PR 标题 chore(index): 追踪 Lithe-IDEA 组织插件新版本 chore(index): 追踪组织外插件新版本
    合入 校验通过后工作流自动合入 维护者审查后合并
  • 组织那一轮的合入方式:开 PR 之前已经运行 validate-index.mjs --verify-archives --base(与 Validate index 对新增归档的检查相同);之后用 app token 执行 gh pr merge --squash --match-head-commit <本轮校验过的提交>(与仓库现有的 squash 历史一致;分支在校验之后被改动过,GitHub 会拒绝合并),合并后删除分支。
  • 为什么用 GitHub App:main 由规则集 “Only owners merge main” 保护。GitHub 不允许把 GitHub Actions 加入仓库规则集的绕过名单(API 返回 Actor GitHub Actions integration must be part of the ruleset source or owner organization),Lithe-IDEA 组织又禁用了 deploy key(添加时返回 Deploy keys are disabled for this repository),所以用组织自己的私有 GitHub App “Lithe Store Bot” 作为唯一的 bot 绕过者。只有组织那一轮会用 actions/create-github-app-token@v3 生成 app token;组织外那一轮仍用 STORE_BOT_TOKEN 或 GITHUB_TOKEN,写不了 main。
  • 没有配置 Lithe Store Bot(仓库变量为空时不生成 app token),或者合并失败时,只输出 ::warning::,PR 保持打开,由维护者审查合并。合并这一步只用 app token,不回退到其他 token。
  • 某一轮没有发现 main 尚未收录的版本时,自动关闭这一轮遗留的 PR(只指定一个插件的手动运行不会关闭)。
  • job 只在 main 上运行(同 Sync README),checkout 固定 ref: main:组织外那一轮要从组织那一轮刚更新过的 main 开始;从其他分支手动启动时不会用新工作流配旧脚本而误合入组织外插件。
  • PR 的查找改为 gh pr list --head <分支> --state open 取编号,避免同名分支有已合并的旧 PR 时找错。
  • PR 描述按范围说明合入方式;参数改用 bash 数组传递(shellcheck 无告警)。
  • 用 app token 开的 PR 会触发 Validate index;合并到 main 也会触发 main 上的 Validate index 和 Sync README,README 总览已在 PR 里重新生成,所以不会再产生同步 PR。

文档

  • docs/maintainers.md:两轮扫描的范围、分支、合入方式对照表;自动合入的三个步骤和失败时的回退;信任边界(在组织插件仓库能发 Release、或能在组织里建公开 lithe-plugin-* 仓库的人,都能不经 Store 审查发布到 Store;组织允许成员创建公开仓库时,每个成员都在这个范围内);“需要的仓库设置”改为 Lithe Store Bot、STORE_BOT_APP_CLIENT_ID、STORE_BOT_APP_PRIVATE_KEY、规则集绕过名单的真实配置,删掉原来与实际不符的“分支保护要求 Validate 与 CODEOWNERS 审查”;审查清单注明组织插件的 bot PR 不走人工清单,首次收录的组织插件合入后由维护者补 icon、中文简介并检查 description/tags。
  • docs/publishing.md:首次收录和发布新版本两节说明组织插件自动合入、组织外插件由维护者审查。
  • CONTRIBUTING.md:任务表、track-releases.mjs 与工作流说明同步更新。

测试(scripts/store.test.mjs)

  • isOrganizationEntry 对大小写和末尾斜杠的判断。
  • 同一份索引(一个组织插件、一个组织外插件,各有一个新 Release):organization 只追踪组织插件并做组织发现;external 只请求组织外插件的 Release,不请求组织仓库列表,newPlugins 为空;不传 scope 时两者都追踪。断言每轮实际发出的 GitHub 请求,确认不会跨范围。

合并前需要的仓库设置

需要组织管理员运行一次配置脚本(GitHub App manifest 流程):浏览器打开预填好的“创建 GitHub App”页面(私有、不接收 webhook、只有 Contents 与 Pull requests 读写),点 Create 后脚本把 Client ID 存为仓库变量 STORE_BOT_APP_CLIENT_ID、私钥直接存为 secret STORE_BOT_APP_PRIVATE_KEY(不落盘);接着在安装页只选 Lithe-store;脚本确认 App 能访问 Lithe-store 后,把它加进 “Only owners merge main” 的绕过名单。没有配置时,组织那一轮只开 PR 并给出警告,不会报错,所以先合并这个 PR、后做设置也可以。

绕过名单按 App ID 指定,只放行 Lithe Store Bot,不放行其他 App 或 deploy key。删除仓库变量 STORE_BOT_APP_CLIENT_ID 或卸载这个 App 就会停用自动合入。

验证

  • node --test scripts/store.test.mjs:52 通过,0 失败。
  • node scripts/validate-index.mjs lithe-plugin-index.json:12 个插件全部有效(本 PR 不改索引)。
  • actionlint .github/workflows/*.yml:只有两条关于 actions/create-github-app-token@v3 的误报(“缺少 app-id”“没有 client-id 输入”)。actionlint 1.7.12(当前最新)内置的是旧版元数据;v3.3.0 的 action.yml 里 client-id 是推荐输入,app-id 已废弃且不再必填。仓库 CI 不运行 actionlint。
  • 基于最新 main(已含 chore(index): 追踪插件新版本 #48 的 Lua 0.3.1),用真实 GitHub 数据分范围 dry-run:--scope organization --dry-run 没有新版本(keymap-import 只有 pre-release,被跳过);--scope external --dry-run 输出 io.github.fxrayhughes.mise@0.1.0 (v0.1.0)。合并后下一轮扫描会在 bot/track-releases 开一个组织外 PR 收录 mise 0.1.0,等待审查。

自检

  • 我是该插件的作者或维护者(或已获得授权)(不涉及具体插件)
  • plugin.json 的 vendor.signatureRequirement 为 "none",ID 不在 dev.lithe.*(自动合入同样经过这项校验)
  • 已在本地运行 node scripts/validate-index.mjs --verify-archives(本 PR 不改索引,没有新包需要校验)
  • 插件要运行的程序都已在 plugin.json 中声明,并在仓库 README 中说明(不涉及)
  • 没有修改已发布版本的 downloadURL / sha256,没有删除历史版本(撤回除外)

Track plugin releases now runs once per scope. The organization scope covers
plugins whose repository belongs to Lithe-IDEA, including first listings, and
fast-forwards main with the STORE_BOT_DEPLOY_KEY deploy key after the archives
are verified. The external scope covers every other plugin, never receives the
key, and keeps its pull request open for maintainer review. A scope without new
versions closes its leftover pull request, and the job only runs from main.
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review November 4, 2026 15:14
@xiaoyumuxi
xiaoyumuxi merged commit 6060585 into main Nov 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant