Automatisch 中 Ghost 触发器实战:New Post Published 的接入原理与流程配置
【免费下载链接】automatischThe open source Zapier alternative. Build workflow automation without spending time and money.项目地址: https://gitcode.com/GitHub_Trending/au/automatisch
本文围绕 Automatisch 对 Ghost(开源博客平台)的官方触发器「New post published」展开,讲解该 Webhook 触发器的能力边界、连接配置、底层实现原理,以及如何在一个自动化流程中订阅「新文章发布」事件并消费其数据负载。读完本文,你将掌握在 Automatisch 中为 Ghost 创建连接、配置流程、启用/停用该触发器的完整方法,并理解其背后基于 Ghost Admin API Webhook 的事件订阅机制。
Ghost 触发器一览:当前版本只有一个事件
在 Automatisch 的 Ghost 应用中,官方目前提供的触发器记录在 packages/docs/pages/apps/ghost/triggers.md 中,内容非常聚焦——当前仅有一个:
| 触发器名称 | 触发条件 |
|---|---|
| New post published | 当一篇新文章(post)发布时触发 |
该触发器的类型为webhook(而非轮询),意味着 Automatisch 不会定时去抓取 Ghost 的接口,而是由 Ghost 在文章发布事件发生时主动把数据推送到 Automatisch 生成的 Webhook 地址上。这在事件及时性、请求开销两方面都优于轮询方案。
在源码层面,触发器注册于 packages/backend/src/apps/ghost/triggers/index.js:
import newPostPublished from './new-post-published/index.js'; export default [newPostPublished];而应用(app)本身的声明位于 packages/backend/src/apps/ghost/index.js:
export default defineApp({ name: 'Ghost', key: 'ghost', baseUrl: 'https://ghost.org', apiBaseUrl: '', iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg', authDocUrl: '{DOCS_URL}/apps/ghost/connection', primaryColor: '#15171A', supportsConnections: true, beforeRequest: [setBaseUrl, addAuthHeader], auth, triggers, });从这里可以看到 Ghost 应用的几个关键事实:它通过supportsConnections: true支持连接(凭据)管理;所有出站请求都会经过setBaseUrl与addAuthHeader两个前置钩子统一处理 URL 与鉴权头。
前置条件:先建立 Ghost 连接
在使用「New post published」触发器之前,必须先在 Automatisch 中创建一条 Ghost 连接。官方操作指引记录在 packages/docs/pages/apps/ghost/connection.md,步骤如下:
- 登录你的 Ghost 后台(Ghost Admin panel)。
- 点击Integrations(集成)按钮。
- 点击Add custom integration(添加自定义集成),创建一个 Admin API Key(管理 API 密钥)。
- 在 Automatisch 的Admin API Key字段中填入该密钥。
- 在 Automatisch 的Instance URL(实例地址)字段中填入你的 Ghost API URL(例如
https://your-blog.example.com)。 - 点击Submit提交。
- 连接建立成功后,即可在流程中开始使用该连接。
两个必填字段的源码视角
连接表单定义在 packages/backend/src/apps/ghost/auth/index.js,包含两个required: true的字段:
- Instance URL(
instanceUrl,string):你的 Ghost 站点地址; - Admin API Key(
apiKey,string):由 Ghost 自定义集成生成的 Admin API 密钥。
这两个字段的实际作用在请求钩子中体现得淋漓尽致。
Instance URL 如何变成 API 地址
packages/backend/src/apps/ghost/common/set-base-url.js 会在每次请求发出前拼接基础 URL:
const setBaseUrl = ($, requestConfig) => { const instanceUrl = $.auth.data.instanceUrl; if (instanceUrl) { requestConfig.baseURL = `${instanceUrl}/ghost/api`; } return requestConfig; };即最终所有 API 请求都会被定向到<instanceUrl>/ghost/api之下,配合后续的/admin/webhooks/、/admin/site/等路径使用。
Admin API Key 如何完成鉴权
Ghost 的 Admin API Key 形如{id}:{secret}。鉴权逻辑位于 packages/backend/src/apps/ghost/common/add-auth-header.js:
const addAuthHeader = ($, requestConfig) => { const key = $.auth.data?.apiKey; if (key) { const [id, secret] = key.split(':'); const token = jwt.sign({}, Buffer.from(secret, 'hex'), { keyid: id, algorithm: 'HS256', expiresIn: '1h', audience: `/admin/`, }); requestConfig.headers.Authorization = `Ghost ${token}`; } return requestConfig; };可以看到,Automatisch 用:切分密钥的id与secret,以 HS256 算法签发一个1 小时有效、audience为/admin/的 JWT,并以Authorization: Ghost <token>的形式附加到请求头。这完全遵循 Ghost Admin API 的官方鉴权规范,因此任何符合该规范的 Ghost 实例(包括自托管 Ghost)都能接入。
连接验证的底层逻辑
提交连接时,Automatisch 会调用 packages/backend/src/apps/ghost/auth/verify-credentials.js 做连通性校验:
const verifyCredentials = async ($) => { const site = await $.http.get('/admin/site/'); const screenName = [site.data.site.title, site.data.site.url] .filter(Boolean) .join(' @ '); await $.auth.set({ screenName }); await $.http.get('/admin/pages/'); };它会请求/admin/site/读取站点标题与地址,拼成连接的显示名称(screenName),再请求/admin/pages/确认管理接口可用。两个请求都成功,连接才会被判定为有效;之后每次校验(is-still-verified.js)会重跑同一套验证。
New Post Published 触发器的实现拆解
该触发器的完整实现在 packages/backend/src/apps/ghost/triggers/new-post-published/index.js,通过defineTrigger声明,核心信息如下:
export default defineTrigger({ name: 'New post published', key: 'newPostPublished', type: 'webhook', description: 'Triggers when a new post is published.', ... });name:界面展示名「New post published」;key:内部唯一标识newPostPublished;type:webhook,说明该触发器由外部事件驱动;description:与文档一致——当一篇新文章发布时触发。
registerHook:如何订阅 Ghost 的 post.published 事件
Webhook 类型触发器的关键步骤是「注册回调」。当你在 Automatisch 中为一个流程启用该触发器时,会执行registerHook:
async registerHook($) { const payload = { webhooks: [ { event: 'post.published', target_url: $.webhookUrl, name: `Flow ID: ${$.flow.id}`, }, ], }; const response = await $.http.post('/admin/webhooks/', payload); const id = response.data.webhooks[0].id; await $.flow.setRemoteWebhookId(id); }其工作流程是:
- 向 Ghost Admin API 的
/admin/webhooks/端点 POST 一条 webhook 订阅; - 订阅的
event为post.published(文章发布事件); target_url指向 Automatisch 为该流程动态生成的$.webhookUrl;- 以
Flow ID: <流程ID>作为 webhook 名称,便于在 Ghost 后台识别来源; - 将 Ghost 返回的 webhook 记录 ID 保存为
remoteWebhookId,供后续注销时使用。
run:收到事件后如何产出数据
当 Ghost 命中post.published并回调 Webhook 地址时,触发器的run方法会被执行:
async run($) { const dataItem = { raw: $.request.body, meta: { internalId: Crypto.randomUUID(), }, }; $.pushTriggerItem(dataItem); }它把 Ghost 推送的请求体($.request.body,即新文章的结构化数据)包装成一条触发数据项,并生成一个随机的internalId用于执行记录去重/追踪,随后通过$.pushTriggerItem推入流程引擎。后续所有步骤(例如把新文章标题同步到其他应用)都可以引用这批输出数据。
testRun:无事件时如何测试
为了在没有真实新文章时也能验证流程,testRun会复用最近一次执行步骤的数据:
async testRun($) { const lastExecutionStep = await $.getLastExecutionStep(); if (!isEmpty(lastExecutionStep?.dataOut)) { $.pushTriggerItem({ raw: lastExecutionStep.dataOut, meta: { internalId: '' }, }); } }也就是说,只要流程此前成功跑过一次,测试运行就能直接取用上次的dataOut作为模拟输入;若从未执行过,则测试不会产生数据项。
unregisterHook:停用流程时的清理
当你停用或删除该流程时,unregisterHook会调用 Ghost 删除对应的远端 webhook:
async unregisterHook($) { await $.http.delete(`/admin/webhooks/${$.flow.remoteWebhookId}/`); }这一对「注册/注销」保证了远程订阅与流程生命周期严格同步,避免 Ghost 后台残留失效的 webhook。
在 Automatisch 中配置使用该触发器
把以上原理落到实际操作上,推荐步骤如下:
- 进入 Automatisch 的Flows页面,创建一个新流程;
- 在「Choose an app and event」中选择Ghost;
- 事件(event)列表中选择New post published;
- 在连接(connection)下拉中选择之前创建的 Ghost 连接;若尚未创建,可在该步骤内直接跳转创建;
- 保存并启用流程——启用时 Automatisch 会向你的 Ghost 实例注册
post.published的 webhook; - 到 Ghost 后台发布一篇文章,返回 Automatisch 的Executions页面查看本次执行,触发器的输出即为该文章的数据负载;
- 可以再串联任意后续步骤(如发送通知、写入其他应用),并在流程中使用触发器输出的字段。
需要留意:触发器的输出结构直接取决于 Ghost 推送的post.published事件负载(包括文章标题、URL、作者等元数据),具体字段以你的 Ghost 版本实际返回为准。若你的流程曾执行成功,也可以在编辑器中点击测试(test run)来复用最近一次数据预览输出结构。
常见问题与排查方向
- 连接验证失败:确认
Instance URL是站点根地址(不要带上/ghost/api),且Admin API Key是完整的{id}:{secret}形式;验证逻辑会依次请求/admin/site/与/admin/pages/,任一失败都会导致校验不通过。 - 发布文章后流程未触发:进入 Ghost 后台的Integrations → 对应自定义集成,检查是否存在名为
Flow ID: xxx的 webhook,并核对target_url是否与 Automatisch 为该流程生成的回调地址一致;若不一致,尝试停用再重新启用流程,强制重新注册。 - 停用流程后 Ghost 后台仍有残留 webhook:正常停用流程会调用
unregisterHook删除远端记录;若发现残留,通常是流程被强制中断所致,可在 Ghost 后台手动删除该 webhook,或重新启用再停用一次以触发清理逻辑。 - 鉴权相关报错(401):Admin API Key 生成的 JWT 有效期为 1 小时且
audience固定为/admin/,若你的 Ghost 实例版本较旧或开启了自定义鉴权策略,需要确认其与 HS256/JWT 方案兼容。
小结
Automatisch 的 Ghost 应用虽小,却是一个结构非常完整的 Webhook 触发器示例:通过setBaseUrl/addAuthHeader两个钩子完成 API 地址与 JWT 鉴权,通过registerHook订阅post.published事件,再由run消费回调负载、unregisterHook做生命周期清理。掌握「New post published」这一个触发器的接入与排查,也就同时理解了 Automatisch 中所有 Webhook 类触发器(如各类「当新内容发布/创建时」场景)的统一工作模型。
如果你想深入了解触发器的通用定义规范,可以继续阅读 define-trigger.js 与 define-app.js;而 Ghost 应用的连接接入细节,可回看 connection.md 与 auth/index.js。
【免费下载链接】automatischThe open source Zapier alternative. Build workflow automation without spending time and money.项目地址: https://gitcode.com/GitHub_Trending/au/automatisch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考