使用 GitHub Actions 将开发者文章导入 Jekyll
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
GitHub Actions是一种在 GitHub 上创建自定义工作流的新方式。它与编程语言无关,因此无论您喜欢使用 Python、Node.js、Ruby 还是 PHP 编写,都可以。一旦在 GitHub 仓库中创建了正确的文件夹结构,GitHub 就会立即识别出新的 Action,并执行相应的操作。
(tl;dr:您现在就可以在GitHub上查看此操作。)
GitHub Actions 的功能非常丰富,即使只是简单描述一下,也需要写一整篇博客文章。
我希望创建一个 Action,用于按cron 定时任务自动将我在 DEV 上的博客文章导入到我的 Jekyll 网站。我非常喜欢在 DEV 上写作的体验,并希望继续将其作为我的主要博客平台,同时将这些数据导入到我的个人网站。
在这种情况下,最终目标是创建一个 GitHub Action,该 Action 能够:
- 每周检查一次 DEV 博客文章。
- 如果有新的博客文章,请提交一个包含生成的 Markdown 文件的 pull request,以便将文章添加到我的 Jekyll 网站。
此外,在我的使用场景中,我希望将 Jekyll 网站上的博客文章数量限制为环境变量中指定的特定数量的最新文章${NUM_OF_POSTS}。因此,我希望该操作还能执行以下操作:
- 如果有一个新的 DEV 帖子,但
${NUM_OF_POSTS}Jekyll 网站上已经存在,那么在新的拉取请求中也要删除最旧的 Jekyll 帖子。
我特意希望这个操作能从新分支发起一个拉取请求,而不仅仅是提交更改,因为我尽量遵循GitHub 的工作流程来开发新项目。我希望我的操作也能遵循这个流程。
创建操作时,我做的第一件事是添加一个action.yml包含操作基本信息的文件:
name: DEV Blog Posts To Jekyll Markdown
description: Search for new DEV blog posts and raise a PR with the post converted to Jekyll Markdown Post
runs:
using: docker
image: Dockerfile
branding:
icon: copy
color: white
具体来说,在上述文件中,我定义了操作的名称、简短描述,以及我希望它在 Docker 上运行的设置。如果我将操作发布到 GitHub Marketplace,我还指定了列表中使用的图标和颜色。
完成上述步骤后,我开始构建实际的 Action 功能。所有相关代码都位于一个index.js文件中。
首先,我设置了require语句。该操作需要以下依赖项:
const { Toolkit } = require('actions-toolkit');
const dotenv = require("dotenv");
dotenv.config();
const axios = require('axios').default;
const btoa = require('btoa');
我使用 Jason Ectovich 的actions-toolkit与 GitHub API 进行交互。我还使用dotenv管理环境变量,使用axios进行异步 API 调用,并使用btoa对作为 pull request 一部分而创建的新 Jekyll markdown 文件的内容进行 Base64 编码。
所有操作代码都封装在一个Toolkit.run()函数中。从 GitHub API 获取一些基本的仓库信息并将其存储在变量中以供后续使用后,下一步就是从DEV API获取我的帖子。这可以通过以下方式实现axios:
const getData = () => {
return axios({
method: 'get',
url: 'https://dev.to/api/articles/me?page=1&per_page=6',
headers: headers
})
};
devPosts = (await getData()).data;
目前,该devPosts变量保存着我最近发布的 DEV 帖子。
接下来,我还需要获取 Jekyll 网站_posts文件夹的内容。我使用以下工具包完成了这项工作:
posts = (await tools.github.repos.getContents({
owner,
repo,
path
})).data;
该posts变量现在保存的是我的文件夹内容_posts。
在此期间,我还将一些数据点存储在变量中,以便稍后使用:
- 关于我上一篇 Jekyll 博文的信息
- 帖子数量
_posts - 我最近发表的两篇关于 DEV 和 Jekyll 的文章的发布日期如下。
- 我最近发布的关于 DEV 和 Jekyll 的文章标题。
我还为最新的 Jekyll Markdown 文章创建文件名。我通过将 DEV 返回的数据转换成 Jekyll 文件名所使用的模式来实现这一点:
newJekyllPostFileName = `${devPostDate.split('T')[0]}-${devPostTitle.toLowerCase().split(' ').join('-')}.md`;
现在我准备检查创建新拉取请求所需的条件。我需要满足以下条件:
- DEV 的最新帖子比 Jekyll 的最新帖子更新吗?
- Jekyll 上的帖子数量是否比……更多或相等
${NUM_OF_POSTS}? - 我的仓库中是否已经存在新的工作分支?
- 如果分支已经存在,那么我想添加的新 markdown 文件也已经存在了吗?
- 该拉取请求是否已存在?
以上每个问题的答案都会改变代码的运行方式。
如果满足条件,该操作最终将创建一个拉取请求,添加一个包含以下内容的新 Markdown 文件:
fileContents = `
---
layout: defaults
modal-id: ${postsCount+1}
date: ${devPostDate}
img: ${devPostCoverImage}
alt: Cover Image
title: ${devPostTitle}
link: ${devPostURL}
---
`.trim();
我也可以把整个 DEV 帖子添加到 markdown 文件中,或者只添加一部分文本,但在我个人网站的使用场景中,我只想创建一个指向 DEV 博客文章的小型博客文章卡片。
根据 Jekyll 文件夹中当前帖子的数量_posts,拉取请求可能还会包括删除最旧的 Jekyll 帖子:
deletedPost = (await tools.github.repos.deleteFile({
owner,
repo,
path: lastPostPath,
message: 'Deleting oldest blog post from Jekyll site',
sha: lastPostSHA
}));
构建这个操作的过程对我来说是一次非常宝贵的学习经历。我知道我想在我的个人网站上保留一份最新博客文章的列表。我也知道我不想手动管理这个过程。GitHub Actions 工具让我有机会构建一个自动化工作流来帮我完成这项工作。
我💙欢迎大家贡献!如果您有任何改进或增强的想法,请告诉我。如果您想在自己的项目中使用这个操作,也请随意!我很想了解您是如何使用它的。
DEV Posts to Jekyll Markdown Action可以在GitHub上找到。
文章来源:https://dev.to/bengreenberg/import-dev-posts-to-jekyll-with-github-actions-1bni
