2026-05-03 学习日志
今日主题
- GitHub Actions reusable workflows vs composite actions
- JetBrains Marketplace 插件上传
- Node.js 模块系统
- Promise 与跨模块健壮性
- AI Agent 通信协议对比(MCP/A2A/ACP)
新增认知
GitHub Actions reusable workflows vs composite actions
- GitHub Actions 有两种复用机制:reusable workflow 和 composite action。核心区别:composite action 嵌入调用方 job 内运行,共享 runner 和 secrets,适合纯工具类步骤;reusable workflow 是独立 job,有自己 runner,需要显式传 secrets,适合需要 checkout 代码和独立构建环境的场景。
- Composite action 相当于「菜谱给朋友,在他家厨房用他家调料做」;reusable workflow 相当于「厨子带全套家伙上门,单独开火」。判断标准:看是否需要 checkout 代码、是否需要独立运行环境。
- 两者本质都是 uses 机制引用外部仓库,跟 uses: actions/setup-java@v4 底层一样。区别在于 action 类型仓库根目录有 action.yml,引用时不用写路径;workflow 类型必须写完整路径 .github/workflows/xxx.yml。
- GitHub Actions workflow 版本规则:push/tag 事件用被 push 的 ref 上的版本,workflow_dispatch 手动触发用默认分支版本。这意味着如果把 CI 逻辑嵌在代码仓库里,tag 打到的旧 commit 会跑旧版 workflow,这就是 CI 配置和业务代码耦合的痛点。
- 解耦方案:把 CI 逻辑提取到独立 github 仓库作为 reusable workflow,业务仓库只留触发条件,用 uses 引用。跟引用 actions/setup-java 一样,区别只是自己维护。代价是多一个仓库,但对单项目来说有点 overkill。
JetBrains Marketplace 插件上传
- JetBrains Marketplace 的 HTTP upload API (POST plugins.jetbrains.com/plugin/uploadPlugin) 只需要 Bearer token,不需要签名证书。签名是 Gradle intellij-platform 插件的 publishPlugin 任务的额外要求,不是 Marketplace 本身的限制。用 curl 直接调 API 可以绕过签名步骤。
- 上传时插件 description 必须以拉丁字母开头且至少 40 字符,否则返回 HTTP 400。中文在前会触发此校验。
- curl 不加 --fail 时,即使返回 HTTP 400 也会 exit 0,GitHub Actions 会误报成功。必须加 --fail-with-body(curl 7.76+)让 HTTP 错误映射为非零退出码。
Node.js 模块系统
- .mjs 永远是 ESM,.cjs 永远是 CJS,.js 取决于最近的 package.json 的 type 字段;后缀是强制声明,不受环境影响。
- CJS 不能 require ESM(单向限制),ESM 可以 import CJS;混用时必须注意这个方向。
- ESM 的优势(tree shaking、live binding、top-level await)在 CLI 脚本场景下完全用不上,CJS 更简洁且有 __dirname,是 CLI 工具的首选。
Promise 与跨模块健壮性
- Promise 链中 .then() 回调内的同步异常不会被上层 try/catch 捕获,会变成 unhandled rejection;Node.js 15+ 会直接崩溃,链尾必须加 .catch()。
- 构造函数式错误类在跨模块 instanceof 时有失效风险:同一文件被不同路径 require 时,模块缓存 key 不同会产生两份构造函数,instanceof 判断失效。用属性标记(e.isJinaAPIError = true)替代 instanceof 可彻底规避。
AI Agent 通信协议对比(MCP/A2A/ACP)
- MCP 解决 Agent ↔ 外部工具的调用问题(Anthropic),A2A 和 ACP 解决 Agent ↔ Agent 的协作问题,三者不在同一抽象层级
- A2A(Google)是任务导向的,内置任务生命周期管理(submitted→working→completed),适合需要进度追踪的长时间协作场景
- ACP(BeeAI/Linux Foundation)是通信导向的,更像通用的消息传递基础设施,不预设任务语义,由上层应用决定协作模式
- A2A vs ACP 的分歧类比 Web 服务时代的 SOAP vs REST:一个偏重协议和流程规范,一个追求简单通用的通信管道