GitHub Actions 可以添加运行参数。我只需要设置 filepath 和 content 两个参数,然后配合 shell 脚本就可以自动生成和提交博文到 GitHub 仓库,进而触发自动构建和发布。
GitHub Actions 提供了 REST API 来触发前面的工作流,这样我就可以通过 HTTP 请求来自动生成和发布博文。
开源服务指南数据库现在是建立在 Notion 上的,Notion 也提供了 REST API 的交互方式。所以我只需要定时扫描 Notion 数据库,获取状态刚变更为 “已发布” 的博文,提取文章内容,通过第 2 步中提到的 REST API 来触发第 1 步中提到的 GitHub Actions 即可自动生成和发布博文。这里我使用了 Cloudflare Workers 实现。
怎么监测 Notion 数据库文章状态变动呢?想要监测状态“变动”,我们需要知道变动前的状态和变动后的状态,进而需要有数据库缓存变动前的状态,能做,但麻烦。所幸,pipedream 帮我们做好了这个事情。它能够监测 Notion 数据库变动,并且触发工作流执行。
所以,最后的工作流程就是:
- Pipedream 监测开源服务指南 Notion 文章数据库变动,提取状态为“已完成”的文章,把文章 id 通过 HTTP 请求发送给 Cloudflare Workers;
- Cloudflare Workers 根据文章 id 查询文章内容,把文章路径和文章内容作为参数,发送请求给 Github Actions;
- Github Actions 把文章内容写入文章路径,提交文章源文件到 Github 仓库;
- Github Actions 监听代码提交,持续集成和发版;
嗯,云服务挺好用。
置于为什么不直接用 Pipedream 提取参数触发 Github Actions 工作流,个人主观意愿影响比较多:Pipedream 代码编写体验略差,稳定性欠佳,所以在逐步往 Cloudflare Workers 迁移。这个回头细讲。
附录:
- Github Actions 文档
- Cloudflare Workers 文档
- Pipedream 文档
- 第 1 步中提到的 Github Actions 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| name: Create Post
on: workflow_dispatch: inputs: path: description: 'File path' required: true content: description: 'File content' required: true
permissions: contents: write
jobs: create-file: runs-on: ubuntu-latest
steps: - name: Checkout repository uses: actions/checkout@v4
- name: Create Post run: | cat << EOF > ./content/post/${{ github.event.inputs.path }} ${{ github.event.inputs.content }} EOF
- name: Commit and push changes run: | git config user.name "username" git config user.email "email@osguider.com" git add ./content/post/${{ github.event.inputs.path }} git commit -m "add post: ${{ github.event.inputs.path }}" git push
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import axios from 'axios';
const filePath = 'daily/daily-01.md'; const fileContent = 'Hello World';
const owner = "osguider"; const repo = "blog"; const workflow_file = "create-post.yml"; const url = `https://api.github.com/repos/${owner}/${repo}/actions/workflows/${workflow_file}/dispatches`; const headers = { 'Authorization': `Bearer ${process.env.GITHUB_REPO_PAT_BLOG}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json' }; const data = { 'ref': 'main', 'inputs': { path: filePath; content: fileContent; }, };
axios.post(url, data, { headers: headers }) .then((response) => { console.log('GitHub Action dispatched successfully!'); }) .catch((error) => { console.log(`Failed to dispatch GitHub Action: ${error}`); });
|